如果我运行以下内容:
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选项nvcc
–dlink
链接CUDA设备代码。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 - 我在Linux Mint 18.2上使用CUDA 8.0.61
答案 0 :(得分: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涵盖了更详细的设备代码链接主题。