MATLAB下使用CUDA。
#@author: gr
#@date: 2014-04-08
#@email: [email protected]
一、 Matlab & C
1. 概念
Matlab 与 C 混编可以提高程序运行效率。
2. C文件
C文件需要在引入头文件mex.h ,我的mex.h 位置在/opt/MATLAB/R2013a/extern/include/mex.h 。
#include <mex.h>
Matlab与C文件的接口函数是mexFunction 。
mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]){
// entry
}
mexFunciton 就像main 函数一样,是Matlab 调用的入口。其中,nlhs 是输出参数个数,plhs 是输出参数;nrhs 是输入参数个数,prhs 是输入参数,它是一个只读的变量。
3. 常用函数
4. 编译
需要将C 语言源文件编译成可执行文件才能被Matlab 调用,并且编译出来的文件比同名的.m 文件执行优先级更高,即如果两个同名先执行编译出来的文件。
编译分两个步骤,先编译生成.o 中间文件(windows下是.obj ),再链接生成.mexa64 文件(linux32位是.mexglx ,windows是.mexw64 ),这个.mexa64 文件可以直接被Matlab 使用。
具体操作是打开Matlab ,进入要编译文件的文件夹,要先配置一下编译器。
# configure the compiler
mex -setup
# compile
mex -c hello.c -o hello.o
# link
mex -O hello.o
之后在Matlab 中直接敲hello 便可以调用hello 程序。
二、Matlab & CUDA
1. Cuda的kernel函数
代码分为两部分,一部分代码在主机(host)上执行,另一部分则在设备(device)上执行,kernel 函数是在GPU上执行的函数。
进行Cuda 编译的一般步骤:
- 在主机上申请device内存
- 将主机数据拷贝到设备上
- 在设备上进行运算
- 主机将设备上的运算结果拷贝回主机内存
- 释放设备内存
如下定义kernel 函数:
__global__ static void kernel_function(int* a, int* b, int* c){
// realted code
}
2. Cuda的启动
在主机上通过调用kernel 函数名进行启动。
# 启动
kernel_function<<<block, thread>>>(a, b, c);
其中thread是一个block 中启动的线程数,而block 是需要划分为多少个block .块内的thread 可以时行数据同步和共享内存,不同的block 之间无法进行同步。a, b, c是相关的参数。
具体CUDA相关知识请看博客。
3. 编译
因为Cuda 有自己的编译器nvcc ,所以需要调用这个编译器去编译C文件。我们可以在Matlab 中利用一个脚本进行编译。
nvmex('hello.c');
function [ path, filename, zaet, fd ] = nvmex( cuFileName )
%NVMEX Summary of this function goes here
% Detailed explanation goes here
file_split = regexp(cuFileName, '\.', 'split');
filename = file_split{1};
if ispc % Windows
CUDA_LIB_LOCATION = 'C:\CUDA\lib';
Host_Compiler_Location = '-ccbin "D:\Program Files\Microsoft Visual Studio 9.0\VC\bin"';
PIC_Option = '';
else % Mac and Linux
CUDA_LIB_Location = '/usr/local/cuda/lib64';
Host_Compiler_Location = '';
PIC_Option = '--compiler-options -fPIC';
end
% compile .o file
nvccCommandLine = [ ...
'nvcc --compile ' cuFileName ' ' Host_Compiler_Location ' ' ...
' -o ' filename '.o ' ...
PIC_Option ...
' -I' matlabroot '/extern/include ' ...
];
disp(nvccCommandLine);
status = system(nvccCommandLine);
if status < 0
error 'Error invoking nvcc';
end
% link .mexa64 file
mexCommandLine = ['mex (''' filename '.o'', ''-L' CUDA_LIB_Location ''', ''-lcudart'')'];
disp(mexCommandLine);
eval(mexCommandLine);
end
|
请发表评论