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

时间:2009-12-29 19:51:54

标签: c visual-studio-2008 refactoring cuda linker-errors

我有一个工作正常的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 <cutil_inline.h>

int main() [...]

// bar.cu
#include "bar.cuh"
#include "foo.cuh"
#include <cutil_inline.h>

[...]

// foo.cu
#include "foo.cuh"
#include <cutil_inline.h>

[...]

问题是,当我用这个新结构编译我的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的文件中是未知的(正如预期的那样,但我必须尝试所有内容)   - 列出项目

4 个答案:

答案 0 :(得分:4)

我的程序中也发生了此错误。我通过在inline__global__之前添加关键字__device__来解决此问题。然后,错误就消失了。

答案 1 :(得分:2)

不知何故,cutil_inline.h中的函数在编译时不会被标记为“内联”。

如果你在普通的非Cuda C ++项目中遇到这个错误,答案就是你在头文件中有函数定义(不仅仅是声明)而且缺少“inline”关键字。

你可能必须生成相应的.i文件(预处理器)输出才能真正看到所有宏扩展后发生了什么。

EDIT 1/2/2009

如果通过读取.h文件无法弄清楚是什么问题,由于某些宏扩展混淆,以下是生成.i文件的方法:

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

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

  3. 更改“生成预处理 文件“从”否“到另一个 选项。

  4. 然后编译该文件。编译器 将写入预处理器输出 到一个文件然后停止没有 实际编译。你可以看到 .i文件产生了最后的结果 所有宏扩展的结果都是。

  5. 您必须返回并重置 该属性按顺序返回“否” 将项目编译到 再次正常工作。

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

请考虑使用“静态”而不是“内联”,以避免在编译过程中出现警告。根据{{​​3}}的结果,导致此错误的原因是this answer.

但是,这很可能是由于将.cuh文件(包含内核)包含到普通的.h文件中引起的。要么:

  • 制作一个单独的dll,其中填充了您的.cuh.cu文件,并针对该文件进行链接;

  • ,或者将.h文件重命名为.cuh,将.cpp重命名为cu。对于此选项,请确保也执行以下操作:discussed here:

  

在.cu文件(刚刚重命名)的上下文菜单中,选择“属性”。然后转到常规,并确保将项目类型设置为CUDA C / C ++。

提醒您,第二个选项会使您的项目编译慢很多(编译慢4倍)