2011-05-16 61 views
1

我已经从linux移植了一个cuda项目到windows(基本上只是在头文件中添加了几个定义和typedefs)。我使用Visual Studio 2008,以及SDK中的cuda运行时api自定义构建规则。代码是C,而不是C++(我正在编译/ TC不是/ TP)windows cuda项目中的无效资源

我遇到了我在linux中没有的范围问题。我的头文件中的全局变量不在.c文件和.cu文件之间共享。

我创建了一个简单的项目,这里是所有的代码:

main.h:

#ifndef MAIN_H 
#define MAIN_H 

#include <stdio.h> 
#include <cuda.h> 
#include <cuda_runtime.h> 

cudaEvent_t cudaEventStart; 

#if defined __cplusplus 
extern "C" void func(void); 
#else 
extern void func(void); 
#endif 

#endif 

的main.c:

#include "main.h" 

int main(void) 
{ 
    int iDevice = 0; 

    cudaSetDevice(iDevice); 
    cudaFree(0); 
    cudaGetDevice(&iDevice); 
    printf("device: %d\n", iDevice); 

    cudaEventCreate(&cudaEventStart); 
    printf("create event: %d\n", (int) cudaEventStart); 

    func(); 

    cudaEventDestroy(cudaEventStart); 
    printf("destroy event: %d\n", (int) cudaEventStart); 

    return cudaThreadExit(); 
} 

kernel.cu:

#include "main.h" 

void func() 
{ 
    printf("event in cu: %d\n", (int) cudaEventStart); 
} 

输出:

device: 0 
create event: 44199920 
event in cu: 0 
event destroy: 441999920 

有关我在做什么错的任何想法吗?我该如何改变我的设置才能在Visual Studio中使用?理想情况下,我想要一个多平台的设置。

CUDA 3.2,GTX 480,64位的Win7,263.06一般

回答

1

你正在尝试做

  1. 不会没有CUDA连工作 - 尝试重命名kernel.cu到kernel.c并重新编译。你会得到一个链接错误,因为cudaEventStart将被多重定义 - 在包含它的每个编译单元(.c文件)中。您需要将变量设置为静态,并仅在一个编译单元中对其进行初始化。
  2. 在CUDA中编译,因为CUDA没有链接器,因此编译单元中由nvcc(.cu文件)编译的代码不能引用其他编译单元中的符号。 CUDA目前不支持静态全局变量。未来CUDA将有一个链接器,但目前它没有。

发生了什么是每个编译单元正在获取它自己的非冲突实例cudaEventStart

您可以做的是摆脱全局变量(使其成为main()中的局部变量),将cudaEvent_t参数添加到需要使用该事件的函数中,然后传递该事件变量。

顺便说一句,在你的第二个职位,你有圆形#include小号...

+0

@harrism感谢这一点。你暗示这个设置无论如何都不会起作用,但它在我的linux版本中起作用。其次,请不要包括警卫阻止通知包括?事实上,在我的真实项目中,头球也包括守卫。 – jmilloy 2011-05-17 03:02:13

+0

@harrism包括卫兵在linux和visual studio中的工作方式可能不同吗?也许在visual studio中,nvcc无法从cl.exe中看到定义,反之亦然,导致两个cudaEventStart实例。而在Linux中,守卫在两个编译器上都能工作,防止所有全局变量的双重实例? – jmilloy 2011-05-17 03:07:11

+0

我不是暗示,我说。 :)目前,您不能以这种方式在CUDA编译单元和C++编译单元之间共享全局变量。如果您按照我的建议将kernel.cu重命名为kernel.c,您将*从g ++中得到如下链接器错误:“ld:duplicate symbol _foo in ...”。 至于通知包括,它可能会工作,但它不是一个好的编程习惯。另外,请注意,在任何编译器中,包括守护程序都不能在编译单元中工作,它们只会阻止两次将相同的头文件包含到同一个编译单元中。每个.c或.cu文件都是一个单独的编译单元。 – harrism 2011-05-17 03:22:02

0

我通过包括在报头中的文件.CU并除去.CU的前向声明修改了简化的示例(成功)文件功能。

main.h:

#include <stdio.h> 
#include <cuda.h> 
#include <cuda_runtime.h> 

#include "kernel.cu" 

cudaEvent_t cudaEventStart; 

main.c中:

#include "main.h" 

int main(void) 
{ 
    int iDevice = 0; 

    cudaSetDevice(iDevice); 
    cudaFree(0); 
    cudaGetDevice(&iDevice); 
    printf("device: %d\n", iDevice); 

    cudaEventCreate(&cudaEventStart); 
    printf("create event: %d\n", (int) cudaEventStart); 

    func(); 

    cudaEventDestroy(cudaEventStart); 
    printf("destroy event: %d\n", (int) cudaEventStart); 

    return cudaThreadExit(); 
} 

kernel.cu:

#ifndef KERNEL_CU 
#define KERNEL_CU 

#include "main.h" 

void func(void); 

void func() 
{ 
    printf("event in cu: %d\n", (int) cudaEventStart); 
} 

#endif 

输出:

device: 0 
create event: 42784024 
event in cu: 42784024 
event destroy: 42784024 

关于查看它是否适用于我的真实项目,以及解决方案是否可移植回Linux。

+0

和调查说,没了......许多变化后,在我的实际项目中的.CU文件不进行编译。 'blockDim undefined idenfifier','__syncthreads undefined'等 – jmilloy 2011-05-16 22:48:12