尝试一起编译多个CUDA文件时链接错误LNK2005

我有一个工作正常的CUDA程序,但目前所有程序都写在一个文件中。 我想将这个大文件拆分成几个较小的文件,以便更容易维护和导航。

新结构是:

foo.cuh foo.cu bar.cuh bar.cu main.cu 

.cuh头文件包含结构和函数原型, .cu文件包含函数定义(像往常一样)。 主文件包括bar.cuhbar.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文件的方法:

  1. 在Visual Studio“解决方案资源管理器”窗口中,右键单击源文件并选择“属性”。

  2. 在属性树中,选择“C / C ++”,“预处理器”。

  3. 将“生成预处理文件”从“否”更改为其他选项之一。

  4. 然后编译该文件。 编译器会将预处理器输出写入文件,然后在不进行实际编译的情况下停止。 您可以在.i文件中看到所有宏扩展的最终结果。

  5. 您将不得不返回并将该属性重置为“否”,以使项目能够使编译器再次正常工作。

您是否需要链接cutil库(即cutil32D.lib用于32位调试等)?

出于某种原因,您有多个定义。 您是否使用NVIDIA Cuda.rules文件使Visual Studio能够将.cu文件编译为.obj文件? 看起来您已经修改了规则以与cutil链接,而您应该使用NVIDIA Cuda.rules告诉VS如何编译.cu到.obj,然后修改标准链接器属性以引入cutil库。