使用 g++ 编译器与 CUDA 目标文件链接的 Makefile

Makefile linking using g++ compiler with CUDA object files

我正在尝试使用 nvcc 编译 cuda 目标文件,并使用 g++ 编译器编译最终的主脚本。我已经看到 this post 但无法让我的示例正常工作。我得到的错误似乎是链接错误:

nvcc -c -g -I -dlink -I/usr/local/cuda-11/include -I. -L/usr/local/cuda-11/lib64 -lcudart -lcurand module.cu -o module.o 
g++ -I/usr/local/cuda-11/include -I. -L/usr/local/cuda-11/lib64 -lcudart -lcurand module.o main.cpp -o main
module.o: In function `call_kernel()':
/home/ubuntu/Desktop/CUDA/MPI&CUDA/module.cu:16: undefined reference to `__cudaPushCallConfiguration'
module.o: In function `__cudaUnregisterBinaryUtil()':
/usr/local/cuda-11/include/crt/host_runtime.h:259: undefined reference to `__cudaUnregisterFatBinary'
module.o: In function `__nv_init_managed_rt_with_module(void**)':
/usr/local/cuda-11/include/crt/host_runtime.h:264: undefined reference to `__cudaInitModule'

我做错了什么?我知道我可以简单地用 nvcc 编译 main.cpp 但这是我不想要的,因为在我的问题中,我稍后会用 mpicxx 替换 g++ 并且有我的 main.cpp 脚本中的 MPI 代码。

我的 makefile 是:

INC := -I$(CUDA_HOME)/include -I.
LIB := -L$(CUDA_HOME)/lib64 -lcudart -lcurand
CUDAFLAGS=-c -g -I -dlink $(INC) $(LIB)

all: main

main: module.o
    g++ $(INC) $(LIB) module.o main.cpp -o main

module.o: module.cu module.h 
    nvcc -c -g -I -dlink $(INC) $(LIB) module.cu -o module.o 

clean: 
    rm -rf *.o

main.cpp

#include "module.h"

int main(){

    return 0;
}

module.cu

#ifdef __CUDACC__
#define CUDA_GLOBAL __global__
#else
#define CUDA_GLOBAL
#endif

#include <cuda.h>
#include "module.h"

CUDA_GLOBAL
void kernel(){

}

void call_kernel(){
    kernel<<<1,1>>>();
}

module.h

#ifndef _MODULE_H_
#define _MODULE_H_

#ifdef __CUDACC__
#define CUDA_GLOBAL __global__
#else
#define CUDA_GLOBAL
#endif

#include <numeric>
#include <cuda.h>

CUDA_GLOBAL
void kernel();

void call_kernel();

#endif

您的 link 行有误。所有库(例如 -lfoo)必须位于 link 行的 end 处,位于所有目标文件(例如 .o 文件)之后。

不仅如此,它们还需要正确排序(但我不知道正确的顺序是什么所以也许上面是正确的)。

几乎所有现代 linker 都是“单程”linker,这意味着他们只通过图书馆一次,并且由于他们只提取符号,因为他们已经需要你必须首先为您的库排序“最高级别”的内容,然后是“较低级别”的内容。

感谢 MadScientist 的解释,linkages 必须在 link 行的末尾完成,毕竟 .o 个文件:

INC := -I$(CUDA_HOME)/include -I.
LIB := -L$(CUDA_HOME)/lib64 -lcudart -lcurand

all: main

main: module.o
    mpicxx module.o main.cpp -o main $(INC) $(LIB)

module.o: module.cu module.h 
    nvcc -c -g module.cu -o module.o -I -dlink

clean: 
    rm -rf *.o