我試圖將CUDA程序分離爲兩個單獨的.cu文件,以便更接近於在C++中編寫真實應用程序。我有一個簡單的小程序:如何將CUDA代碼分離爲多個文件
在主機和設備上分配內存。
將主機數組初始化爲一系列數字。 複製主機陣列的設備陣列 發現陣列中的所有元素的使用設備的內核 複製器件陣列回主陣列 打印結果
,如果我把它所有的這個偉大的工程方在一個.cu文件中並運行它。當我將它分成兩個單獨的文件時,我開始出現鏈接錯誤。就像我最近的所有問題一樣,我知道這很小,但它是什麼?
KernelSupport.cu
#ifndef _KERNEL_SUPPORT_
#define _KERNEL_SUPPORT_
#include <iostream>
#include <MyKernel.cu>
int main(int argc, char** argv)
{
int* hostArray;
int* deviceArray;
const int arrayLength = 16;
const unsigned int memSize = sizeof(int) * arrayLength;
hostArray = (int*)malloc(memSize);
cudaMalloc((void**) &deviceArray, memSize);
std::cout << "Before device\n";
for(int i=0;i<arrayLength;i++)
{
hostArray[i] = i+1;
std::cout << hostArray[i] << "\n";
}
std::cout << "\n";
cudaMemcpy(deviceArray, hostArray, memSize, cudaMemcpyHostToDevice);
TestDevice <<< 4, 4 >>> (deviceArray);
cudaMemcpy(hostArray, deviceArray, memSize, cudaMemcpyDeviceToHost);
std::cout << "After device\n";
for(int i=0;i<arrayLength;i++)
{
std::cout << hostArray[i] << "\n";
}
cudaFree(deviceArray);
free(hostArray);
std::cout << "Done\n";
}
#endif
MyKernel.cu
#ifndef _MY_KERNEL_
#define _MY_KERNEL_
__global__ void TestDevice(int *deviceArray)
{
int idx = blockIdx.x*blockDim.x + threadIdx.x;
deviceArray[idx] = deviceArray[idx]*deviceArray[idx];
}
#endif
生成日誌:
1>------ Build started: Project: CUDASandbox, Configuration: Debug x64 ------
1>Compiling with CUDA Build Rule...
1>"C:\CUDA\bin64\nvcc.exe" -arch sm_10 -ccbin "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin" -Xcompiler "/EHsc /W3 /nologo /O2 /Zi /MT " -maxrregcount=32 --compile -o "x64\Debug\KernelSupport.cu.obj" "d:\Stuff\Programming\Visual Studio 2008\Projects\CUDASandbox\CUDASandbox\KernelSupport.cu"
1>KernelSupport.cu
1>tmpxft_000016f4_00000000-3_KernelSupport.cudafe1.gpu
1>tmpxft_000016f4_00000000-8_KernelSupport.cudafe2.gpu
1>tmpxft_000016f4_00000000-3_KernelSupport.cudafe1.cpp
1>tmpxft_000016f4_00000000-12_KernelSupport.ii
1>Linking...
1>KernelSupport.cu.obj : error LNK2005: __device_stub__Z10TestDevicePi already defined in MyKernel.cu.obj
1>KernelSupport.cu.obj : error LNK2005: "void __cdecl TestDevice__entry(int *)" ([email protected]@[email protected]) already defined in MyKernel.cu.obj
1>D:\Stuff\Programming\Visual Studio 2008\Projects\CUDASandbox\x64\Debug\CUDASandbox.exe : fatal error LNK1169: one or more multiply defined symbols found
1>Build log was saved at "file://d:\Stuff\Programming\Visual Studio 2008\Projects\CUDASandbox\CUDASandbox\x64\Debug\BuildLog.htm"
1>CUDASandbox - 3 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
我在Windows 7上運行64位的Visual Studio 2008。
編輯:
我想我需要闡述這一點。我在這裏尋找的最終結果是有一個正常的C++應用程序,它具有類似於Main.cpp的int main()
事件,並從那裏運行。在我的.cpp代碼中的特定點處,我希望能夠引用CUDA位。所以我的想法(並糾正我,如果這裏有一個更標準的約定)是我將把CUDA內核代碼放入它們的.cu文件中,然後有一個支持.cu文件,它將負責與設備通話並呼叫內核函數和什麼不是。
請詳細說明一個簡單的代碼示例 – 2010-01-19 05:38:47
由於當KernelSupport.cu變成KernelSupport.cpp時,MyKernel.h應該有'void TestDeviceWrapper(dim3 grid,dim3 block,int * devicearray)'cl.exe不會理解__global__句法。然後在MyKernel.cu中,'TestDeviceWrapper()'只是調用'TestDevice <<<> >>'。 – Tom 2010-01-19 08:34:22
這聽起來很合理,給出的代碼假定它將包含在cuda文件中,如問題中給出的那樣。 – 2010-01-19 09:13:17