2017-08-26 122 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涵盖了更详细的设备代码链接主题。