编译多个 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
最初报告的问题是对 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
开关。
我还建议将所有内容都转换为 C++ 风格 linking,因为 nvcc
link 就是这样。用 C++ 风格的 link 来整理 C-style link 可能是可能的,但这对我来说似乎很麻烦。因此我建议将唯一的 .c
文件 (main.c
) 转换为 .cpp
文件,并将 mpicc
转换为 mpicxx
下一个问题是未定义的引用,例如cudaSetDevice()
和 cudaFree()
。这些是 CUDA 运行时 API 库 ("libcudart") 的一部分。当使用 nvcc
执行最终 link 时,这些会自动 linked。但是由于最终 link 由 mpicxx
执行(基本上是 g++
上的包装器),因此有必要针对该库调用 link,特别是 -lcudart
.
最后,剩下的问题是link-order个问题。简而言之,需要在linker命令行中从左到右满足link依赖。不同的编译器或多或少对此很挑剔。最终的重新排序更改是以正确的顺序指定 link 反对的库,并且还在 link 命令行的末尾指定这些库,以便对这些库的任何依赖性,到它们留在link命令行,都满意了。
我有一堆使用动态并行性的 .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
最初报告的问题是对
中的这一行引起的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
开关。我还建议将所有内容都转换为 C++ 风格 linking,因为
nvcc
link 就是这样。用 C++ 风格的 link 来整理 C-style link 可能是可能的,但这对我来说似乎很麻烦。因此我建议将唯一的.c
文件 (main.c
) 转换为.cpp
文件,并将mpicc
转换为mpicxx
下一个问题是未定义的引用,例如
cudaSetDevice()
和cudaFree()
。这些是 CUDA 运行时 API 库 ("libcudart") 的一部分。当使用nvcc
执行最终 link 时,这些会自动 linked。但是由于最终 link 由mpicxx
执行(基本上是g++
上的包装器),因此有必要针对该库调用 link,特别是-lcudart
.最后,剩下的问题是link-order个问题。简而言之,需要在linker命令行中从左到右满足link依赖。不同的编译器或多或少对此很挑剔。最终的重新排序更改是以正确的顺序指定 link 反对的库,并且还在 link 命令行的末尾指定这些库,以便对这些库的任何依赖性,到它们留在link命令行,都满意了。