2012-09-04 121 views
0

我有一個包含我的cuda內核的.cu文件和一個調用內核的包裝函數。我也有一堆.c文件,其中一個包含主要功能。其中一個.c文件調用.cu的包裝函數來調用內核。鏈接cuda目標文件

我編譯這些文件如下:

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文件中調用一個函數。當爲主要鏈接時,我得到該函數不存在的錯誤。有人可以告訴我發生了什麼事嗎?

+0

哪個函數不存在?它是不存在的內核嗎? – ATG

回答

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++修改和鏈接規則。