2011-05-16 96 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