Matlab, CUDA, and linker issues

Hi guys,

I have been trying to learn CUDA this summer. Everything has been pretty cool so far, wrote my first kernel which ran decently (but kind of slowly due my complete lack of optimization :D) on my GTX470.

I’ve been trying to port my cuda function to MATLAB as a mex function in order to integrate with a few existing projects, but I’m having problems with the linker once I decided to separate my routine into different files.

This is currently what I see from the cuda_mex macro in MATLAB:

cuda_mex -v -f cudamexopts.bat mexRayPlaneIntersect.c RayPlaneIntersect_kernel.cu cudaErrCheck.cu

--> link /out:"mexRayPlaneIntersect.mexw32" /dll /export:mexFunction /LIBPATH:"C:\PROGRA~1\MATLAB\R2009B\extern\lib\win32\microsoft" libmx.lib libmex.lib libmat.lib /MACHINE:X86 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /incremental:NO /implib:"C:\USERS\o0xc\APPDATA\LOCAL\TEMP\MEX_HC~1\templib.x" /MAP:"mexRayPlaneIntersect.mexw32.map"  cudart.lib  @C:\USERS\o0xc\APPDATA\LOCAL\TEMP\MEX_HC~1\MEX_TMP.RSP   

Creating library C:\USERS\o0xc\APPDATA\LOCAL\TEMP\MEX_HC~1\templib.x and object C:\USERS\o0xc\APPDATA\LOCAL\TEMP\MEX_HC~1\templib.exp 

mexRayPlaneIntersect.obj : error LNK2019: unresolved external symbol _rayPlaneIntersect referenced in function _mexFunction 

mexRayPlaneIntersect.mexw32 : fatal error LNK1120: 1 unresolved externals 

C:\PROGRA~1\MATLAB\R2009B\BIN\CUDA_MEX.PL: Error: Link of 'mexRayPlaneIntersect.mexw32' failed.

I cannot seem to find the reason behind this unresolved symbol, as in my mexRayPlaneIntersect_kernel.cu file, I have the function defined

void rayPlaneIntersect(double * outPoints, double * phases, double * fcam_constants, double * ccam_constants, 

									double * kcam_constants, double * pixel_m, double * plane_m, int M, int N)

as well as putting it in the header I have. I can compile with -c and get .obj files, but when I try to link them, the same problem happens.

Im kind of at a loss right now. If anyone has any ideas on where to look for the solution, I’d be extremely grateful. Thanks in advance.

Edit: I should add that obj files compiled between .cu sources link correctly, and if I just put everything as .cu files, nvcc compiles them to be linked correctly (even though some .cu files are actually .c files, and have no cuda functionality).

These are the nvcc commands cuda_mex spits out:

--> nvcc  -c -arch sm_13 -Xcompiler "/c /Zp8 /GR /W3 /EHs /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /D_SECURE_SCL=0 /DMATLAB_MEX_FILE /nologo /MD" -o ""C:\USERS\o0xc\APPDATA\LOCAL\TEMP\MEX_Z1~1\mexRayPlaneIntersect.obj -IC:\PROGRA~1\MATLAB\R2009B\extern\include -IC:\PROGRA~1\MATLAB\R2009B\simulink\include -Xcompiler "/O2 /Oy- /DNDEBUG" -DMX_COMPAT_32 mexRayPlaneIntersect.c 

mexRayPlaneIntersect.c 

--> nvcc  -c -arch sm_13 -Xcompiler "/c /Zp8 /GR /W3 /EHs /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /D_SECURE_SCL=0 /DMATLAB_MEX_FILE /nologo /MD" -o ""C:\USERS\o0xc\APPDATA\LOCAL\TEMP\MEX_Z1~1\RayPlaneIntersect_kernel.obj -IC:\PROGRA~1\MATLAB\R2009B\extern\include -IC:\PROGRA~1\MATLAB\R2009B\simulink\include -Xcompiler "/O2 /Oy- /DNDEBUG" -DMX_COMPAT_32 RayPlaneIntersect_kernel.cu 

RayPlaneIntersect_kernel.cu 

tmpxft_0000104c_00000000-3_RayPlaneIntersect_kernel.cudafe1.gpu 

tmpxft_0000104c_00000000-8_RayPlaneIntersect_kernel.cudafe2.gpu 

RayPlaneIntersect_kernel.cu 

tmpxft_0000104c_00000000-3_RayPlaneIntersect_kernel.cudafe1.cpp 

tmpxft_0000104c_00000000-13_RayPlaneIntersect_kernel.ii 

--> nvcc  -c -arch sm_13 -Xcompiler "/c /Zp8 /GR /W3 /EHs /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /D_SECURE_SCL=0 /DMATLAB_MEX_FILE /nologo /MD" -o ""C:\USERS\o0xc\APPDATA\LOCAL\TEMP\MEX_Z1~1\cudaErrCheck.obj -IC:\PROGRA~1\MATLAB\R2009B\extern\include -IC:\PROGRA~1\MATLAB\R2009B\simulink\include -Xcompiler "/O2 /Oy- /DNDEBUG" -DMX_COMPAT_32 cudaErrCheck.cu 

cudaErrCheck.cu 

tmpxft_00001e48_00000000-3_cudaErrCheck.cudafe1.gpu 

tmpxft_00001e48_00000000-8_cudaErrCheck.cudafe2.gpu 

cudaErrCheck.cu 

tmpxft_00001e48_00000000-3_cudaErrCheck.cudafe1.cpp 

tmpxft_00001e48_00000000-13_cudaErrCheck.ii 

	Contents of C:\USERS\o0xc\APPDATA\LOCAL\TEMP\MEX_Z1~1\mex_tmp.rsp: 

  C:\USERS\o0xc\APPDATA\LOCAL\TEMP\MEX_Z1~1\mexRayPlaneIntersect.obj  C:\USERS\o0xc\APPDATA\LOCAL\TEMP\MEX_Z1~1\RayPlaneIntersect_kernel.obj  C:\USERS\o0xc\APPDATA\LOCAL\TEMP\MEX_Z1~1\cudaErrCheck.obj

You need to declare rayPlaneIntersect as extern “C”–C++ has its own mangled names for things, and extern “C” will make things all better.

Ahh I was thinking about that, but I thought nvcc wouldn’t have used one export type for cu files and one for c files! Guess I have to read the documentation more closely.

Thanks!

If you pass a .c file to nvcc, it’ll just pass it wholesale to gcc. If you pass a .cpp file, it’ll pass it to g++. Only .cu files are special.

What is cuda_mex? Nvidia provides a special makefile that compiles CUDA in mex-files…