我有一个包含我的cuda内核的.cu文件,以及一个调用内核的包装函数。我有一堆.c文件,其中一个包含main函数。其中一个.c文件从.cu调用包装器函数来调用内核。
我按如下方式编译这些文件:
LIBS=-lcuda -lcudart
LIBDIR=-L/usr/local/cuda/lib64
CFLAGS = -g -c -Wall -Iinclude -Ioflib
NVCCFLAGS =-g -c -Iinclude -Ioflib
CFLAGSEXE =-g -O2 -Wall -Iinclude -Ioflib
CC=gcc
NVCC=nvcc
objects := $(patsubst oflib/%.c,oflib/%.o,$(wildcard oflib/*.c))
table-hash-gpu.o: table-hash.cu table-hash.h
$(NVCC) $(NVCCFLAGS) table-hash.cu -o table-hash-gpu.o
main: main.c $(objects) table-hash-gpu.o
$(CC) $(CFLAGSEXE) $(objects) table-hash-gpu.o -o udatapath udatapath.c $(LIBS) $(LIBDIR)
到目前为止一切都很好。 table-hash-gpu.cu从其中一个.c文件中调用一个函数。当链接为main时,我得到函数不存在的错误。有人可以告诉我发生了什么事吗?
答案 0 :(得分:2)
nvcc使用主机C ++编译器编译设备和主机代码,这意味着name mangling。如果需要在C ++中调用用C编译器编译的函数,则必须告诉C ++编译器它使用C调用约定。我认为你看到的错误类似于:
$ cat cfunc.c
float adder(float a, float b, float c)
{
return a + 2.f*b + 3.f*c;
}
$ cat cumain.cu
#include <cstdio>
float adder(float, float, float);
int main(void)
{
float result = adder(1.f, 2.f, 3.f);
printf("%f\n", result);
return 0;
}
$ gcc -m32 -c cfunc.c
$ nvcc -o app cumain.cu cfunc.o
Undefined symbols:
"adder(float, float, float)", referenced from:
_main in tmpxft_0000b928_00000000-13_cumain.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
这里我们有用nvcc编译的代码(所以主机C ++编译器)试图调用C函数并获得链接错误,因为C ++代码在所提供的目标文件中需要adder
的错位名称。如果主要改变如下:
$ cat cumain.cu
#include <cstdio>
extern "C" float adder(float, float, float);
int main(void)
{
float result = adder(1.f, 2.f, 3.f);
printf("%f\n", result);
return 0;
}
$ nvcc -o app cumain.cu cfunc.o
$ ./app
14.000000
有效。使用extern "C"
来限定函数声明到C ++编译器,它在引用adder
时不会使用C ++修改和链接规则,并且生成的代码链接正确。