用CUDA实现Bellman-Ford
最近在看CUDA,剛好有一個類似的項目,就拿來練練手。
項目地址:github.com/Sanzona/Bellman-Ford
Bellman Ford
Bellman Ford是求最短路的算法,可以處理帶有負(fù)邊的圖,也可以用來判斷負(fù)環(huán)。
算法的主要思想是:每次遍歷所有的邊并更新每條邊相鄰的點,遍歷N-1次后就可以得到源點到其他點的最短路,對于N個點的圖任意兩點的最短路徑長度不超過N-1。
CUDA
CUDA(Compute Unified Device Architecture,統(tǒng)一計算架構(gòu)),是一種由NVIDIA推出的通用并行計算架構(gòu),該架構(gòu)使GPU能夠解決復(fù)雜的計算問題。
硬件層面分為:SP(streaming processor)、SM(streaming multiprocessor)。
軟件層面分為:grid、block、thread、wrap。
streaming processor
sp是CUDA最基本的處理單元,又稱為CUDA core。
streaming multiprocessor
SM由多個SP組成,SM中包括wrap scheduler、register、shared memory等,CUDA將register和shared memory分配個SM中的threads,SM中的資源數(shù)決定了SM中active wrap的個數(shù)。
grid、block、thread、wrap
grid、block、thread、wrap是CUDA編程上的概念,方便程序設(shè)計。
每個kernel函數(shù)都會運行在GPU的一個Grid上。
Grid包含多個Blocks,每個Grid一共有三個維度。
Block包含多個threads,每個Block同樣有三個維度,Block內(nèi)部的thread可以通過shared
memory通信和同步,不同Block之間的thread互不干擾。
wrap是GPU執(zhí)行時的調(diào)度單位,wrap由32個thread組成,每個wrap在同一時刻執(zhí)行相同的指令(SIMT),wrap的切換沒有開銷,不需要保存上下文。
thread是最小的執(zhí)行單位,每個thread有自己的程序計數(shù)器和狀態(tài)寄存器。
SIMT
gpu分配多個thread執(zhí)行kernel函數(shù),這些thread以32個為一組分成多個wrap,這些wrap輪流進(jìn)入SM執(zhí)行相同過的指令。
設(shè)計思路
relaxWithGridStride():對應(yīng)Bellman-Ford的松弛操作。
updateDistanceWithGridStride():更新松弛操作的結(jié)果。
updatePredWithGridStride():在Bellman-Ford完成之后求前驅(qū)節(jié)點。
其他
在多線程更新dis數(shù)組和pred數(shù)組時,會出現(xiàn)時序競態(tài)的問題,原項目作者沒有考慮完全,我在他的基礎(chǔ)上將atomicExch()改為atomicMin()這樣可以保證多線程下dis的正確性,但是仍然不能保證pred更新的正確性,因為沒有找到合適的CUDA lock unlock的寫法,所以我把前驅(qū)節(jié)點的計算放到Bellman-Ford完成之后再進(jìn)行,同時也減少了運行的時間。
參考文獻(xiàn)
Bellman–Ford algorithm
sengorajkumar/gpu_graph_algorithms
Bellman-Ford Single Source Shortest Path Algorithm on GPU using CUDA
總結(jié)
以上是生活随笔為你收集整理的用CUDA实现Bellman-Ford的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 拓扑排序 - 项目管理
- 下一篇: 并查集 - 由斜杠划分区域