SIMT 與 threads 配置的兩三事…

因為 CUDA 程式的執行效能存有太多和硬體實作相關的變因,所以在進一步改善 y-twist 小實驗的執行效能之前,先稍微把目前所瞭解的資訊作個概略的整理,希望能讓自己在未來優化程式時更有方向感… 若文中有任何錯誤的地方還煩請大家不吝指導!! 🙂

CUDA 的架構是由 N 個 SM (streaming multiprocessor) 所構成的,而每個 SM 內含有 M 個 SP (scalar processor) 、 shared memory 和其他硬體原件。當 host CPU 呼叫 kernel function 時,硬體是以 block 為單位將工作分派給目前有能力處理的 SM 進行(據說以 block 為單位是為了方便 porting 至其他硬體)。當 SM 接受到任務之後,便會處理手頭上的 blocks,執行其中所包含的 threads。當手邊任一個 block 裡的 threads 皆執行完畢之後,該 SM 才能再去多接另一個新的 block 的工作。

那 SM 是如何處理 block 呢? CUDA 是透過一個稱為 SIMT (single-instruction, multiple-thread) 的架構來處理整個流程。SIMT 會將數以千百計的 threads 分成一堆 wraps,每個 wrap 內含 K 個 ID 連續的 threads,並以 wrap 為單位作排程。在處理每個 wrap 時,SIMT 會將其中的每一個 thread 批次對應於每個 SP,而這些 thread 都保有自身 register 的狀態,並在同一時間各自獨立地執行某個相同的 instruction

在G80的架構下,每個 SM 有8個 SP,每個 wrap 有 32 threads。所以每個 wrap 在執行每項指令時,總共需要 32/8 = 4 輪,才能處理完畢。而該 wrap 會一直執行,直到指令全部結束或是停在需要 sync 的位置,SIMT 這時便會選擇其他等待執行的 wrap 來遞補接替,如此反覆交替進行到全部的 wraps 皆處理完畢為止。至於branch 的部分,SIMT 則會執行每一個分歧的路線,最後在根據每個 thread 的狀態,選擇符合條件的結果。

從上述的流程中,我們可以發現到,真正平行處理的 threads 其實是每一個 SP 當下所處理的 thread,而這些 threads 則是來自於每個 wrap 中的某一輪。所以為了要 hide I/O latency,便要盡可能增加 wrap 的數量,使 SIMT 在排程時有更多的選擇(盡量讓硬體總有事情可作,避免讓它晾在那裡等 I/O 之後的 synchronization)。但是為了要增加平行處理的 thread 數量,單單只增加 gridDim 和 blockDim 的值來呼叫 kernel function 是不夠的(值越大還不見得比較好,有時候反會導致平行執行的 threads 更少),我們還必須考量 Compute Capability 所帶來的限制。以 Compute Capability 1.0 為例:

  • 每個 block 中最多只能有 512 threads
  • 每個 wrap 含有 32 threads
  • 每個 SM 最多只能有8個block、24個wraps、768個threads

再看以下幾種 block 設定與每個 SM 所含最多 thread 數目的關係:

Threads in Block Blocks in SM Threads in SM
1024(這裡就爆了) 0 0
512 1 512 (再多一個 block 就爆了)
256 3 768 (滿載! 內含 24 個 wraps!)
64 8 512 (這裡還有空間,但是 block 數目已到極限)

雖然 CUDA 程式的執行效能不單只受平行處理的 threads 數目所影響,memory access 的 pattern 也是另一個重要的因素。但是在優化程式過程中,若發現平行 threads 的負載量已經到達某種極限時,便可以摒除這部分的因素,朝其他方面著手。以免投注太多心力於錯誤的方向,造成事倍功半的遺憾。在 CUDA 的架構下,如何將有限的資源,發揮最大的效用,之中還有很多課題需要再進一步地學習與探索。希望,有一天,我也能找到 CUDA 的方向感!! 🙂

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s