编译多个 cuda 文件(具有动态并行性)和 MPI 代码

compile multiple cuda files (that have dynamic parallelism) and MPI code

我有一堆使用动态并行性的 .cu 文件(a.cu、b.cu、c.cu..、e.cu、f.cu) ,以及使用 MPI 在多个节点上从 a.cu 调用函数的 main.c 文件。我正在尝试编写一个 make 文件来编译可执行文件,但我一直面临以下错误:

cudafiles.o: In function `__cudaRegisterLinkedBinary_66_tmpxft_00001a84_00000000_17_cuda_device_runtime_compute_61_cpp1_ii_8b1a5d37':
link.stub:(.text+0x1fb): undefined reference to `__fatbinwrap_66_tmpxft_00001a84_00000000_17_cuda_device_runtime_compute_61_cpp1_ii_8b1a5d37'

这是我的 makefile:

INCFILES=-I/usr/local/cuda-8.0/include -I/opt/mpi/mvapich2-gnu/2.2/include -I./
LIBFILES=-L/usr/local/cuda-8.0/lib64 -L/opt/mpi/mvapich2-gnu/2.2/lib
LIBS=-lcudart -lcudadevrt -lcublas_device -lmpi 
ARCH=-gencode arch=compute_60,code=sm_60
NVCC=nvcc -ccbin g++


default: all

all: clean final.o

io.o: io.cpp
        g++ -c -std=c++11  io.cpp 


final.o: io.o a.cu b.cu c.cu d.cu e.cu f.cu main.cpp
        $(NVCC) -std=c++11 $(INCFILES) $(LIBFILES) $(LIBS) -g -G -Xptxas -v -dc $(ARCH) a.cu b.cu c.cu d.cu e.cu f.cu
        $(NVCC) -std=c++11 $(ARCH) $(INCFILES) $(LIBFILES) $(LIBS) -rdc=true -dlink a.o b.o c.o d.o e.o f.o io.o -o cudafiles.o
        mpicxx -O3 $(INCFILES) $(LIBFILES) -c main.cpp -o main.o
        mpicxx $(INCFILES) $(LIBFILES) $(LIBS) cudafiles.o a.o b.o c.o d.o e.o f.o io.o main.o -o exec

clean:
        rm -rf *.o exec
  1. 最初报告的问题是对 main 的未定义引用。这是由 Makefile:

    中的这一行引起的
    $(NVCC) -std=c++11 $(ARCH) $(INCFILES) $(LIBFILES) $(LIBS) -rdc=true a.o b.o c.o d.o e.o f.o io.o -o cudafiles.o
    

    按照构造,这实际上指示 nvcc 执行 full/final linking。然而,这一行的目的是仅执行 device-link 步骤,在使用 -rdc=true-dc 进行编译时需要,并且在不使用 [=13= 执行最终的 link 时需要].在这种情况下,最终的 link 由 mpicc/mpicxx 执行。要仅执行 device-link 步骤,我们需要指定 -dlink。如果没有那个开关,nvcc 期望执行最终的 linking,但失败了,因为提供的对象中的 none 包含一个 main 函数。正确的解决方案是使用 -dlink 开关。

  2. 我还建议将所有内容都转换为 C++ 风格 linking,因为 nvcc link 就是这样。用 C++ 风格的 link 来整理 C-style link 可能是可能的,但这对我来说似乎很麻烦。因此我建议将唯一的 .c 文件 (main.c) 转换为 .cpp 文件,并将 mpicc 转换为 mpicxx

  3. 下一个问题是未定义的引用,例如cudaSetDevice()cudaFree()。这些是 CUDA 运行时 API 库 ("libcudart") 的一部分。当使用 nvcc 执行最终 link 时,这些会自动 linked。但是由于最终 link 由 mpicxx 执行(基本上是 g++ 上的包装器),因此有必要针对该库调用 link,特别是 -lcudart .

  4. 最后,剩下的问题是link-order个问题。简而言之,需要在linker命令行中从左到右满足link依赖。不同的编译器或多或少对此很挑剔。最终的重新排序更改是以正确的顺序指定 link 反对的库,并且还在 link 命令行的末尾指定这些库,以便对这些库的任何依赖性,到它们留在link命令行,都满意了。