CUDA nvcc編譯步驟簡單講解

如果你想了解 Nvcc 到底搞了什麼鬼,究竟 compute_xy sm_xy 區別在哪裏, ptx,cudabin 又是怎麼嵌套到 exe 裏面最終被驅動執行的,這一節正是你想要的知識。他將講解每一個編譯的具體步驟,而且不光是知識,讀者可以自己動手操作來體驗這一個過程。他的用處不僅在能夠對 CUDA 的編譯以及工作機制有更深的認識,而且可以進行高級 debug ,比如可以自己手動進行 ptx->cudabin 的步驟等等。

參考: nvcc2.1.pdf 由於水平有限,錯誤部分歡迎大家留言指出

作者: insky(wenyao2009(at)gmail.com)

主頁: www.gamecoding.cn


1. 一個編譯例子

隨意找一個包含 kernel 以及 kernel 調用的 .cu 文件,如 x.cu 。進入命令行 : 敲打 nvcc –cuda x.cu –keep 將得到如下結果, -cuda 是將 .cu 編譯成 .cu.cpp , -keep 保留中間結果。(如果提示找不到 nvcc 請在 path 中添加 %cuda_bin_path%) 

打開 .cu 文件所在目錄(此處是 ptx ) , 你會驚訝的發現多出了一大堆文件,是的,很煩,不過很快你將會喜歡上他們,因爲他們把 nvcc 的工作流程完美的記錄下來了。好吧,那我們開始吧。

2. Virtual architecture vs GPUfeature

首先定位到文件 x.cu, x.ptx, x.sm_10.cubin 這三個文件上來,他們按照下圖流程依次生成, x.cubin,x.ptx 最終會被嵌套到 x.cu.cpp 中。 
 

Virtual compute architecture 對應 nvcc 的 -arch 編譯選項,他的值如下表所示。他的意思 
是 nvcc 將針對哪個類型的 virtual compute architecture 生成 ptx 彙編代碼。如果是 compute_10
則 x.cu 中無法使用 atomic 等不支持的操作,否則會出現編譯錯誤。 
 
Real sm architecture 指的是真實 GPU 的架構,這個選項對應於 nvcc 的 -code 編譯選項, 
他可以選的值如下表所示。他的意思是根據此目標 GPU 架構將 x.ptx 編譯成 x.cubin ,一般 
來說, Real sm architecture 必須等於或者高於對應的 Virtual compute architecture 。比如: 
Nvcc –cuda x.cu –arch compute_13 –code sm_10 是行不通的。 
 

到這裏,你或許會說 “ 你講錯了吧 ” , nvcc 的 -arch 選項可以取 sm_13 呢, cudarule 都這麼取的,沒錯,是可以怎麼做,因爲有些特殊機制的支持:

_ -code 可以有多個值,將生成多個版本的 cubin ,最終全部嵌套在 exe 中,見下節

_ -code 裏面可以包含 compute_xy, 對應的 ptx 會被嵌套在 exe 中,見下節

_ 省略 -arch, 則自動選擇最接近的

nvcc x.cu –code=sm_13 _ nvcc x.cu –arch=compute_13 –code=sm_13

_ 省略 -code

nvcc x.cu –arch=sm_13 _ nvcc x.cu –arch=compute_13 –code=compute_13 sm_13

nvcc x.cu –arch=compute_10 _ nvcc x.cu –arch=compute_10 –code=compute_10

_ 省略 -arch –code

nvcc x.cu _ nvcc x.cu –arch=compute_10 –code=sm_10

3. cubin , ptx 是如何組織到 exe 中,又是如何被加載到驅動中去的

好的,現在我們已經能夠用 -code –arch 去控制 nvcc 生成對應 virtual or gpu architecture 的 ptx 及 cubin 文件了。接下來我們講更徹底去了解,這些 ptx, cubin 是怎麼集中到 exe 中,又是如何被執行的。打開 x.cu.cpp ,搜索 “__deviceText_$compute_10$ ” , 找到了嗎?沒錯,這就是 compute_10 下的 PTX 代碼的二進制形式,接着往下看,你可以找到 “ __deviceText_$sm_10$ ” ,這是 sm_10 下的 cubin 代碼。好吧,再接着看吧:

static __cudaFatPtxEntry __ptxEntries []

static __cudaFatCubinEntry __cubinEntries[]

static __cudaFatDebugEntry __debugEntries[]

他們分別是 ptx 數組, cubin 數組以及 debug 數組, {0 , 0} 結尾的原因不用多說了吧,再找找 __cudaFatPtxEntry 在哪定 義 的吧 cuda2.1include__cudaFatFormat.h ,好好的讀一下這個文件的說 明 ,你會 長嘆 一 聲 “ 你 丫 原來 藏 在這裏 ” 。 OK ,全文 引 用如下: 

4. 回頭來解決剩下的中間文件

其 實 nvcc 只 是個編譯 器 驅動,他會調用很多 cuda tools 去完成 各 個編譯步驟,最 後 調用

系統 的 c/cpp 編譯 器 (cl,gcc) 以及 鏈 接 器 。他的流程如下圖所示:

1 , cudafe.exe 去分 離 host code, device code ,生成 .gpu 等

2 , nvopencc( 我想應 該 就是 nvcc.exe 完成的 ) 編譯 .gpu 到 .ptx

3 , ptxas.exe 編譯 .ptx 到 .cubin

4 , fatbin.exe 編譯 .cubin 到 .fatbin.c ,最終集 合 到 .cu.cpp 或者 .cu.c 中。 

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