Matlab使用CUDA--利用cudamex

目录

    • 一、编写可供Matlab编译的CUDA代码
    • 1、 待编译的程序需要包含的头文件
    • 2、待编译程序的程序入口函数mexFunction
    • 3、参数传递方法
    • 二、使用Matlab编译CUDA工程并调用
    • 1、mexcuda编译指令
    • 2、
    • 参考文章:

一、编写可供Matlab编译的CUDA代码

1、 待编译的程序需要包含的头文件

在项目中添加新建项 mexFunction.h,头文件内容如下

#ifndef _mexFunction_H
#define _mexFunction_H
 
#include "MatlabPath\extern\include\mex.h"
#include "MatlabPath\toolbox\parallel\gpu\extern\include\gpu\mxGPUArray.h"
 
#endif

MatlabPath是本机Matlab的安装目录,mex和mxGPUArray的文件路径可能与上述不符,在Matlab安装目录中搜索mex.h和mxGPUArray.h,将搜索结果所在的路径复制过来即可。
这里如果单独写了.h头文件也可以跟其他的放在一起,具体看程序。

2、待编译程序的程序入口函数mexFunction

与c语言不同,使用Matlab编译代码时的程序入口函数为mexFunction函数,函数定义规范为:

void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
    /**** 程序内容 ****/		
}

调用语句包括后面的参数都是固定的,
nlhs:输出参数数目 (Left-hand side)
plhs:指向输出参数的指针
nrhs:输入参数数目
prhs:指向输入参数的指针

例如,[a,b]=test(c,d,e)
利用mex函数调用test时,传给test的这三个参数分别是 prhs[0]=c ,prhs[1]=d ,prhs[2]=e
当函数返回时,将会把你放在plhs[0],plhs[1]里的地址赋给a和b,达到返回数据的目的。

3、参数传递方法

(1)获取矩阵大小

//输入矩阵的行数
row = mxGetM(prhs[0]);
 
//输入矩阵的列数
column = mxGetN(prhs[0]);

(2)给matlab分配动态内存空间–mxCalloc

void *mxCalloc(size_t n,size_t size)

参数定义:
n:分配空间的大小。
size:每个元素所占的字节。
返回值:
成功的话会返回一个指向一块动态分配的内存空间:
空间不足的时候mxCalloc将执行不成功。

//程序实例
(char*)mxCalloc(A, sizeof(char))

(3)数据类型
1、mxArray:
在VC中,所有和Matlab的数据交互都是通过mxArray来实现的。
创建任何数组前都需要加上mxArray。例如:

 mxArray* A[]

2、mwSize:
图像的维度数及每一维度的大小的数据类型

//三维
const mwSize dims[] = { x, y, z };
//二维
const mwSize dim[] = { x, y };

3、uint8_t
存放图像信息的矩阵的数据类型
(4)获得字符串阵列的内容–mxGetString
将字符串mxArray的数据复制到c风格的字符串中

//定义
int mxGetString(const mxArray*array_ptr,char*buf,int buflen);
//调用方式
a=mxGetString(pm, str, strlen)

pm:指向mxChar数组的指针;
str:开始的位置。mxGetString将字符数据写入str,然后在C语言中用NULL字符结束字符串(以C字符串的方式)。str既可以指向动态内存,也可以指向静态内存;
strlen:str指向的目标缓冲区的字节大小。通常,在C语言中,设置strlen为1加上mxArray中pm所指向的元素数。要获得元素的数量,请使用mxGetM或mxGetN。例如:

int arg0len = mxGetM(prhs[0]) * mxGetN(prhs[0]) + 1;

与之联用的函数还有:

//mxIsChar:判断阵列是否为字符串类型的阵列。
  bool mxIsChar(const mxArray *array_ptr);
//mxGetString:获得字符串阵列的内容。
  int mxGetString(const mxArray*array_ptr,char*buf,int buflen);
//mxCreateString:创建一个1*N维的字符串阵列。
  mxArray *mxCreateString(const char *str);

(5)mxGetData函数
mxGetData函数可以用来获取mxArray型指针内容。

data = (double*)mxGetData(mat);

(6)mxGetPr和mxGetPi函数

//使用方式
#include "matrix.h"
double *mxGetPr(const mxArray *pm);

mxGetPr可以从将pm指向的数据从matlab传递到c中

//获取阵列的实数部分的数据指针
 double *mxGetPr(const mxArray *array_ptr);
//获取阵列的虚数部分的数据指针。
double *mxGetPi(const mxArray *array_ptr);

(7)mxCreateNumericArray函数
生成N维的矩阵,官方定义:

mxArray *mxCreateNumericArray(mwSize ndim, const mwSize *dims,
    mxClassID classid, mxComplexity ComplexFlag);
//使用示例
plhs[0] = mxCreateNumericArray(3, dims, mxSINGLE_CLASS, mxREAL);

参数定义:
ndim:创建的矩阵维度
dims:包含尺寸的数组
classid:类标识符,指定数据为哪种类型。Classid决定数值数据在内存中的表示方式。例如,mxCreateNumericMatrix将mxINT16_CLASS值存储为16位有符号整数。
ComplexFlag:复杂数组指示符,指定为mxComplexity值。矩阵中的元素类型依 mxComplexity 的值而定。
1>如果 mxComplexity 的值是 mxREAL 则矩阵中的元素类型全是实数,matlab会分配足够的空间来存放这些实数,并将这些实数初始化为0;
2>如果 mxComplexity 的值是 mxCOMPLEX ,则matlab分配足够的空间来存放这个复数空间(实部地址为 pr ,虚部地址为 pi ),实部和虚部都初始化为0。
classid与数据类型对应表:
Matlab使用CUDA--利用cudamex_第1张图片

二、使用Matlab编译CUDA工程并调用

1、mexcuda编译指令

想要在Matlab中调用.cu文件的程序,需要先把.cu文件编译成mex cuda工程,编译需要在matlab中完成,具体的编译指令为:
官方文档
(1)如果工程中有多个源文件option1,option2,……,optionN,则需要输出使用到的所有源文件的路径,此处建议输入文件的完整路径(绝对路径),而非相对路径,例如:

mexcuda E:\Work\cudaSource1.cu...
E:\Work\cudaSource2.cu...
E:\Work\cSource1.cpp...
E:\Work\cSource2.cpp

(2)如果文件中使用了动态并行,则需要在对应的文件前面加上-dynamic,例如:

mexcuda -dynamic E:\Work\cudaDynamicSource1.cu ...
E:\Work\cudaNoDynamicSource2.cu ...
-dynamic E:\Work\cudaDynamicSource3.cu ...
E:\Work\cSource1.cpp ...

(3) 如果文件中使用了CUDA库函数(cufft、cublas等),则需要加入库函数路径,格式是
‘库函数完整文件路径’ -l+库函数名称,例如:

mexcuda  'C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.3\lib\x64\cufft.lib' -lcufft ...
-dynamic E:\Work\cudaDynamicSource1.cu ...
E:\Work\cudaNoDynamicSource2.cu ...
-dynamic E:\Work\cudaDynamicSource3.cu ...
E:\Work\cSource1.cpp ...

(4)保存写好的编译文件并执行,出现MEX已成功完成证明编译成功,此时文件夹中应该出现.mexw64执行文件,该文件名称与mexcuda指令后的第一个文件名保持一致,例如,(3)中生成的文件名称为cudaDynamicSource1.mewx64。

一般没有特殊需求,普通的编译文件只需要一行:

mexcuda -v 文件名***.cu

注意:
1、mexw64/mexa64文件是matlab下使用的一种特殊的函数封装形式。这种函数一般是用C/C++语言编写的,在使用的时候也像一个普通m文件一样按照文件名调用,只是不可能看到源码。
2、按照matlab的调用顺序规则,mex比m有更高的优先级,即只会调用***.mexa64而不调用***.m。
3、mexa64是linux64位下编译和使用的版本,不能在windows下用。windows64位下编译的是mexw64。

2、

参考文章:

https://blog.csdn.net/hsc0709/article/details/124182076
https://zhidao.baidu.com/question/1430803365903554779.html

你可能感兴趣的:(CUDA,matlab,matlab,c++)