利用cuda加速MATLAB程序

利用cuda加速MATLAB程序

  • 利用cuda加速MATLAB程序
  • 1参考木子超的办法
  • 2参考Tomheaven的方法
  • 3引用

  最近因为要做张量的模态积,所以要考虑使用cuda来进行并行的编程,但是c++实在太麻烦,尤其是在有MATLAB的时候,写c++简直就是一种“浪费时间”的行为。如果能用MATLAB调用cuda的程序那该是一件多么美好的事情呀。
  确实,这件事情非常美好,但是配置开发环境的过程却是非常痛苦,我花了将近一个星期的时间才把这个问题解决,希望读者能在看完本文后节约宝贵的时间。
  如果你用的是版本比较老的VS(比如2005)和matlab,那么这个问题其实很好办,只要调用nvmex函数就好了,但是据stackoverflow的网友说,自MATLAB2010a开始,nvmex就不被支持了,因此网上有很多答案讨论如何改nvmex函数使得能在更高版本的MATLAB运行,但我试了很多源码都不成功,于是乎放弃。好在MATLAB出了个比较新的MATLABR2015b的版本,这个版本有个mexcuda函数, 用起来相当舒心,只要一两句代码就能调用.cu程序,唯一的不足就在于传入的数组必须是GPUARRay的形式,而且重新下载MATLAB再安装也是挺不舒服的。另外一个要注意的就是在mathworks的releasenote里有说哪个版本的MATLAB支持哪个版本的cuda。所以重装什么的绝对不是一个最好的办法呀。下面就给出两个解决办法:
  

1、参考木子超的办法

  这个办法写得很完整也很细致,我所遇到的问题和他遇到的问题几乎是一样的,读者只要对照着去做就好,我亲自测试过,测试环境是MATLAB_R2014a+VS2010+cuda7.5。还有一点值得注意的是,木子超所给出的代码有的地方是有点瑕疵的,需要读者自己完善,这里我就不说了。以下给出链接:
  http://blog.csdn.net/endlch/article/details/44561535

2、参考Tomheaven的方法

  这个方法我也亲自测试过,测试环境同上,作者写得非常好,就是有个小细节要注意
  

COMPFLAGS="-gencode=arch=compute_20,code=sm_20 -gencode=arch=compute_30,code=sm_30 -gencode=arch=compute_50,code=\"sm_50,compute_50\" --compiler-options=/c,/GR,/W3,/EHs,/nologo,/MD"

  在上面这个地方,如果你是cuda7.5的版本一定要把第一行第一个出现的arch和code后面的那个数字都改成20了(我记得cuda5.5这俩数字都是13),不然会出现nvcc报错,也就是我第一段说的MATLAB找不到它支持的编译器的架构的问题。以下是链接:
  http://blog.csdn.net/hanlin_tan/article/details/48790273
  
  
%%%%%%%%%%%% 2018年更新 %%%%%%%%%%%%%%
上面讲述了如何在MATLAB2014下进行配置,时间来到了2018年,可能Mathwork公司已经意识到深度学习的火热和大家配置Cuda+MATLAB开发环境的痛苦,所以最新版本的MATLAB(据我所知是MATLAB2016a之后的版本)定义了一个新的语句:”mexcuda”。这个语句使用起来相当方便,比如你有一个向量相加的程序(VectorAdd.cu),你只需要按照编译C++ mex 文件的方法去编译就行了,直接敲击mexcuda VectorAdd.cu, 等待一会,就可以生成你想要的可执行文件了。注意MATLAB官方给了一个模板,但你其实不需要按照它给的函数传递方法去定义GPUArray,传统的mex方法依旧可行。为了方便大家的理解,我给出以下的一个例子:


#include "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\include\cuda_runtime.h"
#include "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\include\device_launch_parameters.h"
#include 
#include 

cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size);

__global__ void addKernel(int *c, const int *a, const int *b)
{
    int i = threadIdx.x;
    c[i] = a[i] + b[i];
}


void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    // initialize
    int *array_A = (int*)mxGetPr(prhs[0]);
    int *array_b = (int*)mxGetPr(prhs[1]);
    const int arraySize = 5;
    int c[arraySize] = { 0 };

       // Add vectors in parallel.
    cudaError_t cudaStatus = addWithCuda(c, array_A, array_b, arraySize);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "addWithCuda failed!");
    }

    printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}\n",
        c[0], c[1], c[2], c[3], c[4]);

    // cudaDeviceReset must be called before exiting in order for profiling and
    // tracing tools such as Nsight and Visual Profiler to show complete traces.
    cudaStatus = cudaDeviceReset();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaDeviceReset failed!");
    }
}

// Helper function for using CUDA to add vectors in parallel.
cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size)
{
    int *dev_a = 0;
    int *dev_b = 0;
    int *dev_c = 0;
    cudaError_t cudaStatus;

    // Choose which GPU to run on, change this on a multi-GPU system.
    cudaStatus = cudaSetDevice(0);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaSetDevice failed!  Do you have a CUDA-capable GPU installed?");
        goto Error;
    }

    // Allocate GPU buffers for three vectors (two input, one output)    .
    cudaStatus = cudaMalloc((void**)&dev_c, size * sizeof(int));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    cudaStatus = cudaMalloc((void**)&dev_a, size * sizeof(int));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    cudaStatus = cudaMalloc((void**)&dev_b, size * sizeof(int));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    // Copy input vectors from host memory to GPU buffers.
    cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(int), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

    cudaStatus = cudaMemcpy(dev_b, b, size * sizeof(int), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

    // Launch a kernel on the GPU with one thread for each element.
    addKernel<<<1, size>>>(dev_c, dev_a, dev_b);

    // Check for any errors launching the kernel
    cudaStatus = cudaGetLastError();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
        goto Error;
    }

    // cudaDeviceSynchronize waits for the kernel to finish, and returns
    // any errors encountered during the launch.
    cudaStatus = cudaDeviceSynchronize();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus);
        goto Error;
    }

    // Copy output vector from GPU buffer to host memory.
    cudaStatus = cudaMemcpy(c, dev_c, size * sizeof(int), cudaMemcpyDeviceToHost);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

Error:
    cudaFree(dev_c);
    cudaFree(dev_a);
    cudaFree(dev_b);

    return cudaStatus;
}

注意开头的两行对应的是相应的Cuda安装目录,如果你懒得管,你在安装Cuda的时候只要一路点击确定就行了。

还有另外一个问题,相信大家都注意到了,那就是版本的问题,据我所知,Cuda已经出到了9.1,但是MATLAB还是有一定滞后的,但是我们也不能一辈子使用Cuda7.5和VS2012, 我上Mathwork的官方论坛和Stackoverflow搜索了以下,得到了以下网友的回复:

引用块内容
This is how to compile (mexcuda) with Visual Studio 2015 and Cuda 8.0 :
1:Go to: “\toolbox\distcomp\gpu\extern\src\mex\win64”
2:Copy files and rename 2013 to 2015: { “nvcc_msvcpp2013.xml” , “nvcc_msvcpp2013_dynamic.xml”}
3:Replace inside those files “7.5” to “8.0” and “12” to “14”.
4:Done.

我今天实验以下,如果成功了,我再来更新。


3、引用

[1]: http://blog.csdn.net/endlch/article/details/44561535
[2]: http://blog.csdn.net/hanlin_tan/article/details/48790273

你可能感兴趣的:(数学,计算机,cuda)