MATLAB2014b下运行cuda6.5安装方法及例程

<span style="color:#ff0000;">准备条件:首先确认电脑具有nvidia的显卡,如果没有的话,是不能进行cuda编程的</span>

要想在matlab下运行cuda,毋庸置疑,我们至少需要matlab,cuda,visual studio三款软件,在这里,笔者使用的是matlab2014b,cuda6.5和visual studio 2013的版本,至于版本要求,一般是matlab的版本要大于visual studio的版本,而cuda的版本要通过nvidia的官网查看是否能兼容vs的版本。

安装顺序:笔者推荐为matlab—visual studio—cuda,一般把cuda放在vs后安装,是因为如果cuda在vs之前安装,可能会导致vs安装之后新建项目里不会出现nvidia的项目。

安装注意:把360等杀毒软件关闭,以防止会阻挡进程,另外,一定要安装完整版的,特别是visual studio,一定要安装带有相关环境的,否则在matlab中用到mex时,会提示找不到相关的环境。

安装细节:

1,安装matlab2014b,至于激活方法等网上均有例程;

2,安装visual studio 2013,傻瓜式安装;

3,从nvidia官网上下载cuda6.5,6.5版本已经集成了cuda中所有的组件,因此只要选择好系统的版本等,直接下载就好了,下载地址为:https://developer.nvidia.com/cuda-downloads,具体安装方法和图示可以参考:http://www.360doc.com/content/14/1012/09/19076531_416241911.shtml

4,cuda6.5安装完成后(建议直接用默认目录),要设置相关的环境变量,右键我的电脑,属性——高级系统系统设置—高级—环境变量,安装完毕后,可以看到系统中多了CUDA_PATH和CUDA_PATH_V6_0两个环境变量,接下来,还要在系统中添加以下几个环境变量(注意复制粘贴的时候一定不要粘上后面的空格,我为了它纠结了一天):

CUDA_SDK_PATH = C:\ProgramData\NVIDIA Corporation\CUDA Samples\v6.5

CUDA_LIB_PATH = %CUDA_PATH%\lib\x64

CUDA_BIN_PATH = %CUDA_PATH%\bin

CUDA_SDK_BIN_PATH = %CUDA_SDK_PATH%\bin\x64

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就差不多配好了。

5,运行测试代码,我在安装cuda的时候,一直使用的默认目录,打开C:\ProgramData\NVIDIA Corporation\CUDA Samples\v6.5\1_Utilities\deviceQuery,打开deviceQuery_vs2013,测验一下,如果运行成功,说明配置好了。接着打开一个新建的项目,直接选择nvidia的cuda6.5,里面有一个示范代码,改变一下项目的属性设置(这里和你电脑nvidia显卡的型号有关),

6,这样的vs和cuda的接口就验证成功了,接着我们开始进行matlab和vs的接口。参考:http://blog.csdn.net/hongqiang200/article/details/6273406

(1) 编写基于CUDA的.cu程序;
(2) 下载nvmex_tool压缩包(http://www.cs.ucf.edu/~janaka/gpu/using_nvmex.htm),解压缩;
(3) 将解压缩后的nvmex.pl文件复制至Matlab安装文件夹下的Bin文件夹内,X:/Matlab/R2009a/Bin/;
(4) 将压缩后的nvmex_tool文件夹内的nvmex.m文件、nvmex_helper.m文件以及nvmexopts.bat文件放至你的.cu文件,使他们位于同一文件夹内。
(5) 将该文件夹设为Matlab当前工作目录

(6)在matlab要运行的.m文件里,前面输入:system('nvcc -c conv2d.cu -ccbin "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin"');

(7)接着在下面输入:

mex conv2dCuda.cpp conv2d.obj -lcudart -L"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v6.5\lib\x64"

总运行代码如下:(以卷积为例)

matlab的.m文件:

%makeInMatlab
clc, clear
system('nvcc -c conv2d.cu -ccbin "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin"');
fprintf('compile conv2d.cu, succeed!\n');
mex conv2dCuda.cpp conv2d.obj -lcudart -L"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v6.5\lib\x64"
fprintf('mex conv2dCuda.cpp, succeed!\n');
fprintf('testing...\n');

%%
N = int32(10000);
n_V = int32(32);
n_W = int32(8);
K = int32(16);
n_H = n_V - n_W + 1;
V = single(rand(N, n_V * n_V));
W = single(rand(K, n_W * n_W));

tic,
H = conv2dCuda(V', W', n_V, n_W, N, K);
H = H';
%H = reshape(H,[n_H*n_H, N])';
gpu_time = toc;
fprintf('GPU computing time: %f seconds\n', gpu_time);

tic,
H_cpu = single(zeros(N, n_H * n_H));
for i = 1:N,
    Vi = reshape(V(i,:),[n_V, n_V]);
    Hi = zeros(n_H, n_H);
    for k = 1:K,
        Wk = reshape(W(k,:),[n_W,n_W]);
        Hi = Hi + conv2(Vi, Wk, 'valid');
        %Hi = Hi + filter2(Wk, Vi, 'valid');
    end
    H_cpu(i,:) = Hi(:)';
end
cpu_time = toc;
fprintf('CPU computing time: %f seconds\n', cpu_time);

speed_up = cpu_time/gpu_time;
fprintf('%f times speed up!\n',speed_up);

err = abs(H-H_cpu);
epsilon = 3*1e-4;
err(err<epsilon) = 0;
fprintf('err = %.4f\n',sum(err(:)));

%% 
% H(:,1:10)
% H_cpu(:,1:10)
cuda核里的.cu文件:

#include "conv2d.h"
#include <stdio.h>
#include "D:\Program Files\MATLAB\R2014b\extern\include\tmwtypes.h"
#include "D:\Program Files\MATLAB\R2014b\extern\include\mex.h"

#define TILE_WIDTH 16

__global__ void conv2d_valid_OnDevice(float *V, float *W, float *H, int n_V, int n_W, int n_H, int N, int n_F)
{   
    float temp;
    int i,j,k,l;
    for(i=0; i < n_V/TILE_WIDTH; i++){
        for(j = 0; j < n_V/TILE_WIDTH; j++){           
            int idH_m = threadIdx.x + i*TILE_WIDTH;
            int idH_n = threadIdx.y + j*TILE_WIDTH;
            if(idH_m >= n_H || idH_n >= n_H)
                continue;

            temp = 0;

            for(k=0; k<n_W; k++){
                for(l=0; l<n_W; l++){
                    float v = V[blockIdx.x*n_V*n_V + (idH_m + k)*n_V + (idH_n + l)];
                    float w = W[blockIdx.y*n_W*n_W + (n_W-1-k)*n_W + (n_W-1-l)];  //因为是卷积,所以将w反排
                    temp += v*w;
                }
            }
            atomicAdd(&H[blockIdx.x*n_H*n_H + idH_m*n_H + idH_n], temp);
        }
    }
}

void conv2d_valid(float *V, float *W, float *H, int n_V, int n_W, int n_H, int N, int n_F)
{
    float *d_V, *d_W, *d_H;
    
    size_t size_V = N * n_V * n_V * sizeof(float);
    size_t size_W = n_F * n_W * n_W * sizeof(float);
    size_t size_H = N * n_H * n_H * sizeof(float);

    dim3 dimBlock(TILE_WIDTH,TILE_WIDTH);
    dim3 dimGrid(N, n_F);

    cudaMalloc((void**)&d_V, size_V);
    cudaMalloc((void**)&d_W, size_W);
    cudaMalloc((void**)&d_H, size_H);

    cudaMemcpy(d_V, V, size_V, cudaMemcpyHostToDevice);
    cudaMemcpy(d_W, W, size_W, cudaMemcpyHostToDevice);
    cudaMemcpy(d_H, H, size_H, cudaMemcpyHostToDevice);

    conv2d_valid_OnDevice<<<dimGrid, dimBlock>>>(d_V, d_W, d_H, n_V, n_W, n_H, N, n_F);

    cudaMemcpy(H, d_H, size_H, cudaMemcpyDeviceToHost);

    cudaFree(d_V);
    cudaFree(d_W);
    cudaFree(d_H);
}

void printArray(float *A, int numRows, int numCols)
{
    int i,j;
    for(i=0; i<numRows; i++){
        for(j=0; j<numCols; j++){
            printf("%.2f ",A[i*numCols+j]);
        }
        printf("\n");
    }
}

// reset matrix:
// e.g. A=[1 2 3 4 5; 6 7 8 9 10];  => A=[1 3 5 7 9; 2 4 6 8 10];
void resetMatrix_byRow(float *A, int numRows, int numCols)
{
    float *B = (float*)malloc(sizeof(float)*numRows*numCols);
    int i,j;
    for(i=0; i<numRows; i++){
        for(j=0; j<numCols; j++){
            B[i*numCols + j] = A[i*numCols + j];
        }
    }

    int m_A,n_A,m_B,n_B;
    for(i=0; i<numRows*numCols; i++){
        m_A = i/numCols;
        n_A = i%numCols;

        m_B = i%numRows;
        n_B = i/numRows;

        A[m_A*numCols+n_A] = B[m_B*numCols+n_B];
    }

    free(B);
}
另外新建一个.cpp和.h文件,用来提供matlab数据和c/c++数据的转换分别为:

#ifndef __CONV2D_H__
#define __CONV2D_H__

extern void resetMatrix_byCol(float *A, int numRows, int numCols);
extern void resetMatrix_byRow(float *A, int numRows, int numCols);
extern void printArray(float *A, int numRows, int numCols);
extern void conv2d_valid(float *V, float *W, float *H, int n_V, int n_W, int n_H, int N, int n_F);
//extern void conv2d_full(float *V, float *W, float *H, int n_V, int n_W, int n_H);

#endif

#include "D:\Program Files\MATLAB\R2014b\extern\include\mex.h"
#include "conv2d.h"
#include <math.h>
// nlhs: 输出变量的个数(lefthand side,调用语句的左手面)
// plhs:输出的mxArray矩阵的头指针
// nrhs: 输入变量个数(righthand side,调用语句的右手面)
// prhs:输入的mxArray矩阵的头指针
// 如果有两个输入变量,那么prhs[0]指向第一个变量
// prhs[1]指向第二个变量
// Matlab的array使用mxArray类型来表示。
// plhs和hrhs都是指向mxArray类型的指针数组

void mexFunction(int nlhs, 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");

    // mxGetData 获取数据阵列中的数据
    float *V = (float*)mxGetData(prhs[0]);
    float *W = (float*)mxGetData(prhs[1]);
    int *p_nV = (int*)mxGetData(prhs[2]);
    int *p_nW = (int*)mxGetData(prhs[3]);
    int *p_N = (int*)mxGetData(prhs[4]);
    int *p_K = (int*)mxGetData(prhs[5]);
    
    int n_V = *p_nV;
    int n_W = *p_nW;
    int N = *p_N;
    int K = *p_K;
    
    int n_H = n_V - n_W + 1;  
    
    //printf("n_V = %d, n_W = %d, n_H = %d\n",n_V,n_W,n_H);
    
    // 生成输出参数的mxArray结构体
    int numRowsH = N;   //这是C中矩阵的行,正好对应matlab矩阵的列!!!
    int numColsH = n_H * n_H;
    
    plhs[0] = mxCreateNumericMatrix(numColsH, numRowsH, mxSINGLE_CLASS, mxREAL);
    
    // 获取输出参数的指针
    float *H = (float*)mxGetData(plhs[0]);

    // 初始化
    int i,j;
    for(i = 0; i<numRowsH; i++){
        for(j=0; j<numColsH; j++){
            H[i*numColsH + j] = 0;
        }
    }
    
    // 调用子程序
    conv2d_valid(V, W, H, n_V, n_W, n_H, N, K);
    
    // 重排后使得存储方式与matlab一致
    //resetMatrix_byRow(H, numRowsH, numColsH);
 } 
显示结果如下:

MEX completed successfully.
mex conv2dCuda.cpp, succeed!
testing...
GPU computing time: 2.242399 seconds
CPU computing time: 20.623921 seconds
9.197258 times speed up!
err = 0.0000


参考博客:

http://www.360doc.com/content/14/1012/09/19076531_416241911.shtml
http://blog.csdn.net/hongqiang200/article/details/6273406



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值