2017-08-26 103 views
0

如果我運行以下命令:爲什麼我可以跳過「設備代碼鏈接」與非nvcc鏈接器?

c++ -c --std=c++11 $(includes) -o src/main.o src/main.cpp 
nvcc -c -m64 -arch=sm_30 --std=c++11 $(includes) -o src/kernels/add.o src/kernels/add.cu 
ar qc src/kernels/libkernels.a src/kernels/add.o 
ranlib src/kernels/libkernels.a 
c++ -o program -L/usr/local/cuda/lib64 src/main.o src/kernels/libkernels.a -lcudart -lcudadevrt 

它的工作原理。它不應該失敗,因爲我沒有執行-dlink階段?該Parallel4All blog entry on separate compilation說:

當您使用NVCC鏈接,沒有什麼特別的事:用NVCC代替正常的編譯器命令,它會採取一切必要的步驟照顧。但是,您可以選擇使用nvcc以外的編譯器驅動程序(例如g++)作爲最後的鏈接步驟。由於您的CPU編譯器不知道如何鏈接CUDA設備代碼,因此您必須在編譯中添加一個步驟,使nvcc鏈接CUDA設備代碼,使用nvcc選項–dlink

nvcc –arch=sm_20 –dlink v3.o particle.o main.o –o gpuCode.o 

這將所有設備對象代碼鏈接到gpuCode.o中。請注意,這不會鏈接CPU對象代碼。事實上,v3.o,particle.o和main.o中的CPU目標代碼在此步驟中被丟棄。要完成到可執行文件的鏈接,我們可以使用ld或g ++。

g++ gpuCode.o main.o particle.o v3.o –lcudart –o app 

是否使用.a庫在某種程度上彌補了缺少「設備代碼鏈接」的?

PS - 我使用CUDA 8.0.61的Linux Mint的18.2

回答

3

設備代碼鏈接不是在所有情況下需要。 (這必須是真實的,因爲在CUDA 5.0之前沒有設備代碼鏈接。)

設備代碼鏈接在很多情況下都是必需的,最典型的是設備代碼鏈接必須在不同編譯單元之間進行鏈接。這意味着一個模塊(,文件,編譯單元)中的設備代碼將調用另一個模塊(,文件,編譯單元)中的設備代碼。

我可以告訴大家一個事實,這種情況是不存在的情況下,因爲恰好有一個包含任何設備代碼你的一個模塊(,檔案,編制單位):

nvcc -c -m64 -arch=sm_30 --std=c++11 $(includes) -o src/kernels/add.o src/kernels/add.cu 

                     ^^ 
                   only one file here 

我知道這是真的,因爲任何嘗試用nvcc以外的普通主機代碼編譯器編譯任何設備代碼都會引發語法錯誤。由於這種情況不會發生在您的案例中,並且您只有一個文件可能具有設備代碼,所以您不可能有設備代碼鏈接爲需要的情況,因此您的方法可以使用。

即使您有例如多個.cu文件,如果文件中沒有設備代碼調用另一個文件中的設備代碼(或引用的設備變量),您可能仍不需要設備代碼鏈接。

nvcc手冊的relevant section涵蓋了更詳細的設備代碼鏈接主題。