Matlab中C-mex与CUDA环境的配置

Step 1: 安装Visual Studio 2012(或以上版本)


Step 2: 安装CUDA 7.0

  安装完毕后,可以看到系统中多了CUDA_PATH和CUDA_PATH_V6_0两个环境变量,接下来,还要在系统中添加以下几个环境变量:

CUDA_SDK_PATH = C:\ProgramData\NVIDIA Corporation\CUDA Samples\v7.0

CUDA_LIB_PATH = %CUDA_PATH%\lib\x64

CUDA_BIN_PATH = %CUDA_PATH%\bin

CUDA_SDK_BIN_PATH = %CUDA_SDK_PATH%\bin\win64

CUDA_SDK_LIB_PATH = %CUDA_SDK_PATH%\common\lib\x64

然后,在系统变量PATH的末尾添加:

;%CUDA_LIB_PATH%;%CUDA_BIN_PATH%;%CUDA_SDK_LIB_PATH%;%CUDA_SDK_BIN_PATH%;

注意:CUDA一定要在VS之后安装


Step 3: 安装Matlab R2014(或其他版本)

Step 4: c-mex配置,在Matlab的命令行窗口中输入如下命令

可以看到,Matlab已经自动选择了VC 2012的C编译器进行C语言的编译。


Step 5: 测试c-mex是否可用

1. 在当前文件夹下建立一个新的文件夹(也可以在任意位置下建立),如”HelloMex”。然后双击进入该文件夹

2. 新建一个Matlab脚本,然后保存为.cpp文件

注意文件的保存类型要选择为“所有文件(*.*)


3. 在hellomex.cpp中键入以下代码,然后保存

#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[],int nrhs,const mxArray *prhs[])

{

mexPrintf("Hello, mex!\n");

}

4. 在Matlab命令行窗口中键入以下命令,编译文件hellomex.cpp

由上图可知,MEX文件编译成了。我们还可以看到当前文件夹下,生成了目标文件”hellomex.mexw64"

5. 在Matlab中调用。在Matlab中,我们使用文件名调用Mex目标文件,如下:

到此,在Matlab中调用c-mex的一个简单的例子已经测试完毕。


Step 6: 测试CUDA是否可用

1. 在Matlab命令行窗口输入以下命令

出现以上提示说明CUDA环境是配置好了的,即系统中安装了nvcc编译器。

如果系统提示没有nvcc编译器,说明你没有安装CUDA。

2. 新建一个脚本,输入以下代码并保存为“AddVectors.h”

#ifndef __ADDVECTORS_H__
#define __ADDVECTORS_H__

extern void addVectors(float* A, float* B, float* C, int size);
#endif

3. 新建一个脚本,输入以下代码,并保存为“AddVectors.cu"(.cu代表CUDA代码)

#include "addVectors.h"
#include "mex.h"

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

__global__ void addVectorsMask(float* a, float* b, float* c, int size)
{
    int i = threadIdx.x;
    if( i >= size )  return;
    c[i] = a[i] + b[i];
}

// Helper function for using CUDA to add vectors in parallel.
void addVectors(float* a, float* b, float* c, int size)
{
    float *dev_a = 0;
    float *dev_b = 0;
    float *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(float));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

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

    cudaStatus = cudaMalloc((void**)&dev_b, size * sizeof(float));
    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(float), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

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

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

    // 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(float), cudaMemcpyDeviceToHost);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

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

4. 新建一个脚本文件,输入以下代码,保存为”AddVectors.cpp“

#include "mex.h"
#include "addVectors.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]) 
{
    if (nrhs != 2)
        mexErrMsgTxt("Invaid number of input arguments");
    if (nlhs != 1)
        mexErrMsgTxt("Invalid number of outputs");
    if (!mxIsSingle(prhs[0]) && !mxIsSingle(prhs[1]))
        mexErrMsgTxt("input vector data type must be single");
    
    int numRowsA = (int)mxGetM(prhs[0]); 
    int numColsA = (int)mxGetN(prhs[0]); 
    int numRowsB = (int)mxGetM(prhs[1]); 
    int numColsB = (int)mxGetN(prhs[1]);
    
    if (numRowsA != numRowsB || numColsA != numColsB) 
        mexErrMsgTxt("Invalid size. The sizes of two vectors must be same");
    
    int minSize = (numRowsA < numColsA) ? numRowsA : numColsA; 
    int maxSize = (numRowsA > numColsA) ? numRowsA : numColsA;
    
    if (minSize != 1)
        mexErrMsgTxt("Invalid size. The vector must be one dimentional");

    float* A = (float*)mxGetData(prhs[0]);
    float* B = (float*)mxGetData(prhs[1]);

    //create the output vector
    plhs[0] = mxCreateNumericMatrix(numRowsA, numColsB, mxSINGLE_CLASS, mxREAL);

    float* C = (float*)mxGetData(plhs[0]);

    addVectors(A, B, C, maxSize);
}


5. 使用nvcc编译器编译".cu"文件,

编译完成后,在当前文件夹下可以看到生成了".obj"目标文件。

这一步可能出现找不到编译器'cl.exe'的错误,如下:

出现这个错误的原因是在系统变量”PATH“中没有添加VC编译器”cl.exe"的路径,找到该路径并添加便可。

“cl.exe”在VS安装路径下的“VC\bin”中,将这个路径添加到系统变量“PATH”的末尾。

注意:要使环境变量生效,还需重启计算机或者注销用户。

6. 编译mex文件并链接到生成的CUDA目标文件,命令为“mex AddVectors.cpp addVectors.obj -lcudart -L"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.0\lib\x64"

命令行窗口提示”MEX 已成功完成“,在当前目录下,我们可以看到生成的文件”AddVectors.mexw64"

7. 在Matlab中调用,如下:


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值