I have a class-based C++ code similar to this and have followed the structure for declaring a __device__
method of the class. I have also gone to Project Properties-> CUDA C/C++ -> Common -> Generate Relocatable Device Code
and changed it to YES but here it says the linking options need modifying and I do not understand how to do this in the VS options from this information . How do I do this to get it to link?
**Removed VC studio settings in original post as not relevant**
Test code is:
kernel.cu
#include "Test.cuh"
// CUDA kernel
__global__ void myKernel(Test* t) {
// Call device function
t->device_function();
}
// Entry point
int main()
{
// Create object (host and device copies)
Test* t = new Test();
Test* t_dev = NULL;
cudaMalloc(&t_dev, sizeof(Test));
// Copy object
cudaMemcpy(t_dev,t,sizeof(Test),cudaMemcpyHostToDevice);
// Call kernel passing pointer to device copy of the object
myKernel<<<1,1>>>(t_dev);
}
Test.cuh
class Test
{
public:
Test(void);
~Test(void);
__device__ void device_function();
};
Test.cu
#include "Test.cuh"
Test::Test(void){}
Test::~Test(void){}
__device__ void Test::device_function() {
// Do something
}
EDIT
Adding compilation log as I think it might not be compiling the device implementation properly.
1> C:\C++ Projects\CudaTest\CudaTest>"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nvcc.exe" -ccbin "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include" --keep-dir Release -maxrregcount=0 --machine 32 --compile -DWIN32 -DNDEBUG -D_CONSOLE -D_MBCS -Xcompiler "/EHsc /W3 /nologo /O2 /Zi /MD " -o Release\kernel.cu.obj "C:\C++ Projects\CudaTest\CudaTest\kernel.cu" -clean
1> kernel.cu
1> Compiling CUDA source file kernel.cu...
1>
1> C:\C++ Projects\CudaTest\CudaTest>"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nvcc.exe" -gencode=arch=compute_20,code=\"sm_20,compute_20\" --use-local-env --cl-version 2012 -ccbin "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin" -rdc=true -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include" --keep-dir Release -maxrregcount=0 --machine 32 --compile -cudart static -DWIN32 -DNDEBUG -D_CONSOLE -D_MBCS -Xcompiler "/EHsc /W3 /nologo /O2 /Zi /MD " -o Release\kernel.cu.obj "C:\C++ Projects\CudaTest\CudaTest\kernel.cu"
1> kernel.cu
1> Test.cu
1>
1> C:\C++ Projects\CudaTest\CudaTest>"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nvcc.exe" -dlink -o Release\CudaTest.device-link.obj -Xcompiler "/EHsc /W3 /nologo /O2 /Zi /MD " -L"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\lib\Win32" cudart.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib -gencode=arch=compute_20,code=sm_20 --machine 32 Release\kernel.cu.obj
1> CUDALINK : nvlink error : Undefined reference to '_ZN4Test15device_functionEv' in 'Release/kernel.cu.obj'`
OK, so VS with the CUDA plug-in has two different Item Type
s that it catalogues differently, a CUDA C/C++ source/header file
and a C/C++ source/header
and you cannot simply convert one to another by renaming *.cpp
to *.cu
which is what I was doing originally to try force it to compile the class into an object which I could link to.
I re-added the files Test.cpp
and Test.h
with exactly the same source code as Test.cu
and Test.cuh
respectively by right-clicking in the solution explorer and going to Add Item -> CUDA source/header file
and now it builds the kernel.cu
and the Test.cu/h
into two objects which are both supplied during the linking stage and the problem disappears.
Thanks to @talonmies for helping point me in the right direction.
EDIT
As I mentioned in the comments, you can simply rename the files if you still need to tell VS that they are now a different Item Type
. Originally I managed to do this by editing the *.vcxproj
file to tell the CUDA compiler to compile the renamed files. This is done by changing the <ItemGroup>
definitions like this:
<ItemGroup>
<CudaCompile Include="main.cu" />
<CudaCompile Include="RenamedSrcFile.cu" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="RenamedHeaderFile.cuh" />
<ClInclude Include="myOtherHeader.h" />
</ItemGroup>
This line <CudaCompile Include="RenamedSrcFile.cu" />
is the key and includes this file in the CUDA compile stage. Regular C++ files appear under the group <ClCompile>
although none are given in this example.
As indicated by Robert's comment you should never need to edit the *.vcxproj
file directly as VS will manage the file for you based on the options you select in VS. By (re-)adding the files as I did earlier, this swap is taken care of by VS.
EDIT2
As per Drop's suggestion in the comments, you may achieve this swap without re-adding files by right-clicking on the file in the solution explorer and under Properties->General
you may select the Item Type
to be a CUDA C/C++
rather than C/C++
to catalogue it correctly.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.