我有一个工作正常的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 <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的文件中是未知的(正如预期的那样,但我必须尝试所有内容) - 列出项目
答案 0 :(得分:4)
我的程序中也发生了此错误。我通过在inline
或__global__
之前添加关键字__device__
来解决此问题。然后,错误就消失了。
答案 1 :(得分:2)
不知何故,cutil_inline.h中的函数在编译时不会被标记为“内联”。
如果你在普通的非Cuda C ++项目中遇到这个错误,答案就是你在头文件中有函数定义(不仅仅是声明)而且缺少“inline”关键字。
你可能必须生成相应的.i文件(预处理器)输出才能真正看到所有宏扩展后发生了什么。
EDIT 1/2/2009
如果通过读取.h文件无法弄清楚是什么问题,由于某些宏扩展混淆,以下是生成.i文件的方法:
在Visual Studio“解决方案中 资源管理器“窗口,右键单击 源文件并选择“属性”。
在属性树中,选择 “C / C ++”,“预处理器”。
更改“生成预处理 文件“从”否“到另一个 选项。
然后编译该文件。编译器 将写入预处理器输出 到一个文件然后停止没有 实际编译。你可以看到 .i文件产生了最后的结果 所有宏扩展的结果都是。
您必须返回并重置 该属性按顺序返回“否” 将项目编译到 再次正常工作。
答案 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倍)