views:

2455

answers:

2

This post closely resembles my earlier post: http://stackoverflow.com/questions/2090974/how-to-separate-cuda-code-into-multiple-files/2092091#2092091 I am afraid I made such a blunder of what I was actually asking that it will be too confusing to try and correct it there.

I am basing this code loosely off the cppIntegration example from the CUDA SDK.

I want to have a main.cpp with my main() function and have it call to a separate .cu file to do some work on the GPU. In the separate .cu file I want it to be able to call to my kernel code that resides in another .cu file. I envision three files: Main.cpp, KernelWrapper.cu, and MyKernel.cu. Main.cpp for purposes of testing does nothing except call a function RunTest() that is located in KernelWrapper.cu. the RunTest() method executes the TestDevice(int *deviceArray) kernel that is located in MyKernel.cu

Main.cpp:

#include <iostream>

void RunTest(); //forward declaration???

int main( int argc, char** argv) 
{
    RunTest();
    std::cout << "blah\n";

    return 0;
}

KernelWrapper.cu:

#include <iostream>

__global__ void TestDevice(int *deviceArray); //forward declaration

void RunTest()
{
    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";
}

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

Which yields these errors:

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\KernelWrapper.cu.obj" "d:\Stuff\Programming\Visual Studio 2008\Projects\CUDASandbox\CUDASandbox\KernelWrapper.cu" 
1>KernelWrapper.cu
1>tmpxft_00001ab8_00000000-3_KernelWrapper.cudafe1.gpu
1>tmpxft_00001ab8_00000000-8_KernelWrapper.cudafe2.gpu
1>tmpxft_00001ab8_00000000-3_KernelWrapper.cudafe1.cpp
1>tmpxft_00001ab8_00000000-12_KernelWrapper.ii
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\MyKernel.cu.obj" "d:\Stuff\Programming\Visual Studio 2008\Projects\CUDASandbox\CUDASandbox\MyKernel.cu" 
1>MyKernel.cu
1>tmpxft_000017b0_00000000-3_MyKernel.cudafe1.gpu
1>tmpxft_000017b0_00000000-8_MyKernel.cudafe2.gpu
1>tmpxft_000017b0_00000000-3_MyKernel.cudafe1.cpp
1>tmpxft_000017b0_00000000-12_MyKernel.ii
1>Compiling...
1>Main.cpp
1>Compiling manifest to resources...
1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
1>Copyright (C) Microsoft Corporation.  All rights reserved.
1>Linking...
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: void __cdecl std::basic_ios<char,struct std::char_traits<char> >::setstate(int,bool)" (?setstate@?$basic_ios@DU?$char_traits@D@std@@@std@@QEAAXH_N@Z) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: __int64 __cdecl std::ios_base::width(__int64)" (?width@ios_base@std@@QEAA_J_J@Z) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: __int64 __cdecl std::basic_streambuf<char,struct std::char_traits<char> >::sputn(char const *,__int64)" (?sputn@?$basic_streambuf@DU?$char_traits@D@std@@@std@@QEAA_JPEBD_J@Z) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: static bool __cdecl std::char_traits<char>::eq_int_type(int const &,int const &)" (?eq_int_type@?$char_traits@D@std@@SA_NAEBH0@Z) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: static int __cdecl std::char_traits<char>::eof(void)" (?eof@?$char_traits@D@std@@SAHXZ) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: int __cdecl std::basic_streambuf<char,struct std::char_traits<char> >::sputc(char)" (?sputc@?$basic_streambuf@DU?$char_traits@D@std@@@std@@QEAAHD@Z) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: class std::basic_streambuf<char,struct std::char_traits<char> > * __cdecl std::basic_ios<char,struct std::char_traits<char> >::rdbuf(void)const " (?rdbuf@?$basic_ios@DU?$char_traits@D@std@@@std@@QEBAPEAV?$basic_streambuf@DU?$char_traits@D@std@@@2@XZ) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: char __cdecl std::basic_ios<char,struct std::char_traits<char> >::fill(void)const " (?fill@?$basic_ios@DU?$char_traits@D@std@@@std@@QEBADXZ) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: int __cdecl std::ios_base::flags(void)const " (?flags@ios_base@std@@QEBAHXZ) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: __int64 __cdecl std::ios_base::width(void)const " (?width@ios_base@std@@QEBA_JXZ) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: static unsigned __int64 __cdecl std::char_traits<char>::length(char const *)" (?length@?$char_traits@D@std@@SA_KPEBD@Z) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl std::basic_ostream<char,struct std::char_traits<char> >::flush(void)" (?flush@?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV12@XZ) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: class std::basic_ostream<char,struct std::char_traits<char> > * __cdecl std::basic_ios<char,struct std::char_traits<char> >::tie(void)const " (?tie@?$basic_ios@DU?$char_traits@D@std@@@std@@QEBAPEAV?$basic_ostream@DU?$char_traits@D@std@@@2@XZ) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: bool __cdecl std::ios_base::good(void)const " (?good@ios_base@std@@QEBA_NXZ) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: void __cdecl std::basic_ostream<char,struct std::char_traits<char> >::_Osfx(void)" (?_Osfx@?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAXXZ) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "bool __cdecl std::uncaught_exception(void)" (?uncaught_exception@std@@YA_NXZ) already defined in libcpmt.lib(uncaught.obj)
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: void __cdecl std::basic_streambuf<char,struct std::char_traits<char> >::_Lock(void)" (?_Lock@?$basic_streambuf@DU?$char_traits@D@std@@@std@@QEAAXXZ) already defined in KernelWrapper.cu.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: void __cdecl std::basic_streambuf<char,struct std::char_traits<char> >::_Unlock(void)" (?_Unlock@?$basic_streambuf@DU?$char_traits@D@std@@@std@@QEAAXXZ) already defined in KernelWrapper.cu.obj
1>MSVCRTD.lib(ti_inst.obj) : error LNK2005: "private: __cdecl type_info::type_info(class type_info const &)" (??0type_info@@AEAA@AEBV0@@Z) already defined in LIBCMT.lib(typinfo.obj)
1>MSVCRTD.lib(ti_inst.obj) : error LNK2005: "private: class type_info & __cdecl type_info::operator=(class type_info const &)" (??4type_info@@AEAAAEAV0@AEBV0@@Z) already defined in LIBCMT.lib(typinfo.obj)
1>LINK : warning LNK4098: defaultlib 'MSVCRTD' conflicts with use of other libs; use /NODEFAULTLIB:library
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 - 21 error(s), 1 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

I am running Visual Studio 2008 on Windows Vista 7 64 bit

Edit:

Tom, here is the build log that results from setting the code generation to /MT

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\MyKernel.cu.obj" "d:\Stuff\Programming\Visual Studio 2008\Projects\CUDASandbox\CUDASandbox\MyKernel.cu" 
1>MyKernel.cu
1>tmpxft_000019e4_00000000-3_MyKernel.cudafe1.gpu
1>tmpxft_000019e4_00000000-8_MyKernel.cudafe2.gpu
1>tmpxft_000019e4_00000000-3_MyKernel.cudafe1.cpp
1>tmpxft_000019e4_00000000-12_MyKernel.ii
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\KernelWrapper.cu.obj" "d:\Stuff\Programming\Visual Studio 2008\Projects\CUDASandbox\CUDASandbox\KernelWrapper.cu" 
1>KernelWrapper.cu
1>tmpxft_0000078c_00000000-3_KernelWrapper.cudafe1.gpu
1>tmpxft_0000078c_00000000-8_KernelWrapper.cudafe2.gpu
1>tmpxft_0000078c_00000000-3_KernelWrapper.cudafe1.cpp
1>tmpxft_0000078c_00000000-12_KernelWrapper.ii
1>Compiling...
1>Main.cpp
1>Linking...
1>LINK : warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library
1>libcpmtd.lib(cout.obj) : error LNK2019: unresolved external symbol _CrtDbgReportW referenced in function "public: char const & __cdecl std::_String_const_iterator<char,struct std::char_traits<char>,class std::allocator<char> >::operator*(void)const " (??D?$_String_const_iterator@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEBAAEBDXZ)
1>libcpmtd.lib(stdthrow.obj) : error LNK2001: unresolved external symbol _CrtDbgReportW
1>libcpmtd.lib(xmbtowc.obj) : error LNK2001: unresolved external symbol _CrtDbgReportW
1>libcpmtd.lib(xdebug.obj) : error LNK2019: unresolved external symbol _malloc_dbg referenced in function "void * __cdecl operator new(unsigned __int64,struct std::_DebugHeapTag_t const &,char *,int)" (??2@YAPEAX_KAEBU_DebugHeapTag_t@std@@PEADH@Z)
1>libcpmtd.lib(xmbtowc.obj) : error LNK2001: unresolved external symbol _malloc_dbg
1>libcpmtd.lib(xdebug.obj) : error LNK2019: unresolved external symbol _free_dbg referenced in function "void __cdecl operator delete(void *,struct std::_DebugHeapTag_t const &,char *,int)" (??3@YAXPEAXAEBU_DebugHeapTag_t@std@@PEADH@Z)
1>libcpmtd.lib(xmbtowc.obj) : error LNK2001: unresolved external symbol _free_dbg
1>libcpmtd.lib(_tolower.obj) : error LNK2019: unresolved external symbol _calloc_dbg referenced in function _Getctype
1>D:\Stuff\Programming\Visual Studio 2008\Projects\CUDASandbox\x64\Debug\CUDASandbox.exe : fatal error LNK1120: 4 unresolved externals
1>Build log was saved at "file://d:\Stuff\Programming\Visual Studio 2008\Projects\CUDASandbox\CUDASandbox\x64\Debug\BuildLog.htm"
1>CUDASandbox - 9 error(s), 1 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
+2  A: 

It looks like you have a conflict between two different versions of the C runtime. The CUDA runtime uses the statically linked C runtime, and your application uses the dynamically loaded C runtime (typically the default in Visual Studio).

Change the code generation to use statically loaded C runtime to match the CUDA runtime:

  • Right click on the project and choose Properties, then in C/C++ -> Code Generation change the Runtime Library to /MT

You could use /MTd for debug, in which case you will need to mirror this in CUDA Build Rule -> Hybrid CUDA/C++ Options.

See this earlier post for a step-by-step with more tips.

Tom
Thanks Tom. I think you have mentioned this before on an earlier post of mine. I'll try it when I get home tonight.
Mr Bell
Using /MTd allows everything to compile. However, I switched the runtime library to /MT and ensured that CUDA settings matched. This yielded a new set of errors, i'll post the new build log in the post.Thank you for your continuing insight
Mr Bell
/MD and /MDd both work fine. Whats the main difference between /MT and /MD ?
Mr Bell
Check out http://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx for a description of the difference between /MD or /MT - too long for a comment!
Tom
Regarding your latest error message, it looks like you have set /MT in the CUDA Build Rule but not in the C/C++ Code Generation page. Double check that you have made the change in *both* places, and then rebuild everything.
Tom
Regarding my above comment, I think you actually have /MT in the CUDA build rule and /MTd in the C/C++ settings. They need to match, either both /MT or both /MTd.
Tom
A: 

I am a newbie to CUDA and visual studio!! Mr.Bell , it seems that u have been able to compile CUDA codes in VS 2008. I m running VS 2008 on WinVista. I have integrated CUDA sdk with VS 2008.

1) I need to know that CUDA codes are to be compiled as .cpp or .cu, saving the files as .cu and then compiling is giving a lot of errors. As I am a newbie I do not know how to proceed further. Ur advice would be of gr8 help. I am compiling a simple Hello world code.

I m pasting the code for ur reference

* ** Hello World using CUDA ** ** The string "Hello World!" is mangled then restored using a common CUDA idiom ** ** Byron Galbraith ** 2009-02-18 */

include

include

// Prototypes global void helloWorld(char*);

// Host function int main(int argc, char** argv) { int i;

// desired output char str[] = "Hello World!";

// mangle contents of output // the null character is left intact for simplicity for(i = 0; i < 12; i++) str[i] -= i;

// allocate memory on the device char *d_str; size_t size = sizeof(str); cudaMalloc((void**)&d_str, size);

// copy the string to the device cudaMemcpy(d_str, str, size, cudaMemcpyHostToDevice);

// set the grid and block sizes dim3 dimGrid(2); // one block per word
dim3 dimBlock(6); // one thread per character

// invoke the kernel helloWorld<<< dimGrid, dimBlock >>>(d_str);

// retrieve the results from the device cudaMemcpy(str, d_str, size, cudaMemcpyDeviceToHost);

// free up the allocated memory on the device cudaFree(d_str);

// everyone's favorite part printf("%s\n", str);

return 0; }

// Device kernel global void helloWorld(char* str) { // determine where in the thread grid we are int idx = blockIdx.x * blockDim.x + threadIdx.x;

// unmangle output str[idx] += idx; }

ankit