使用 nvcc 编译依赖的 .c 和 .cu 文件

Compiling dependent .c and .cu files with nvcc

我希望将一些用常规旧 C 语言编写的主机辅助函数包含在 .cu 文件中,该文件运行一些主机代码并定义和调用内核函数。我对 makefile 一无所知,对一般的多文件项目也没有很好的感觉,并且无法理解为什么以下内容适用于 .c 扩展名但无法使用 .cu 扩展名。

A.h

void sayhello();

A.c:

#include "A.h"
#include <stdio.h>
void sayhello() {
    printf("Hello from A\n");
}

B.c:

#include "A.h"
int main(int argc, char * argv) {
    sayhello();
    return 0;
}

B.cu

#include "A.h"
int main(int argc, char * argv[]) {
    sayhello();
    return 0;
}

当我编译 A.c 时一切正常:

$ nvcc -arch compute_30 -code sm_30 -o test B.c A.c  
$ ./test  
Hello from A

但是当试图编译 B.cu 链接器找不到 sayhello()

$ nvcc -o test B.cu A.c  
/tmp/tmpxft_000017bb_00000000-16_B.o: In function 'main':
tmpxft_000017bb_00000000-4_B.cudafe1.cpp:(.text+0x26): undefined reference to 'sayhello()'
collect2: error: ld returned 1 exit status

为什么找不到sayhello(),这些编译有什么区别,有没有办法编译这种结构的代码?

您需要在 sayhello 函数上使用 __host__ __device__ 修饰。

此外,在 A.h

中包含 cuda_runtime.h

CUDA 使用 C++ 编译器编译 .cu 文件。因此,它期望 .cu 文件中引用的所有函数都具有 C++ 链接,除非另有明确说明。在您的情况下,您必须明确指示 C++ 编译器。

您应该发现像这样修改您的代码:

extern "C" { 
#include "A.h"
}
int main(int argc, char * argv[]) {
    sayhello();
    return 0;
}

将解决问题,因为它会指示编译器期望 C 函数的 C 链接,而不是 C++ 链接。