我正在尝试将一个CUDA程序分成两个独立的.cu文件,以便更接近使用C++编写真实应用程序。一个简单的程序需要:
在主机和设备上分配内存。
将主机数组初始化为一系列数字。
将主机数组复制到设备数组
使用设备核函数找到数组中所有元素的平方
将设备数组复制回主机数组
打印结果
如果我把所有内容放在一个.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 *)" (?TestDevice__entry@@YAXPEAH@Z) 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,并从那里启动应用程序。在我的.cpp代码的某些点上,我想能够引用CUDA库。 因此,我的想法是将CUDA内核代码放入它们自己的.cu文件中,然后有一个支持性的.cu文件来处理与设备的通信以及调用内核函数等事项。
void TestDeviceWrapper(dim3 grid, dim3 block, int *devicearray)
,因为当 KernelSupport.cu 变为 KernelSupport.cpp 时,cl.exe 将无法理解 global 语法。然后在 MyKernel.cu 中,TestDeviceWrapper()
只需调用TestDevice<<<>>>
。 - Tom