Я пытаюсь разделить программу 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 ==========
Я использую Visual Studio 2008 в 64-разрядной версии Windows 7.
Edit:
Думаю, мне нужно немного подробнее остановиться на этом. Конечный результат, который я здесь ищу, - это иметь нормальное приложение C ++ с чем-то вроде Main.cpp с событием int main()
и запускать его оттуда. В определенный момент в моем коде .cpp я хочу иметь возможность ссылаться на биты CUDA. Поэтому я думаю (и поправьте меня, если здесь есть более стандартное соглашение), что я добавлю код ядра CUDA в их файлы .cu, а затем получу вспомогательный файл .cu, который позаботится о том, чтобы поговорить с устройством и вызвать функции ядра, а что нет.