CUDA基本概念
主機(host)
通常將起控制作用的CPU稱為主機(host)
設備(device)
將起加速作用的 GPU 稱為設備(device)
流處理器(streaming processor)
物理上,GPU最基本的處理單元為SP(streaming processor),又稱為CUDA core,主要包括若干整數型運算的核心、若干單精度浮點數運算的核心、若干雙精度浮點數運算的核心、若干單精度浮點數超越函數的特殊函數單元、若干混合精度的張量核心(有伏特架構引進,適用于機器學習)。
最后具體的指令和任務都是在SP上處理的,GPU進行并行計算,即為多個SP同時做處理。
每個核心可以在一個時鐘周期內執行一個線程。
流多處理器(streaming multiprocessor)
流多處理器SM(streaming multiprocessor)則是GPU的核心,又稱為GPU大核,是GPU并行計算的核心單元。
一個典型的SM包括以下幾個組件:
- 核心SP
- 共享內存/一級緩存 ShareMem/Cache
- 寄存器文件Reg File
- 加載/存儲單元LD/ST
- 特殊功能單元SFU
- 線程束調度器 Warp Sched
每個SM包含多個流處理器SP(CUDA core),以及共享內存、寄存器等資源,所以每個SM都可以并行執行多個線程。
每個流式多處理器可以視為具有較小結構的CPU,支持指令并行(多發射)。
不同的NVIDIA GPU架構(例如Turing, Pascal, Maxwell, Kepler等)具有不同的SM設計和資源配置。
例如,某些架構可能在每個SM上有更多的CUDA核心,而其他架構可能有更多的共享內存或寄存器。
SM可以并發地執行許多線程,一般可以同時調度多個線程塊。SM的基本執行單元是線程束(thead warp),線程束包含32個線程,這些線程同時執行相同的指令,但是每個線程都包含自己的指令地址計數器和寄存器狀態,也有自己獨立的執行路徑,這導致了即便線程束中的線程同時從同一程序地址執行,但是可能具有不同的行為(比如遇到了分支結構,一些線程可能進入這個分支,但是另外一些有可能不執行,它們只能死等(因為GPU規定線程束中所有線程在同一周期執行相同的指令)),這被稱為"線程束分化"。當線程塊被劃分到某個SM上時,它將進一步劃分為多個線程束,因為這才是SM的基本執行單元,但是一個SM同時并發的線程束數是有限的。這是因為資源限制,SM要為每個線程塊分配共享內存,而也要為每個線程束中的線程分配獨立的寄存器。
全局內存(Global Memory)
GPU的主存儲器,容量較大,但訪問速度較慢。
所有的線程都可以對全局內存進行讀寫。緩存可加速對全局內存的訪問。所有通過cudaMalloc分配的存儲器都是全局內存。
共享內存(Shared Memory)
每個SM內部的高速緩存,供同一SM內的線程共享。
訪問速度比全局內存快得多。
寄存器(Registers)
每個線程的私有存儲空間,用于保存臨時變量。
寄存器是訪問速度最快的空間。
當我們在核函數中不加修飾的聲明一個變量,那該變量就是寄存器變量,如果在核函數中定義了常數長度的數組,那也會被分配到Registers中;寄存器變量是每個線程私有的,當這個線程的核函數執行完成后,寄存器變量也就不能訪問了。
寄存器是比較稀缺的資源,空間很小,Fermi架構中每個線程最多63個寄存器,Kepler架構每個線程最多255個寄存器;一個線程中如果使用了比較少的寄存器,那么SM中就會有更多的線程塊,GPU并行計算速度也就越快。
如果一個線程中變量太多,超出了Registers的空間,這時寄存器就會發生溢出,就需要其他內存(Local Memory)來存儲,當然程序的運行速度也會降低。
本地內存(Local Memory)
Local Memory也是每個線程私有的,但卻是存儲在于Global Memory中的。在核函數中符合存儲在寄存器中但不能進入核函數分配的寄存器空間中的變量將被存儲在Local Memory中。
Local Memory中可能存放的變量有以下幾種:
- 使用未知索引的本地數組
- 較大的本地數組或結構體
- 任何不滿足核函數寄存器限定條件的變量
常量內存
線程(Thread)、線程塊(Block)、網格(Grid)
GPU使用線程(Thread)作為最小的執行單位。
線程被組織成線程塊(Block),多個線程塊組成網格(Grid)。
以上圖為例子,把網格和線程塊都看作一個三維的矩陣。這里假設網格是一個333的三維矩陣, 線程塊是一個444的三維矩陣。
線程束(Warp)
線程束(warp)作為并行處理的基石,通過將線程組合成一個執行單元,簡化了線程管理,使線程間能夠共享數據和資源,并通過有效的調度掩蓋內存延遲。
Nvidia把32個threads組成一個warp,warp是調度和運行的基本單元。它們會被同時調度到一個SM上執行。
核函數
核函數是運行在GPU上的函數,可以并行執行,核函數通過特殊的語法和關鍵字定義,并且是 GPU 編程的核心。
定義核函數:
- 必須使用限定詞__global__修飾
- 核函數返回值必須是void
- 核函數通常以<<<blockNum, threadNum>>>形式來配置執行線程和塊
參考文檔
https://blog.csdn.net/qq_42761751/article/details/144297840
https://zhuanlan.zhihu.com/p/544864997