CUDA編譯過程

流程

  1. 將test.cu代碼進行分離,利用cudafe.exe 去分離CPU代碼和GPU代碼,我們可以在生成的中間文件可以看到test.cudafe1.cpp和test.cudafe1.gpu
  2. cicc.exe 將根據編譯選項-arch=compute_xx將GPU代碼編譯成對應架構的test.ptx文件
  3. ptxas.exe 編譯 test.ptx 到test.cubin,這個是根據編譯選項-code=sm_xx定義的,比如test.sm_30.cubin.(這一步叫做PTX離線編譯,主要的目的是爲了將代碼編譯成一個確定的計算能力和SM版本,對應的版本信息保存在cubin中)
  4. fatbin.exe 編譯test .cubin 和test. ptx到 text.fatbin.c 。 (這一步叫PTX在線編譯,是將cubin和ptx中的版本信息保存在fatbin中)
  5. 調用系統的gcc/g++將host代碼(test.cudafe1.cpp)和fatbin(text.fatbin.c)編譯成對應的目標文件test.o 和test._dlink.o。
  6. 用c++編譯器將目標文件鏈接起來生成可執行文件。

實驗

nvcc --cuda test.cu --keep --dryrun

細節

  • -arch=compute_XX, -code=sm_XX, 如果寫兩個的話必須這樣來寫,也就說compute_必須對應的是arch, code必須對應的是sm_,arch代表的是目標機器(vitural),而code代表的是真實機器(real),下面是具體的例子:

nvcc -o test test.cu -arch=compute_35 -code=sm_70 --keep --verbose

具體小步驟

  1. cicc *** -arch compute_35 -o test.ptx// 可以看出ptx是根據arch來設定的
  2. ptxas -arch=sm_70 -m64 “test.ptx” -o “test.cubin”//本地二進制文件是根據sm_70來設定,至於爲用的是arch,這就是nvcc瞎寫
  3. fatbinary --create=“test.fatbin” -64 “–image=profile=sm_70,file=test.cubin” --embedded-fatbin=“test.fatbin.c” --cuda(這裏面沒有將ptx放進去不知道什麼情況,當只有arch一個參數的時候ptx和cubin都會放入fatbin.c裏面)

使用

一般都是隻使用一個-arch, 這樣默認你的arch和code是同一個架構算力,比如-arch=sm_70。感覺英偉達這搞得一點也不規範,都出亂編,也沒個統一的標準。

思考

  • 經常可以看到說cuda的即時編譯,可是我是沒見到運行的時候出現編譯過程,難道是我使用姿勢不對?

fatbinary機制。exe二進制文件中會包含一個或多個體繫結構的二進制代碼以及PTX代碼來完全避免JIT成本。CUDA運行時會在二進制文件中查找當前GPU架構的代碼,並在找到時運行它。如果找不到二進制代碼,但PTX可用,則驅動程序將編譯PTX代碼。這樣,部署的CUDA應用程序可以在新GPU出現時支持它們。nvcc x.cu -arch=compute_10 -code=compute_10,sm_10,sm_13,比如這一段程序,編譯出來的代碼就會有10,13兩個二進制,實際遇到了這類GPU就直接使用,否則就把compute_10.ptx運行時編譯一波。

  • 難道我一份exe每次在新機器A上重複使用時每次都要即時編譯嗎?這也太蠢了吧

緩存機制。 如果在code中沒有指示出來實際運行的GPU, 理論來說你在A這個GPU上運行的時候,每次都要JIT,爲此cuda做了一個優化,就是將它第一次接觸過得GPU卡即時編譯後緩存一起,也就是說第一次在A卡編譯後,下次再運行就直接可以調用緩存裏面的二進制了,理論上來說就是放在-code=sm_10, A,sm_20,不過A是在遇到A之後才編譯的

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