入門和gpu相關知識。作爲開篇應該在完美不過了。
閱讀《CUDA專家手冊》第三章硬件架構後的一個筆記。之所以將目錄都打出來,因爲這就是CUDA的軟件架構。
軟件層
從應用程序本身到CUDA硬件上執行的CUDA驅動程序。
驅動程序API和CUDA運行時中的函數名稱分別以cu*()和cuda*()大頭。3對尖括號<<<>>>爲啓用內核函數。
CUDA運行時和驅動程序
驅動程序版本可由cuDriverGetVersion()函數獲取。
驅動程序模型
- 統一虛擬尋址
- Windows顯式驅動模型
- 超時檢測與恢復
- 特斯拉計算集羣驅動程序
nvcc, PTX和微碼
- nvcc是CUDA開發者使用的編譯器驅動程序。例如編譯、鏈接。
- 並行線程執行(PTX, Parallel Thread eXecution)代碼是編譯後的GPU代碼的一種中間形式,它可以再次編譯爲原生的GPU微碼。
設備與初始化
設備數量
調用cuDeviceGetCount()或cudaGetDeviceCount()函數查詢範圍爲[0…DeviceCount - 1]的設備可用。
設備屬性
- cuDeviceGetName()->查詢設備名稱
- cuDeviceTotalMem()->查詢全局內存
- cuDeviceComputeCapability()->查詢計算能力
- cuDeviceAttribute()->查詢設備屬性
- cudaGetDeviceProperties()->返回包括設備名稱和屬性信息的結構體cudaDeviceProp
無CUDA支持情況
CUDA運行時程序可以運行在不能運行CUDA的機器或未安裝CUDA的機器上。如果cudaGetDeviceCount()函數返回cudaSuccess和一個非0的設備數,CUDA是可以用的。
上下文
上下文類似CPU中的進程,管理CUDA程序中所有對象生命週期的容器,包括如下部分:
- 所有內存分配(線性設備內存,主機內存,CUDA數組)
- 模塊
- CUDA流
- CUDA事件
- 紋理與表面引用
- 使用本地內存的內核的設備內存
- 進行調試、分析、同步操作時,所使用的內部資源
- 換頁內存複製所使用的鎖定中轉緩衝區
cudaSetDevice()函數,爲調用的線程設置當前上下文。
生命週期與作用域
所有與CUDA上下文相關的分配資源都在上下文被銷燬的同時被銷燬。
資源預分配
少數情況下,CUDA不會預分配一個給定操作所需的全部資源。
地址空間
一組私有的虛擬內存地址,它可以分配線性設備內存或用以映射鎖頁主機內存。
當前上下文棧
三個主要功能。
- 單線程應用程序可以驅動多個GPU上下文
- 庫可以創建並管理它們自己上下文,而不需要干涉調用者的上下文。
- 庫不知曉調用它的CPU線程信息。
當前上下文棧的最初動機是使單線程CUDA應用程序可以驅動多個CUDA上下文。
上下文狀態
類似於CPU中的malloc()和printf()函數,cuCtxSetLimit()和cuCtxGetLimit()函數可以設置和獲取內核函數中對應函數的GPU空間上限。cuCtxSetCacheConfig()函數在啓動內核時指定所期望的緩存配置。
模塊與函數
模塊是代碼與一同加載的數據的集合,類似於windows中的動態鏈接庫(DLL)和Linux中的動態共享對象(DSO)。模塊只在CUDA驅動程序API中可用。
模塊被加載,應用程序就可以查詢其中包含的資源:
- 全局資源
- 函數(內核)
- 紋理引用
內核(函數)
在.cu文件中,用global標識內核。三對尖括號<<<>>>爲啓用內核函數。
設備內存
設備內存(或線性設備內存)駐留在CUDA地址空間上,可以被CUDA內核通過標準C/C++指針和數組解引用操作訪問。CUDA硬件並不支持請求式換頁,所以,所有的內存分配被真實的物理內存支持着。CUDA內存分配在物理內存耗盡時會失敗。
流與事件
流與事件使主機與設備之間的內存複製與內核操作可併發執行。
CUDA流被用來粗粒度管理多個處理單元的併發執行:
- GPU/CPU
- 在SM處理時可以執行DMA操作的複製引擎
- 流處理器蔟(SM)
- 併發內核
- 併發執行的獨立GPU
流的操作是按順序執行的,像CPU的線程。
軟件流水線
軟件流水線解決因只有一個DMA引擎服務於GPU各種各樣的粗粒度硬件資源,應用軟件必須對多流中執行的操作進行流水操作。
開普勒架構減少了軟件流水線操作的需求,Hyper-Q技術實際上消除了流水線需求。
流回調
不懂。
NULL流
NULL流失GPU上所有引擎的集結地,所有的流內存複製函數都是異步的。NULL流最有用的場合是在不需要使用多流來利用GPU內部的併發性時,它可以解決應用程序的CPU/GPU併發。一旦流操作使用NULL流初始化,應用程序必須使用同步函數來確保操作在執行下一步之前完成。
事件
CUDA事件表示了另一個同步機制。同CUDA流一同引入,記錄CUDA事件是CUDA流中應用程序跟蹤進度的一個方式。當之前的所有CUDA流的操作執行結束後,全部的CUDA事件通過寫入一個共享同步內存位置而起作用。
主機內存
主機內存(CPU內存)。在所有運行CUDA的操作系統上,主機內存是虛擬化的。
爲了便利DMA,操作系統VMM(虛擬內存管理器)提供了一個頁面鎖定功能。被VMM標記爲鎖頁的內存就不能被換出,所以物理內存地址不能被修改。沒被鎖頁的內存稱作可換頁。
鎖頁主機內存
鎖頁主機內存由CUDA函數cuMemHostAlloc()/cudaHostAlloc()分配。該內存是頁鎖定的並且由當前CUDA上下文爲DMA設置。異步內存複製操作只在鎖頁內存上工作。
在CUDA中,鎖頁內存(pinned memory)是經過頁鎖定後且爲硬件訪問而映射後的主機內存,而頁面鎖定(page-locking)只是操作系統的一種不允許換頁的機制。但是在操作系統文檔中,這個兩個概念是同義的。
可分享的鎖頁內存
可分享頁內存在頁鎖定後映射給所有CUDA上下文。
映射鎖頁內存
映射鎖頁內存映射到CUDA上下文中的地址空間中,所以內核可能讀寫這塊內存。
主機內存註冊
用於開發者分配他們想要訪問的內存。
CUDA數組與紋理操作
紋理引用可以把輸入的任何座標轉化到設置的輸出格式,表面引用則暴露了一個常規的逐位操作接口來讀寫CUDA數組內容。
紋理引用
紋理引用是CUDA用來設置紋理硬件解釋實際內存內容的對象。
表面引用
表面引用可以是CUDA內核使用表面加載/存儲內建函數讀寫CUDA數組。
圖形互操作性
圖形互操作性函數族使得CUDA可以讀寫屬於OpenGL或Direct3D API的內存。
CUDA運行時與CUDA運動程序API
驅動程序API沒有提供任何性能優勢,但它爲應用程序提供了顯式的資源管理。
尾巴
草草結束該章內容,沒有實際的操作真得讓人很容易犯困。最後用一句話結束尾巴的內容——“當一位作家略去他所不知道的東西時,它們在作品中像漏洞似的顯示出來。”
參考:
《GPGPU編程技術——從GLSL、CUDA到OpenCL》♥♥♥♥♥
《數字圖像處理高級應用——基於MATLAB與CUDA的實現》♥♥♥
《基於CUDA的並行程序設計》♥♥♥
《CUDA專家手冊》♥♥♥♥♥
《高性能CUDA應用設計與開發》♥♥♥♥