1. 程式人生 > >CUDA中grid、block、thread、warp與SM、SP的關係

CUDA中grid、block、thread、warp與SM、SP的關係

首先概括一下這幾個概念。其中SM(Streaming Multiprocessor)SP(streaming Processor)是硬體層次的,其中一個SM可以包含多個SP。thread是一個執行緒,多個thread組成一個執行緒塊block,多個block又組成一個執行緒網格grid。

現在就說一下一個kenerl函式是怎麼執行的。一個kernel程式會有一個grid,grid底下又有數個block,每個block是一個thread群組。在同一個block中thread可以通過共享記憶體(shared memory)來通訊,同步。而不同block之間的thread是無法通訊的。

CUDA的裝置在實際執行過程中,會以block為單位

。把一個個block分配給SM進行運算;而block中的thread又會以warp(執行緒束)為單位,對thread進行分組計算。目前CUDA的warp大小都是32,也就是說32個thread會被組成一個warp來一起執行。同一個warp中的thread執行的指令是相同的,只是處理的資料不同。

基本上warp 分組的動作是由SM 自動進行的,會以連續的方式來做分組。比如說如果有一個block 裡有128 個thread 的話,就會被分成四組warp,第0-31 個thread 會是warp 1、32-63 是warp 2、64-95是warp 3、96-127 是warp 4。而如果block 裡面的thread 數量不是32 的倍數,那他會把剩下的thread獨立成一個warp;比如說thread 數目是66 的話,就會有三個warp:0-31、32-63、64-65 。由於最後一個warp 裡只剩下兩個thread,所以其實在計算時,就相當於浪費了30 個thread 的計算能力;這點是在設定block 中thread 數量一定要注意的事!

一個SM 一次只會執行一個block 裡的一個warp,但是SM 不見得會一次就把這個warp 的所有指令都執行完;當遇到正在執行的warp 需要等待的時候(例如存取global memory 就會要等好一段時間),就切換到別的warp來繼續做運算,藉此避免為了等待而浪費時間。所以理論上效率最好的狀況,就是在SM 中有夠多的warp 可以切換,讓在執行的時候,不會有「所有warp 都要等待」的情形發生;因為當所有的warp 都要等待時,就會變成SM 無事可做的狀況了。

實際上,warp 也是CUDA 中,每一個SM 執行的最小單位;如果GPU 有16 組SM 的話,也就代表他真正在執行的thread 數目會是32*16 個。不過由於CUDA 是要透過warp 的切換來隱藏thread 的延遲、等待,來達到大量平行化的目的,所以會用所謂的active thread 這個名詞來代表一個SM 裡同時可以處理的thread 數目。而在block 的方面,一個SM 可以同時處理多個thread block,當其中有block 的所有thread 都處理完後,他就會再去找其他還沒處理的block 來處理。假設有16 個SM、64 個block、每個SM 可以同時處理三個block 的話,那一開始執行時,device 就會同時處理48 個block;而剩下的16 個block 則會等SM 有處理完block 後,再進到SM 中處理,直到所有block 都處理結束 

在CUDA 架構下,GPU晶片執行時的最小單位是thread。
若干個thread可以組成一個執行緒塊(block)。一個block中的thread能存取同一塊共享記憶體,可以快速進行同步和通訊操作。
每一個block 所能包含的thread 數目是有限的。執行相同程式的block,可以組成grid。不同block 中的thread 無法存取同一共享記憶體,因此無法直接通訊或進行同步。
不同的grid可以執行不同的程式(kernel)。

舉個栗子:

1:一個SM有8個SP,SM執行一個Warp時有32個執行緒,這32各執行緒在8個SP上執行4次,實際上是8個8個輪替,嚴格意義上來講不是同時執行,只是隱藏延遲,因為軟體層我們是將其抽象出來,因此可以說是同時執行。
2:當一個SM中有更多的SP時,例如GP100這種,一個SM上有64個SP,執行緒也不一定是平攤的,看具體架構的官方文件。一般情況下還是8個sp執行4次,也就是說當你資料跑32個執行緒的時候,在有64個SP的SM裡實際還是8個SP在跑,和一個SM裡面只有8個SP的情況是一致的。所以一個SM有64個SP的時候,意味著最多同時可以並行8個warp,8×32執行緒即256和執行緒。此時通常情況來說已經滿執行緒了,當架構能進一步降低延遲時,通過抽象可以跑1024個執行緒。