Matlab、C/C++和GPU联合编程环境配置

一、系统配置:

操作系统:Microsoft Windows [版本 10.0.17763.529]
Matlab版本:Matlab 2017b 64位
CUDA版本:CUDA 10
VS版本:Visual Studio 2017(以下简称VS2017)
GPU:RTX 2070

二、应用场景描述:

  最近在探索学习Matlab + C/C++ + GPU联合编程。该编程方法,依靠Matlab平台编写运行能调用GPU运算的C/C++程序,从而达到加速程序运行的效果。
  采用C/C++语言编写的MATLAB函数称为c-mex文件,其相对于Matlab使用的解释性编程语言,可以被提前编译成字节文件以加速运行。并且c-mex文件能无限封装成函数相互调用,增强了MATLAB编程中的可扩展能力。
  使用NVIDIA公司提供的GPU硬件和软件支持,能编程实现cu文件运行到GPU上。合理使用GPU资源能将程序计算耗时成倍降低。

三、环境搭建

1. 环境预配置
  VS+CUDA的搭建方法详见另一篇博客(https://blog.csdn.net/weixin_40106401/article/details/89929816) ,这里强调使用VS2017,并且应先安装VS再安装CUDA。
2. C/C++编译器选择
  这里因为不仅仅使用Matlab编译运行C/C++程序,还要编译运行GPU程序,所以在选择C/C++编译器时参考下表,官方提供Matlab针对不同编译场景推荐的编译器(Complier)。由于我们需要用到GPU,所以建议选择VS2017,并配置好VS2017+CUDA联合编程环境。
  在这里插入图片描述
  查询链接:https://ww2.mathworks.cn/support/requirements/supported-compilers.html
  所以,VS2017+CUDA预先配置好极为重要!预先配置好的VS2017+CUDA包含Matlab编译c-mex用到的编译器。
3. Matlab设置
  mex -setup
  在这里插入图片描述
  在这里插入图片描述
  设置测试:

  在这里插入图片描述
  在这里插入图片描述
以上代码可以复制粘贴如下:

#include "mex.h"
 
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
    mexPrintf("mahello,mex!\n");
}

进行编译:mex helloMex.cpp
   在这里插入图片描述
   在这里插入图片描述
运行:helloMex
   在这里插入图片描述

四、实例测试:

接下来进行向量求和的实例测试,步骤和代码如下:
1.创建头文件AddVectors.h,并写入代码:

#ifndef __ADDVECTORS_H__
#define __ADDVECTORS_H__

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

#endif

2.创建文件AddVectors.cu,并写入代码:


#include "AddVectors.h"


__global__ void addVectorsKernel(float* A, float* B, float* C, int size)
{
    int i = blockIdx.x;
    if (i >= size)
        return;

    C[i] = A[i] + B[i];
}

void addVectors(float* A, float* B, float* C, int size)
{
    float *devPtrA = 0, *devPtrB = 0, *devPtrC = 0;

    cudaMalloc(&devPtrA, sizeof(float) * size);
    cudaMalloc(&devPtrB, sizeof(float) * size);
    cudaMalloc(&devPtrC, sizeof(float) * size);

    cudaMemcpy(devPtrA, A, sizeof(float) * size, cudaMemcpyHostToDevice);
    cudaMemcpy(devPtrB, B, sizeof(float) * size, cudaMemcpyHostToDevice);

    addVectorsKernel<<<size, 1>>>(devPtrA, devPtrB, devPtrC, size);

    cudaMemcpy(C, devPtrC, sizeof(float) * size, cudaMemcpyDeviceToHost);

    cudaFree(devPtrA);
    cudaFree(devPtrB);
    cudaFree(devPtrC);
}

3.编译cu文件生成obj文件,编译指令:

system('nvcc -c AddVectors.cu')

显示如下表示成果:
在这里插入图片描述
4.创建AddVectorsCuda.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]);

    plhs[0] = mxCreateNumericMatrix(numRowsA, numColsB, mxSINGLE_CLASS, mxREAL);
    float* C = (float*)mxGetData(plhs[0]);

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

4.编译mex,指令为:

mex AddVectorsCuda.cpp AddVectors.obj -lcudart -L"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0\lib\x64"

可以得到.mexw64文件,所有文件可以被展示为:
在这里插入图片描述
以上内容为mex生成全部步骤,可以被描述为下图:
在这里插入图片描述需要注意,以上操作生成的结果为mexw64文件,其函数调用入口为:mexw64文件的文件名(不包含后缀)
5.测试效果
在这里插入图片描述

编译可能报错1:
system(‘nvcc -c AddVectors.cu’)
nvcc fatal : Cannot find compiler ‘cl.exe’ in PATH
解决方法:
将VS2017内 cl.exe编译器对应的位置添加到系统环境变量中,并重启Matlab
寻找cl.exe建议使用Everything:
在这里插入图片描述

发布了17 篇原创文章 · 获赞 3 · 访问量 5452

猜你喜欢

转载自blog.csdn.net/weixin_40106401/article/details/90735014