cuda matlab 混合编程,Matlab+CUDA混合编程(二)

1. 创建AddVectors.h文件

#ifndef __ADDVECTORS_H__

#define __ADDVECTORS_H_

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

#endif// ____ADDVECTORS_H_

2. 创建AddVectors.cu函数,这个是CUDA函数

#include "AddVectors.h"

#include "D:Matlab\extern\include\mex.h"

__global__ void addVectorsMask(float*A, float*B, float*C, int size)

{

int i = threadIdx.x + blockIdx.x * blockDim.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);

addVectorsMask<<>>(devPtrA,devPtrB, devPtrC, size);

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

cudaFree(devPtrA);

cudaFree(devPtrB);

cudaFree(devPtrC);

}

3. 用nvcc编译刚才生成的CUDA函数 执行命令:

system('nvcc -c AddVectors.cu')

这是可能出现错误,如下:

nvcc : fatal error : Cannot find compiler 'cl.exe' in PATH

出现这个错误应该是环境没有配置好,不过不要紧,可以通过路径直接编译,如4所示

4. 修改步骤3

system('nvcc -c AddVectors.cu -ccbin "D:Visual Studio 2012\VC\bin"')

引号中的部分是”cl.exe”的路径,都在Visual Studio 2012文件夹下,安装路径不同,版本不同,具体的位置也不同,不过都大同小异。 这时是个问题解决了,但又出现下一个问题,如下:

AddVectors.cu(2) : fatal error C1083:无法打开包括文件:“mex.h”:No such file or directory

也就是说找不到mex.h文件,继续修改

5. 修改步骤4

上个问题应该也是环境配置的问题,但是由于懒得麻烦,这次我就用了比较暴力的方法 在AddVectors.cu的包含头文件处直接加上绝对路径:

#include"D:Matlab\extern\includemex.h"

6. 继续步骤4

system('nvcc -c AddVectors.cu -ccbin "D:Visual Studio 2012\VC\bin"')

再次出现错误:

d:matlab\extern\include\matrix.h(252) : fatal error C1083:无法打开包括文件:“tmwtypes.h”:No such file or directory

意思是找不到tmwtypes.h路径,由于错误是发生在matrix.h文件的252行,因此决定看看到底为何

7. 在matrix.h文件中发现:

#include

怀疑是不是c编译的时候把tmwtypes.h当成库函数的头文件,所以为了保险起见,尝试将其修改为:

#include"tmwtypes.h"

新版的Matlab已经修正此问题

8. 继续步骤4

system('nvcc -c AddVectors.cu -ccbin "D:Visual Studio 2012\VC\bin"')

返回结果0,并生产AddVectors.obj文件,表示操作成功,大功告成。

9. 创建AddVectorsCuda.cpp文件

#include"mex.h"

#include"AddVectors.h"

// nlhs: 输出变量的个数(lefthand side,调用语句的左手面)

// plhs:输出的mxArray矩阵的头指针

// nrhs: 输入变量个数(righthand side,调用语句的右手面)

// prhs:输入的mxArray矩阵的头指针

// 如果有两个输入变量,那么prhs[0]指向第一个变量

//prhs[1]指向第二个变量

// Matlab的array使用mxArray类型来表示。

//plhs和hrhs都是指向mxArray类型的指针数组

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

{

// 判断输入参数个数是否满足条件

if (nrhs != 2)

mexErrMsgTxt("Invaidnumber of input arguments");

if (nlhs != 1)

mexErrMsgTxt("Invalidnumber of outputs");

// 判断输入参数的类型是否满足条件

if (!mxIsSingle(prhs[0])&& !mxIsSingle(prhs[1]))

mexErrMsgTxt("inputvector data type must be single");

// 获取输入参数维度

// mxGetM:得到输入矩阵的行数

// mxGetN:得到输入矩阵的列数

int numRowsA = (int)mxGetM(prhs[0]);//那么prhs[0]指向第一个变量

int numColsA = (int)mxGetN(prhs[0]);

int numRowsB = (int)mxGetM(prhs[1]);//prhs[1]指向第二个变量

int numColsB = (int)mxGetN(prhs[1]);

// 判断输入参数维度是否满足条件

if (numRowsA != numRowsB || numColsA != numColsB)

mexErrMsgTxt("Invalidsize. The sizes of two vectors must be same");

int minSize = (numRowsA < numColsA) ? numRowsA : numColsA; 38 int maxSize = (numRowsA > numColsA) ? numRowsA : numColsA;

if (minSize != 1)

mexErrMsgTxt("Invalidsize. The vector must be one dimentional");

//mxGetData 获取数据阵列中的数据

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

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

// 生成输入参数的mxArray结构体

plhs[0]= mxCreateNumericMatrix(numRowsA,numColsB, mxSINGLE_CLASS, mxREAL);

// 获取输出参数的指针

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

// 调用子程序

addVectors(A, B, C, maxSize);

}

10. 编译AddVectorsCuda.cpp并与obj文件链接

mex AddVectorsCuda.cpp AddVectors.obj -lcudart -L"C:Program Files\NVIDIA GPU Computing Toolkit\CUDAv5.5\libx64"

生成AddVectorsCuda.mexw64文件。

表示成功。

测试。

11. 测试

A = single([1 2 3 4 5 6 7 8 9 10]);

B = single([10 9 8 7 6 5 4 3 2 1]);

C = AddVectorsCuda(A,B);

得到: C = 11 11 11 11 11 11 11 11 11 11

大功告成。

注: mex命令中的参数:

% -lcudart 表明使用了CUDA运行时库

% -lcublas 表明使用了CUDABLAS库

% -L”…” 使用的库的库文件路径

% -L”…” 使用的库的头文件路径

虽然上述步骤成功了,但是看着步骤是相当繁琐的,因此我们可以考虑将其写到一个函数中,以后再使用的时候进行适当的修改就可。

下面生成runAddVectors.m

%runAddVectors.m

clc

clear all

close all

disp('1.nvccAddVectors.cu compiling...');

system('nvcc-c AddVectors.cu -ccbin "D:Visual Studio2012VCbin"')

disp('nvcccompiling done!');

disp('2.C/C++ compiling for AddVectorsCuda.cpp withAddVectors.obj...');

mex AddVectorsCuda.cpp AddVectors.obj -lcudar-L"C:Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.5\libx64"

disp('C/C++compiling done!');

disp('3.TestAddVectorsCuda()...');

disp('Twoinput arrays:');

A = single([1 2 3 4 5 6 7 8 9 10]);

B = single([10 9 8 7 6 5 4 3 2 1]);

C = AddVectorsCuda(A,B);

如上所示,再编译其他文件的时候只用适当的修改文件名就可以了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值