CUDA的文件组织形式:
1. CUDA工程中可以有.cu和.cpp。
2. 在.cu文件中,可以用#include "cuda_x.cuh"来相互调用.cu里的函数,也可以调用 #include "cpp_x.h".
比如在test1.h 中声明class A; 在test1.cpp中定义class A的相关成员函数。那么在cuda_xx.cu中,先 #include "test1.h",然后在定义 extern "C" void foo(...){ A aa; aa.memberfunc(...); } 可以使用,而extern "C" 的定义是为.cpp文件调用foo函数做准备。 如果没有extern "C" 则报错:“无法解析的外部符号 _foo,该符号在函数 _main 中被引用”。
在其他的.cu中定义的 __global__ 函数,可以放到.cuh文件中,共其他.cu调用。但是,不是cuda提供的函数形式(比如C语言形式的函数),则必须要使用extern "C" 。此时,可以不要在.cuh文件中声明,直接在.cu文件中定义,而其他.cu文件调用时,在调用之前用extern "C" int foo(......);声明一下。而调用foo的函数(比如说是foo2)也需要用extern "C"来修饰。
3.在.cpp文件中,可以使用.cu文件中的声明为extern "C"的函数。在.cpp文件调用前,需要用extern "C" +函数声明再声明一次。即.cu中,函数定义时需要用extern "C" 修饰。在.cpp调用时,也需要用extern "C" 来修饰。而.cpp中是不能直接调用__global__函数的,因为编译器是无法解析符号<<<......>>>以及blockIdx、threadIdx等,因此__global__函数只能放在.cu函数里面定义和调用。
4. 有点麻烦吧?呵呵。用extern "C" 修饰的原因,就是.cu是扩展C,但只是部分只是cpp,所以需要定义为类C语言编译(NVCC.exe编译)。
5. 看SDK给出的例子,在比如在cuda1.cu中可以调用cuda2.cu中定义的__global__函数。但是我弄了半天却报错说:
1>正在链接...
1>CUDA2.cu.obj : error LNK2005: ___device_stub__Z14colsSumCUDA232PfS_ii 已经在 CUDA1.cu.obj 中定义
1>CUDA2.cu.obj : error LNK2005: "void __cdecl colsSumCUDA232__entry(float *,float *,int,int)" (?colsSumCUDA232__entry@@YAXPAM0HH@Z) 已经在 CUDA1.cu.obj 中定义
1>http://www.cnblogs.com/bin/win32/Debug/deviceQuery.exe : fatal error LNK1169: 找到一个或多个多重定义的符号
检查了半天,才发现,原来cuda2.cu(其中定义了GPU的kernel函数)在【属性】中需要将cuda2.cu设置为“从生成中排除”。