4

我有一个运行良好的 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

4 回答 4

4

这个错误也发生在我的程序中。我通过在orinline之前添加关键字来解决它。然后,错误消失了。__global____device__

于 2012-09-20T02:16:33.833 回答
2

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

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

您可能必须生成相应的 .i 文件(预处理器)输出才能真正了解所有宏扩展后发生的情况。

编辑 2009 年 1 月 2 日

如果由于某些宏扩展混淆,您无法仅通过读取 .h 文件找出问题所在,以下是生成 .i 文件的方法:

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

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

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

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

  5. 您必须返回并将该属性重置为“否”,以便让项目编译器再次正常工作。

于 2009-12-30T19:15:25.443 回答
0

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

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

于 2009-12-30T10:09:35.330 回答
0

考虑使用 'static' 而不是 'inline' 以避免在编译期间出现警告。那是根据这个答案。此处讨论了此错误的原因

但是,这很可能是由于将.cuh文件(包含您的内核)包含到普通.h文件中而引起的。任何一个:

在 .cu 文件(您刚刚重命名的文件)的上下文菜单中,选择属性。然后转到 General 并确保 Item Type 设置为 CUDA C/C++。

请注意,第二个选项会使您的项目编译速度慢很多(编译速度慢 4 倍)

于 2019-03-01T14:57:02.810 回答