3

I am trying to compile following program, which is a CUDA mex file for MATLAB, using Visual Studio 2013.
There are instructions available on MATLAB's official website only for C++ Mex files , not for the CUDA mex.
So I made following additional changes to my project settings while following the official instructions on Mathworks:
1. I created a project using Visual studio project with my installed CUDA 6.5 runtime.
2. Included the libs (libmx.lib,libmex.lib,libmat.lib,gpu.lib) in Linker properties of my VS project,
3. Added a directory include, (MATLABROOT)\toolbox\distcomp\gpu\extern\include;

Still I get many unresolved external symbol error. What is the right way to do this, since there is no official documentation available for compiling CUDA Mex using VS IDE ? Does anyone has any idea what is the proper way to do this ? Surely I am missing some setting, can someone help please ?

My Program (copied from MATLAB example file, mexGPUExample.cu ) is as follow:

   **
/*
* Example of how to use the mxGPUArray API in a MEX file.  This example shows
* how to write a MEX function that takes a gpuArray input and returns a
* gpuArray output, e.g. B=mexFunction(A).
*
* Copyright 2012 The MathWorks, Inc.
*/
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "mex.h"
#include "gpu/mxGPUArray.h"

/*
* Device code
*/
void __global__ TimesTwo(double const * const A,
    double * const B,
    int const N)
{
    /* Calculate the global linear index, assuming a 1-d grid. */
    int const i = blockDim.x * blockIdx.x + threadIdx.x;
    if (i < N) {
        B[i] = 2.0 * A[i];
    }
}

/*
* Host code
*/

void mexFunction(int nlhs, mxArray *plhs[],
    int nrhs, mxArray const *prhs[])
{
    /* Declare all variables.*/
    mxGPUArray const *A;
    mxGPUArray *B;
    double const *d_A;
    double *d_B;
    int N;
    char const * const errId = "parallel:gpu:mexGPUExample:InvalidInput";
    char const * const errMsg = "Invalid input to MEX file.";

    /* Choose a reasonably sized number of threads for the block. */
    int const threadsPerBlock = 256;
    int blocksPerGrid;

    /* Initialize the MathWorks GPU API. */
    mxInitGPU();

    /* Throw an error if the input is not a GPU array. */
    if ((nrhs != 1) || !(mxIsGPUArray(prhs[0]))) {
        mexErrMsgIdAndTxt(errId, errMsg);
    }

    A = mxGPUCreateFromMxArray(prhs[0]);

    /*
    * Verify that A really is a double array before extracting the pointer.
    */
    if (mxGPUGetClassID(A) != mxDOUBLE_CLASS) {
        mexErrMsgIdAndTxt(errId, errMsg);
    }

    /*
    * Now that we have verified the data type, extract a pointer to the input
    * data on the device.
    */
    d_A = (double const *)(mxGPUGetDataReadOnly(A));

    /* Create a GPUArray to hold the result and get its underlying pointer. */
    B = mxGPUCreateGPUArray(mxGPUGetNumberOfDimensions(A),
        mxGPUGetDimensions(A),
        mxGPUGetClassID(A),
        mxGPUGetComplexity(A),
        MX_GPU_DO_NOT_INITIALIZE);
    d_B = (double *)(mxGPUGetData(B));

    /*
    * Call the kernel using the CUDA runtime API. We are using a 1-d grid here,
    * and it would be possible for the number of elements to be too large for
    * the grid. For this example we are not guarding against this possibility.
    */
    N = (int)(mxGPUGetNumberOfElements(A));
    blocksPerGrid = (N + threadsPerBlock - 1) / threadsPerBlock;
    TimesTwo <<< blocksPerGrid, threadsPerBlock >>>(d_A, d_B, N);

    /* Wrap the result up as a MATLAB gpuArray for return. */
    plhs[0] = mxGPUCreateMxArrayOnGPU(B);

    /*
    * The mxGPUArray pointers are host-side structures that refer to device
    * data. These must be destroyed before leaving the MEX function.
    */
    mxGPUDestroyGPUArray(A);
    mxGPUDestroyGPUArray(B);
}

Errors I get when I try to compile my program :

Error   66  error LNK1120: 64 unresolved externals  
Error   64  error LNK2001: unresolved external symbol _fltused  
Error   62  error LNK2001: unresolved external symbol _RTC_InitBase 
Error   63  error LNK2001: unresolved external symbol _RTC_Shutdown 
Error   65  error LNK2001: unresolved external symbol mainCRTStartup    
Error   58  error LNK2019: unresolved external symbol __imp__dsign referenced in function "bool __cdecl signbit(double)" (?signbit@@YA_NN@Z)    
Error   60  error LNK2019: unresolved external symbol __imp__fdsign referenced in function "bool __cdecl signbit(float)" (?signbit@@YA_NM@Z)    
Error   61  error LNK2019: unresolved external symbol __imp__hypotf referenced in function hypotf   
Error   59  error LNK2019: unresolved external symbol __imp__ldsign referenced in function "bool __cdecl signbit(long double)" (?signbit@@YA_NO@Z)  
Error   39  error LNK2019: unresolved external symbol __imp_acosf referenced in function "float __cdecl acos(float)" (?acos@@YAMM@Z)    
Error   12  error LNK2019: unresolved external symbol __imp_acoshf referenced in function "float __cdecl acosh(float)" (?acosh@@YAMM@Z) 
Error   40  error LNK2019: unresolved external symbol __imp_asinf referenced in function "float __cdecl asin(float)" (?asin@@YAMM@Z)    
Error   13  error LNK2019: unresolved external symbol __imp_asinhf referenced in function "float __cdecl asinh(float)" (?asinh@@YAMM@Z) 
Error   42  error LNK2019: unresolved external symbol __imp_atan2f referenced in function "float __cdecl atan2(float,float)" (?atan2@@YAMMM@Z)  
Error   41  error LNK2019: unresolved external symbol __imp_atanf referenced in function "float __cdecl atan(float)" (?atan@@YAMM@Z)    
Error   14  error LNK2019: unresolved external symbol __imp_atanhf referenced in function "float __cdecl atanh(float)" (?atanh@@YAMM@Z) D:\GitHub\arrayfire-windows-scripts\SimpleCUDAProj\CUDA_Mex\CUDA_Mex\CUDA_Times_Two.cu.obj  CUDA_Mex
Error   29  error LNK2019: unresolved external symbol __imp_cbrtf referenced in function "float __cdecl cbrt(float)" (?cbrt@@YAMM@Z)    
Error   55  error LNK2019: unresolved external symbol __imp_ceilf referenced in function "float __cdecl ceil(float)" (?ceil@@YAMM@Z)    
Error   36  error LNK2019: unresolved external symbol __imp_copysignf referenced in function "float __cdecl copysign(float,float)" (?copysign@@YAMMM@Z) 
Error   43  error LNK2019: unresolved external symbol __imp_cosf referenced in function "float __cdecl cos(float)" (?cos@@YAMM@Z)   
Error   46  error LNK2019: unresolved external symbol __imp_coshf referenced in function "float __cdecl cosh(float)" (?cosh@@YAMM@Z)    
Error   33  error LNK2019: unresolved external symbol __imp_erfcf referenced in function "float __cdecl erfc(float)" (?erfc@@YAMM@Z)    
Error   32  error LNK2019: unresolved external symbol __imp_erff referenced in function "float __cdecl erf(float)" (?erf@@YAMM@Z)   
Error   8   error LNK2019: unresolved external symbol __imp_exp2f referenced in function "float __cdecl exp2(float)" (?exp2@@YAMM@Z)    
Error   49  error LNK2019: unresolved external symbol __imp_expf referenced in function "float __cdecl exp(float)" (?exp@@YAMM@Z)   
Error   9   error LNK2019: unresolved external symbol __imp_expm1f referenced in function "float __cdecl expm1(float)" (?expm1@@YAMM@Z) 
Error   28  error LNK2019: unresolved external symbol __imp_fdimf referenced in function "float __cdecl fdim(float,float)" (?fdim@@YAMMM@Z) 
Error   56  error LNK2019: unresolved external symbol __imp_floorf referenced in function "float __cdecl floor(float)" (?floor@@YAMM@Z) 
Error   38  error LNK2019: unresolved external symbol __imp_fmaf referenced in function "float __cdecl fma(float,float,float)" (?fma@@YAMMMM@Z) 
Error   7   error LNK2019: unresolved external symbol __imp_fmaxf referenced in function "float __cdecl fmax(float,float)" (?fmax@@YAMMM@Z) 
Error   6   error LNK2019: unresolved external symbol __imp_fminf referenced in function "float __cdecl fmin(float,float)" (?fmin@@YAMMM@Z) 
Error   57  error LNK2019: unresolved external symbol __imp_fmodf referenced in function "float __cdecl fmod(float,float)" (?fmod@@YAMMM@Z) 
Error   19  error LNK2019: unresolved external symbol __imp_frexp referenced in function frexpf 
Error   17  error LNK2019: unresolved external symbol __imp_ilogbf referenced in function "int __cdecl ilogb(float)" (?ilogb@@YAHM@Z)   
Error   15  error LNK2019: unresolved external symbol __imp_ldexp referenced in function ldexpf 
Error   34  error LNK2019: unresolved external symbol __imp_lgammaf referenced in function "float __cdecl lgamma(float)" (?lgamma@@YAMM@Z)  
Error   25  error LNK2019: unresolved external symbol __imp_llrintf referenced in function "__int64 __cdecl llrint(float)" (?llrint@@YA_JM@Z)   
Error   22  error LNK2019: unresolved external symbol __imp_llroundf referenced in function "__int64 __cdecl llround(float)" (?llround@@YA_JM@Z)    
Error   51  error LNK2019: unresolved external symbol __imp_log10f referenced in function "float __cdecl log10(float)" (?log10@@YAMM@Z) 
Error   11  error LNK2019: unresolved external symbol __imp_log1pf referenced in function "float __cdecl log1p(float)" (?log1p@@YAMM@Z) 
Error   10  error LNK2019: unresolved external symbol __imp_log2f referenced in function "float __cdecl log2(float)" (?log2@@YAMM@Z)    
Error   16  error LNK2019: unresolved external symbol __imp_logbf referenced in function "float __cdecl logb(float)" (?logb@@YAMM@Z)    
Error   50  error LNK2019: unresolved external symbol __imp_logf referenced in function "float __cdecl log(float)" (?log@@YAMM@Z)   
Error   24  error LNK2019: unresolved external symbol __imp_lrintf referenced in function "long __cdecl lrint(float)" (?lrint@@YAJM@Z)  
Error   21  error LNK2019: unresolved external symbol __imp_lroundf referenced in function "long __cdecl lround(float)" (?lround@@YAJM@Z)   
Error   52  error LNK2019: unresolved external symbol __imp_modff referenced in function "float __cdecl modf(float,float *)" (?modf@@YAMMPEAM@Z)    
Error   26  error LNK2019: unresolved external symbol __imp_nearbyintf referenced in function "float __cdecl nearbyint(float)" (?nearbyint@@YAMM@Z) 
Error   37  error LNK2019: unresolved external symbol __imp_nextafterf referenced in function "float __cdecl nextafter(float,float)" (?nextafter@@YAMMM@Z)  
Error   53  error LNK2019: unresolved external symbol __imp_powf referenced in function "float __cdecl pow(float,float)" (?pow@@YAMMM@Z)    
Error   30  error LNK2019: unresolved external symbol __imp_remainderf referenced in function "float __cdecl remainder(float,float)" (?remainder@@YAMMM@Z)  
Error   31  error LNK2019: unresolved external symbol __imp_remquof referenced in function "float __cdecl remquo(float,float,int *)" (?remquo@@YAMMMPEAH@Z) 
Error   23  error LNK2019: unresolved external symbol __imp_rintf referenced in function "float __cdecl rint(float)" (?rint@@YAMM@Z)    
Error   20  error LNK2019: unresolved external symbol __imp_roundf referenced in function "float __cdecl round(float)" (?round@@YAMM@Z) 
Error   18  error LNK2019: unresolved external symbol __imp_scalblnf referenced in function "float __cdecl scalbln(float,long)" (?scalbln@@YAMMJ@Z) 
Error   44  error LNK2019: unresolved external symbol __imp_sinf referenced in function "float __cdecl sin(float)" (?sin@@YAMM@Z)   
Error   47  error LNK2019: unresolved external symbol __imp_sinhf referenced in function "float __cdecl sinh(float)" (?sinh@@YAMM@Z)    
Error   54  error LNK2019: unresolved external symbol __imp_sqrtf referenced in function "float __cdecl sqrt(float)" (?sqrt@@YAMM@Z)    
Error   45  error LNK2019: unresolved external symbol __imp_tanf referenced in function "float __cdecl tan(float)" (?tan@@YAMM@Z)   
Error   48  error LNK2019: unresolved external symbol __imp_tanhf referenced in function "float __cdecl tanh(float)" (?tanh@@YAMM@Z)    
Error   35  error LNK2019: unresolved external symbol __imp_tgammaf referenced in function "float __cdecl tgamma(float)" (?tgamma@@YAMM@Z)
Error   27  error LNK2019: unresolved external symbol __imp_truncf referenced in function "float __cdecl trunc(float)" (?trunc@@YAMM@Z) 
Error   2   error LNK2019: unresolved external symbol atexit referenced in function "void __cdecl __nv_cudaEntityRegisterCallback(void * *)" (?__nv_cudaEntityRegisterCallback@@YAXPEAPEAX@Z)   
Error   5   error LNK2019: unresolved external symbol fabs referenced in function "double __cdecl abs(double)" (?abs@@YANN@Z)   
Error   3   error LNK2019: unresolved external symbol labs referenced in function "long __cdecl abs(long)" (?abs@@YAJJ@Z)   
Error   4   error LNK2019: unresolved external symbol llabs referenced in function "__int64 __cdecl abs(__int64)" (?abs@@YA_J_J@Z)
mido
  • 24,198
  • 15
  • 92
  • 117
Syed Alam Abbas
  • 521
  • 6
  • 21

1 Answers1

3

The main issue in your case seems to be that you have chosen the wrong project type. Probably you are using an MFC DLL instead of a regular Win32 project (with DLL option). However, there are more settings needed to build MEX files that (a) use the mxGPUArray type that is part of the Parallel Computing Toolbox and (b) contain a CUDA kernel (custom GPU device code) that is compiled with the NVIDIA CUDA SDK compiler, nvcc.

Assuming you've configured the usual MEX-related settings, you select the CUDA "Build Customization" to configure nvcc as the compiler for .cu files. Then you may also need to specify the CUDA runtime library, while ensuring that you still have all the standard Windows library dependencies linked by checking the "Inherit from parent or project defaults" box:

enter image description here

It compiled and linked fine for me this way.

However, I set up my Visual Studio project using a property sheet (MATLAB.props) as described here. This will automatically get the standard MEX settings I mentioned above. EDIT: I've added Parallel Computing Toolbox support to the property sheet. You just need to add the cudart_static.lib part as shown above and choose the CUDA Build Customization to compile a .cu file with nvcc.

Adding CUDA 6.5 SDK settings via Build Customizations. First, right click on the project (not solution):

enter image description here

Check the CUDA customization you want to use (SDK 6.5 in this case):

enter image description here

And just in case you were tempted to edit these fields, DON'T EVER EDIT THEM:

enter image description here

Community
  • 1
  • 1
chappjc
  • 30,359
  • 6
  • 75
  • 132
  • This property sheet does not work, it gives me an error, invalid property sheet or adding it will cause circular inheritance. I tried to follow the list of setting in prop sheet manually and that didn't work either for me. What is the settings required for it to work , or is the file not working ? – Syed Alam Abbas May 23 '15 at 16:16
  • @SyedAlamAbbas I just updated it so it might have broken it although it works for me. Could you try [the previous version](https://github.com/chappjc/MATLAB/blob/c77891e39a0aec8fe3ece6487ac8339e5016d493/propertySheets/MATLAB.props) which does not support the Parallel toolbox and add the parallel parts manually. And let me know any more about the error? If that doesn't work then something else is wrong. I'd like to make it work with the Parallel Computing Toolbox. By the way, start a fresh project and then add it. BTW, did you set the environment variable to point to the MATLAB root? – chappjc May 23 '15 at 16:18
  • Yes the MATLAB root is properly set, I read the configuration settings from your property sheets and then did all the setting manually. But as I said it didn't work for me. Here is the project I create, 1. Win32 dll as shown in your post. Then I try to add the property sheet you have on GitHub using property manager, and then I get that error straightaway. You don't get that error on a blank project ? – Syed Alam Abbas May 23 '15 at 16:30
  • I tried the previous version, and I still get the same error message, "either it is invalid property sheet or including it would cause a circular inheritance" – Syed Alam Abbas May 23 '15 at 16:36
  • @SyedAlamAbbas No, I and others have used it many times. I've never seen that message. Note that the environment variables you need are `MATLAB_ROOT` for the 64-bit install and `MATLAB32_ROOT` for a 32-bit install. (e.g. C:\Program Files\MATLAB\R2014a\ might be `MATLAB_ROOT` on 64-bit Windows, while C:\Program Files (x86)\MATLAB\R2014a\ might be `MATLAB32_ROOT` on 64-bit Windows, while on 32-bit Windows C:\Program Files\MATLAB\R2014a\ might be `MATLAB32_ROOT`) – chappjc May 23 '15 at 16:37
  • @SyedAlamAbbas You could also try the simplified older sheets (MATLABx86.props or MATLABx64.props for 32-bit and 64-bit MATLAB, respectively) to see if there is a problem with Visual Studio detecting the `$(Platform)` property, which is always set if VS is installed correctly. Just be sure you chose "DLL" as "Application Type" no matter what you choose, but I think you know that. – chappjc May 23 '15 at 16:50
  • @SyedAlamAbbas Actually, you got WAY WAY more linker errors than I did or would ever expect so I think your VS installation may be broken. I'd try uninstalling, reinstalling, and updating with service packs, etc. – chappjc May 23 '15 at 17:14
  • The matlab root is proper I checked it. What visual studio version you use ? I use Visual studio 2003 Ultimate, 64 bit OS, Windows 8, MATLAB 2015 and CUDA 6.5 Runtime. So by your inputs it should work, I wonder what I may be missing ? – Syed Alam Abbas May 23 '15 at 17:22
  • Can you post your entire solution ? So I can check and compare settings ? Only the paths would then need to be changed I guess, I hope it is not too much to ask, since you said you were able to compile it all using GPU example cuda file I had. – Syed Alam Abbas May 23 '15 at 17:25
  • Assuming you mean Visual Studio 2013 not 2003. I'll post the solution in a zip shortly. Yes, it compiles and links correctly (although I can't try running it on my laptop with no CUDA-enabled GPU). Note that to use the CUDA SDK, I've used the "Build Customizations..." method. Did you do that too? – chappjc May 23 '15 at 17:30
  • Build Customizations... , I set up the CUDA path and lib ? If not can you please explain, I am doing this setup for the very first time, I dont work much in Visual Studio, mostly in MATLAB. And yes I mean VS 2013. Thanks very very much I will try to download your project and see if it works on my machine. – Syed Alam Abbas May 23 '15 at 17:36
  • @SyedAlamAbbas [Here](https://drive.google.com/file/d/0B0I-3DNmsdxFbEZPMnJUd1B3QTg/view?usp=sharing) is the project. See edited answer to see Build Customizations... – chappjc May 23 '15 at 17:42
  • 1
    Amazingly your solution works. What template you use when creating your VC++ project , can you elaborate a little bit on that ? Thanks very much once again. – Syed Alam Abbas May 23 '15 at 18:23
  • @SyedAlamAbbas Great! I do it just as described in http://stackoverflow.com/a/27391300/2778484. Please up vote both answers if they helped. :) – chappjc May 23 '15 at 18:40
  • Hi chappjc, the proposed solution of MATLAB props works fine, but when I prepare a mex function and use it in MATLAB , it gives me an answer with single precision accuracy. I know in command prompt of MATLAB u can use -largedimensions, so what setting in MS Visual studio do I need to tell the mex project to prepare the function in double precision besides using x64 platform and .mex64 extensions as discussed ? – Syed Alam Abbas Jun 03 '15 at 05:43
  • @SyedAlamAbbas These are entirely unrelated concepts. I suggest you ask a new question. – chappjc Jun 03 '15 at 05:58