尝试一起编译多个CUDA文件时链接错误LNK2005
我有一个工作正常的CUDA程序,但目前所有程序都写在一个文件中。 我想将这个大文件拆分成几个较小的文件,以便更容易维护和导航。
新结构是:
foo.cuh foo.cu bar.cuh bar.cu main.cu
.cuh
头文件包含结构和函数原型, .cu
文件包含函数定义(像往常一样)。 主文件包括bar.cuh
, bar.cu
包括foo.cuh
。 所有.cu文件都包含cutil_inline.h,以便能够使用CUDA函数。
因此:
// main.cu #include "bar.cuh" #include int main() [...] // bar.cu #include "bar.cuh" #include "foo.cuh" #include [...] // foo.cu #include "foo.cuh" #include [...]
问题是当我用这个新结构编译我的Visual Studio 2008项目时,我遇到了大量的链接错误:
error LNK2005: "void __cdecl __cutilBankChecker(unsigned int,unsigned int,unsigned int,unsigned int,unsigned int,unsigned int,char *,int,char *,int)" (?__cutilBankChecker@@YAXIIIIIIPADH0H@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj error LNK2005: "void __cdecl __cutilCondition(int,char *,int)" (?__cutilCondition@@YAXHPADH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj error LNK2005: "void __cdecl __cutilExit(int,char * *)" (?__cutilExit@@YAXHPAPAD@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj error LNK2005: "int __cdecl cutGetMaxGflopsDeviceId(void)" (?cutGetMaxGflopsDeviceId@@YAHXZ) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj error LNK2005: "void __cdecl __cudaSafeCallNoSync(enum cudaError,char const *,int)" (?__cudaSafeCallNoSync@@YAXW4cudaError@@PBDH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj error LNK2005: "void __cdecl __cudaSafeCall(enum cudaError,char const *,int)" (?__cudaSafeCall@@YAXW4cudaError@@PBDH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj error LNK2005: "void __cdecl __cudaSafeThreadSync(char const *,int)" (?__cudaSafeThreadSync@@YAXPBDH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj error LNK2005: "void __cdecl __cufftSafeCall(enum cufftResult_t,char const *,int)" (?__cufftSafeCall@@YAXW4cufftResult_t@@PBDH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj
我理解他们的意思(所有已经定义的符号都是cutil_inline.h的一部分)但是我必须在所有文件中包含这个头,否则它不会编译。 我究竟做错了什么 ?
更新:澄清情况:*所有代码都在一个大文件中,它编译,链接并运行良好*与新结构(几个较小的文件)并在所有.cu文件中包括cutil_inline.h,它正确编译但在失败期间失败链接*与新结构,并且仅在主文件中包含cutil_inline.h,它在编译期间失败,说cutil函数在未包含cutil_inline.h的文件中是未知的(正如预期的那样,但我必须尝试所有内容) – 项目清单
这个错误也发生在我的程序中。 我通过在__global__
或__device__
之前添加关键字inline
来解决它。 然后,错误就消失了。
不知何故,cutil_inline.h中的函数在编译时不会被标记为“内联”。
如果你在一个普通的非Cuda C ++项目中遇到这个错误,答案就是你在头文件中有函数定义(不仅仅是声明)而且缺少“inline”关键字。
您可能必须生成相应的.i文件(预处理器)输出才能真正看到所有宏扩展后发生的情况。
编辑1/2/2009
如果你只是通过读取.h文件就无法弄清楚是什么问题,因为有一些宏扩展混淆,这里是你生成.i文件的方法:
-
在Visual Studio“解决方案资源管理器”窗口中,右键单击源文件并选择“属性”。
-
在属性树中,选择“C / C ++”,“预处理器”。
-
将“生成预处理文件”从“否”更改为其他选项之一。
-
然后编译该文件。 编译器会将预处理器输出写入文件,然后在不进行实际编译的情况下停止。 您可以在.i文件中看到所有宏扩展的最终结果。
-
您将不得不返回并将该属性重置为“否”,以使项目能够使编译器再次正常工作。
您是否需要链接cutil库(即cutil32D.lib用于32位调试等)?
出于某种原因,您有多个定义。 您是否使用NVIDIA Cuda.rules文件使Visual Studio能够将.cu文件编译为.obj文件? 看起来您已经修改了规则以与cutil链接,而您应该使用NVIDIA Cuda.rules告诉VS如何编译.cu到.obj,然后修改标准链接器属性以引入cutil库。