使用 Visual Studio 2013 IDE 编译 CUDA Mex 文件

Posted

技术标签:

【中文标题】使用 Visual Studio 2013 IDE 编译 CUDA Mex 文件【英文标题】:Compiling CUDA Mex Files using Visual Studio 2013 IDE 【发布时间】:2015-05-23 02:27:53 【问题描述】:

我正在尝试使用 Visual Studio 2013 编译以下程序,它是 MATLAB 的 CUDA mex 文件。 MATLAB 官方网站上有 instructions 仅适用于 C++ Mex 文件,不适用于 CUDA mex。 因此,我按照 Mathworks 上的官方说明对项目设置进行了以下额外更改: 1. 我使用 Visual Studio 项目和我安装的 CUDA 6.5 运行时创建了一个项目。 2. 在我的 VS 项目的链接器属性中包含库(libmx.lib、libmex.lib、libmat.lib、gpu.lib), 3.新增目录include,(MATLABROOT)\toolbox\distcomp\gpu\extern\include;

我仍然收到许多未解决的外部符号错误。什么是正确的方法,因为没有可用于使用 VS IDE 编译 CUDA Mex 的官方文档?有谁知道这样做的正确方法是什么?当然我错过了一些设置,有人可以帮忙吗?

我的程序(从 MATLAB 示例文件 mexGPUExample.cu 复制)如下:

   **
/*
* 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);

我在尝试编译程序时遇到的错误:

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)

【问题讨论】:

这个article 可能很有趣。 【参考方案1】:

您的主要问题似乎是您选择了错误的项目类型。可能您使用的是 MFC DLL 而不是常规的 Win32 项目(带有 DLL 选项)。但是,构建 MEX 文件需要更多设置,这些文件 (a) 使用作为并行计算工具箱一部分的 mxGPUArray 类型,并且 (b) 包含使用 NVIDIA CUDA 编译的 CUDA 内核(自定义 GPU 设备代码) SDK 编译器,nvcc。

假设您已经配置了通常的 MEX 相关设置,您选择 CUDA“构建自定义”来将 nvcc 配置为 .cu 文件的编译器。然后您可能还需要指定 CUDA 运行时库,同时通过选中“从父级或项目默认值继承”框确保您仍然拥有链接的所有标准 Windows 库依赖项:

它以这种方式编译和链接对我来说很好。

但是,我设置了我的 Visual Studio 项目using a property sheet (MATLAB.props) as described here。这将自动获得我上面提到的标准 MEX 设置。 编辑:我在属性表中添加了 Parallel Computing Toolbox 支持。您只需要添加如上所示的 cudart_static.lib 部分并选择 CUDA Build Customization 即可使用 nvcc 编译 .cu 文件。

通过 Build Customizations 添加 CUDA 6.5 SDK 设置。 首先,右键单击项目(不是解决方案):

检查您要使用的 CUDA 自定义(在本例中为 SDK 6.5):

如果您想编辑这些字段,请不要编辑它们:

【讨论】:

这个属性表不起作用,它给我一个错误,无效的属性表或添加它会导致循环继承。我尝试手动按照道具表中的设置列表进行操作,但这对我也不起作用。它需要什么设置才能工作,或者文件不工作? @SyedAlamAbbas 我刚刚更新了它,所以它可能已经破坏了它,尽管它对我有用。您能否尝试不支持并行工具箱的the previous version 并手动添加并行部分。让我知道更多关于错误的信息吗?如果这不起作用,那么还有其他问题。我想让它与并行计算工具箱一起工作。顺便说一句,开始一个新项目,然后添加它。顺便说一句,您是否将环境变量设置为指向 MATLAB 根目录? 是的,MATLAB 根设置正确,我从您的属性表中读取了配置设置,然后手动进行了所有设置。但正如我所说,它对我不起作用。这是我创建的项目,1. Win32 dll 如您的帖子所示。然后我尝试使用属性管理器添加您在 GitHub 上的属性表,然后我立即得到该错误。您在空白项目中没有收到该错误吗? 我试了以前的版本,还是一样的错误信息,“要么是无效的属性表,要么包含它会导致循环继承” 您的解决方案非常有效。您在创建 VC++ 项目时使用什么模板,您能详细说明一下吗?再次非常感谢。

以上是关于使用 Visual Studio 2013 IDE 编译 CUDA Mex 文件的主要内容,如果未能解决你的问题,请参考以下文章

Microsoft Visual Studio Professional 2013,变量在哪里定义和编辑?

Visual Studio咋用哦?

C#基础总结 —— C#开发工具 Visual Studio(IDE)

Visual Studio 2013 为C#类文件添加版权信息

使用 Visual Studio Express 2013 进行 64 位编译

visual studio 2013的使用和单元测试