【并行计算-CUDA开发】CUDA线程、线程块、线程束、流多处理器、流处理器、网格概念的深入理解
GPU的硬件結(jié)構(gòu),也不是具體的硬件結(jié)構(gòu),就是與CUDA相關(guān)的幾個概念:thread,block,grid,warp,sp,sm。
sp:最基本的處理單元,streaming processor 最后具體的指令和任務(wù)都是在sp上處理的。GPU進行并行計算,也就是很多個sp同時做處理
sm:多個sp加上其他的一些資源組成一個sm, streaming multiprocessor. 其他資源也就是存儲資源,共享內(nèi)存,寄儲器等。
warp:GPU執(zhí)行程序時的調(diào)度單位,目前cuda的warp的大小為32,同在一個warp的線程,以不同數(shù)據(jù)資源執(zhí)行相同的指令。
grid、block、thread:在利用cuda進行編程時,一個grid分為多個block,而一個block分為多個thread.其中任務(wù)劃分到是否影響最后的執(zhí)行效果。劃分的依據(jù)是任務(wù)特性和
GPU本身的硬件特性。
下面幾張硬件結(jié)構(gòu)簡圖 便于理解(圖片來源于網(wǎng)上)
以上兩圖可以清晰地表示出sm與sp的關(guān)系。
此圖反應(yīng)了warp作為調(diào)度單位的作用,每次GPU調(diào)度一個warp里的32個線程執(zhí)行同一條指令,其中各個線程對應(yīng)的數(shù)據(jù)資源不同。
上圖是一個warp排程的例子。
一個sm只會執(zhí)行一個block里的warp,當(dāng)該block里warp執(zhí)行完才會執(zhí)行其他block里的warp。
進行劃分時,最好保證每個block里的warp比較合理,那樣可以一個sm可以交替執(zhí)行里面的warp,從而提高效率,此外,在分配block時,要根據(jù)GPU的sm個數(shù),分配出合理的
block數(shù),讓GPU的sm都利用起來,提利用率。分配時,也要考慮到同一個線程block的資源問題,不要出現(xiàn)對應(yīng)的資源不夠。
GPU線程以網(wǎng)格(grid)的方式組織,而每個網(wǎng)格中又包含若干個線程塊,在G80/GT200系列中,每一個線程塊最多可包含512個線程,F(xiàn)ermi架構(gòu)中每個線程塊支持高達1536個線程。同一線程塊中的眾多線程擁有相同的指令地址,不僅能夠并行執(zhí)行,而且能夠通過共享存儲器(Shared memory)和柵欄(barrier)實現(xiàn)塊內(nèi)通信。這樣,同一網(wǎng)格內(nèi)的不同塊之間存在不需要通信的粗粒度并行,而一個塊內(nèi)的線程之間又形成了允許通信的細粒度并行。這些就是CUDA的關(guān)鍵特性:線程按照粗粒度的線程塊和細粒度的線程兩個層次進行組織、在細粒度并行的層次通過共享存儲器和柵欄同步實現(xiàn)通信,這就是CUDA的雙層線程模型。
在執(zhí)行時,GPU的任務(wù)分配單元(global block scheduler)將網(wǎng)格分配到GPU芯片上。啟動CUDA 內(nèi)核時,需要將網(wǎng)格信息從CPU傳輸?shù)紾PU。任務(wù)分配單元根據(jù)這些信息將塊分配到SM上。任務(wù)分配單元使用的是輪詢策略:輪詢查看SM是否還有足夠的資源來執(zhí)行新的塊,如果有則給SM分配一個新的塊,如果沒有則查看下一個SM。決定能否分配的因素有:每個塊使用的共享存儲器數(shù)量,每個塊使用的寄存器數(shù)量,以及其它的一些限制條件。任務(wù)分配單元在SM的任務(wù)分配中保持平衡,但是程序員可以通過更改塊內(nèi)線程數(shù),每個線程使用的寄存器數(shù)和共享存儲器數(shù)來隱式的控制,從而保證SM之間的任務(wù)均衡。任務(wù)以這種方式劃分能夠使程序獲得了可擴展性:由于每個子問題都能在任意一個SM上運行,CUDA程序在核心數(shù)量不同的處理器上都能正常運行,這樣就隱藏了硬件差異。
對于程序員來說,他們需要將任務(wù)劃分為互不相干的粗粒度子問題(最好是易并行計算),再將每個子問題劃分為能夠使用線程處理的問題。同一線程塊中的線程開始于相同的指令地址,理論上能夠以不同的分支執(zhí)行。但實際上,在塊內(nèi)的分支因為SM構(gòu)架的原因被大大限制了。內(nèi)核函數(shù)實質(zhì)上是以塊為單位執(zhí)行的。同一線程塊中的線程需要SM中的共享存儲器共享數(shù)據(jù),因此它們必須在同一個SM中發(fā)射。線程塊中的每一個線程被發(fā)射到一個SP上。任務(wù)分配單元可以為每個SM分配最多8個塊。而SM中的線程調(diào)度單元又將分配到的塊進行細分,將其中的線程組織成更小的結(jié)構(gòu),稱為線程束(warp)。在CUDA中,warp對程序員來說是透明的,它的大小可能會隨著硬件的發(fā)展發(fā)生變化,在當(dāng)前版本的CUDA中,每個warp是由32個線程組成的。SM中一條指令的延遲最小為4個指令周期。8個SP采用了發(fā)射一次指令,執(zhí)行4次的流水線結(jié)構(gòu)。所以由32個線程組成的Warp是CUDA程序執(zhí)行的最小單位,并且同一個warp是嚴格串行的,因此在warp內(nèi)是無須同步的。在一個SM中可能同時有來自不同塊的warp。當(dāng)一個塊中的warp在進行訪存或者同步等高延遲操作時,另一個塊可以占用SM中的計算資源。這樣,在SM內(nèi)就實現(xiàn)了簡單的亂序執(zhí)行。不同塊之間的執(zhí)行沒有順序,完全并行。無論是在一次只能處理一個線程塊的GPU上,還是在一次能處理數(shù)十乃至上百個線程塊的GPU上,這一模型都能很好的適用。
目前,某一時刻只能有一個內(nèi)核函數(shù)正在執(zhí)行,但是在Fermi架構(gòu)中,這一限制已被解除。如果在一個內(nèi)核訪問數(shù)據(jù)時,另一個內(nèi)核能夠進行計算,則可以有效的提高設(shè)備的利用率。
每一個塊內(nèi)線程數(shù)應(yīng)該首先是32的倍數(shù),因為這樣的話可以適應(yīng)每一個warp包含32個線程的要求,每一個warp中串行執(zhí)行,這就要求每一個線程中不可以有過多的循環(huán)或者需要的資源過多。但是每一個塊中如果線程數(shù)過多,可能由于線程中參數(shù)過多帶來存儲器要求過大,從而使SM處理的效率更低。所以,在函數(shù)不是很復(fù)雜的情況下,可以適當(dāng)?shù)脑黾泳€程數(shù)目,線程中不要加入循環(huán)。在函數(shù)比較復(fù)雜的情況下,每一個塊中分配32或是64個線程比較合適。每一個SM同時處理一個塊,只有在粗粒度層面上以及細粒度層面上均達到平衡,才能使得GPU的利用到達最大。我用的顯卡為GeForce
GTX560 Ti,每一個網(wǎng)格中允許的最大塊數(shù)位65535個,而每個塊中的線程數(shù)為1024個,所以說粗粒度平衡對于我來說影響比較小,就細粒度來說,每一個塊中的線程數(shù)以及每一個線程中的循環(huán)就變得至關(guān)重要了。
總結(jié)
以上是生活随笔為你收集整理的【并行计算-CUDA开发】CUDA线程、线程块、线程束、流多处理器、流处理器、网格概念的深入理解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python缩进问题
- 下一篇: Mat中的元素类型(如CV_8U)、范围