CUDA程序開發——軟硬件層級的調度解讀

CUDA程序開發——軟硬件層級的調度解讀

通過閱讀文本你將瞭解到以下內容:

  • CUDA硬件層級
  • CUDA軟件層級
  • 軟件層級在硬件層級上的具體調度

關鍵字:SP、SM、Device、Thread、Block、Grid、Warp

想要編寫出高性能的CUDA核函數,研究CUDA的軟硬件架構是必不可少的。比如在給每一個核函數配置<<<>>>內的啓動參數時,你可能在想到底應該分配多少個block,每個block中應該分配多少個thread,這些參數是試出來的,還是有一定的規律可循。如果你想把這個問題搞清楚,不如先從CUDA的軟硬件層級開始瞭解。

1. 軟硬件層級

從硬件方面看,CUDA將GPU的處理單元被分爲3個層次:流處理器(Streaming Process,SP)、流多處理器(Streaming Multiprocessor,SM)和設備(Device)。

  • SP是最基本的處理單元,也稱爲CUDA Core,可以將其理解成CPU的一個核,CUDA的kernel函數運行的具體指令就是在SP上處理的。
  • SM由多個SP和一些其他資源組成,不同的架構包含的SP的數量不同,Kepler架構一個SM包含192個SP(這裏可以理解成一個SM有192個核)。SM通過線程調度器爲SP分發線程,實際可執行的線程要比SP個數多很多。
  • Device由多個SM和一些其他資源組成,不同的設備包含的SM數量不同,以Tesla K80爲例,一個GPU包含13個SM。設備也是通過調度器爲SM分發線程塊的。

而CUDA對Kernel函數中的線程管理也分爲3個層次:線程(Thread)、線程塊(Block)和線程格(Grid)。

  • Thread是處理數據的一個線程。
  • Block由多個Thread組成,Block內的Thread可以通過共享內存通信,也可以通過函數同步。
  • Grid由多個Block組成。
CUDA線程與處理單元的對應關係

實際上,將線程分層不僅是爲了便於將線程與數據塊相對應,也是爲了將軟件執行與硬件相對應。CUDA將Grid分配到Device上,通過GigaThread engine將Block分配到SM上,再通過Warp Scheduler將Thread分配到SP上。也許你會問它們到底是怎麼調度的,其中的細節是怎樣的?

2. 具體調度

2.1 Grid(Kernel)調度

一個kernel核函數在啓動之後,只能在一個GPU設備上運行,不可能運行在多個GPU上。但是,一個GPU是可以同時運行多個kernel的,這與多個工作隊列有關,是爲了最大化GPU的利用率。

2.2 Block調度

kernel核函數中的一個block會被調度到一個SM上,注意一個block也不能在多個SM上運行。但是,一個SM能夠同時運行多個block,計算能力2.0的SM可以最多運行8個block,計算能力3.0的SM可以最多運行16個block。在程序運行時,一個SM具體能夠運行幾個block,這與每個block佔用的資源數量和SM內擁有的總資源數量有關係。同時block在分配給SM時,是考慮到SM的負載均衡的,舉個例子。有19個block,4個SM,分配的情況很可能是這樣的:先給每個SM分配4個block,還剩餘3個block,然後給其中的3個SM分別分配1個block,而不是給其中的1個SM分配3個block。這種負載均衡是有利於縮短程序的運行時間。

2.3 Thread(Warp)調度

最後,是block中thread的調度情況,這個要複雜一點。CUDA出於程序執行效率和執行靈活性的考慮,將thread的調度粒度設置爲32個線程,也就是常說的1個線程束(Warp,warp在英文中有紡織機上經線的意思,多個線組成一排,一起織布)。所以,一個block被分配到一個SM上之後,會被SM按32爲一組分成多個warp,這些warp會被隨機調度,且會被多次調度。

在具體介紹warp的調度情況之前,我們先了解一下warp的三種狀態:

  • 執行態:一個warp佔有計算核心,正在被執行。
  • 就緒態:一個warp做好被立即執行的準備,等待調度器調度。
  • 阻塞態:由於執行延遲,一個warp等待資源,此時沒有做好被立即執行的準備。

一個warp能從就緒態轉爲執行態,需要兩個條件:一個是必須有32個SP可以被利用,另一個是當前指令需要的資源都已準備好。所有處於這三種狀態的warp我們稱其爲active warp,而那些還有被分配SM的block裏的warp則是非active warp。

下面具體說明一下warp的調度情況,如下圖,CUDA會隨機挑選一個warp,並由Warp Scheduler將其調度給32個sp單元,之後由Instruction Dispatch Unit將Kernel中的一條指令發送給32個sp執行,在執行過程中很可能會出現阻塞情況,比如訪問顯存時需要等待,等待過程中這個被執行的warp會從執行態進入阻塞態,此時Warp Scheduler又會隨機調度一個處於就緒態的warp,然後再由Instruction Dispatch Unit分發一條指令,以此類推,多個warp就是這樣被隨機且循環調度的。
(注:這裏提到的32個SP,是對於計算能力較高的設備而言的,而對於計算能力比較低的設備,是16個sp單元,即將warp分成兩份)

這裏,有人可能會問,warp切換的開銷大不大。因爲我們都知道,CPU上線程的切換是需要爲當前線程保存上下文信息的(寄存器和程序計數器等),這個保存和恢復上下文的過程,需要幾十納秒到幾微秒的時間。那麼GPU上涉及到大量的warp切換,會不會很耗時。實際上,SM在進行warp切換時開銷很小,可以忽略不計,因爲相比於CPU,GPU爲所有的thead單獨分配了足夠的寄存器,每一個thread的狀態信息在SM上總是單獨存好的,所以切換的時候不需要額外的保存和恢復。

關於warp還有一個問題 ,就是一個SM最多可以執行多少個warp。對於計算能力3.0以上的設備,理論上1個SM最多可以同時運行2048個thread,那麼,1個SM最多就可以同時運行2048/32=64個warp。注意這裏的同時運行是一個邏輯值,而不是物理值。邏輯值64個warp是指同一時間最多可以同時調度64個active warp;而物理值對應於1個SM中的Warp Scheduler的個數和SP的個數,以Kepler爲例,一個SM中有4個Warp Scheduler和192個SP,則物理上最多可以同時運行4個執行態的warp。

同時,細心的你可能已經發現,最大值64個warp是與一個SM可以同時調度多個block相佐證的。因爲一個block最多運行1024個線程,即32個warp,這只是最大值的一半,所以從側面證明了SM可以調度多個block。

3. 總結

總結一下,CUDA將硬件分爲三個層次:Device、SM、SP,將軟件分爲三個層次:Grid、Block、Thread。一個Grid只能運行在一個Device上,而一個Device可以運行多個Grid;一個Block只能運行在一個SM上,而一個SM也可以同時運行多個Block;CUDA的線程調度粒度是32個Thead,即1個Warp,Warp在SP上是隨機且多次被調度執行的,Warp的切換開銷可以忽略不計。

 

本文爲博主原創文章,轉載請註明鏈接 https://blog.csdn.net/luroujuan/article/details/88088834

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章