关闭

矩阵乘法中的高阶计算时间和计算误差问题

标签: CUDA并行处理gpu
627人阅读 评论(0) 收藏 举报
分类:

主要探讨的有两个问题:

1、当矩阵维度为16*16,2048*2048时,可以计算出来(用全1矩阵进行测试),并且加速比大于1(GPU快),可是当矩阵维度提升到4096*4096时,此时会出错(计算不准确,显示器驱动程序已停止响应 并且已成功恢复 ,怎么解决?

2、先前测试了全1矩阵,现在改成随机数矩阵(包括小数和整数),16*16等矩阵都不能得到正确的结果,怎么办?

首先贴出多线程的矩阵乘法代码:

kernel程序:

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <stdio.h>

#include "matrixMul.h"

#define BLOCK_SIZE 16

// 核函数
__global__ void MatrixMulKernel( double* Md, double* Nd,double* Pd,int WidthM, int WidthN)
{
        //计算Pd中的元素索引
        int Row = blockIdx.y * BLOCK_SIZE + threadIdx.y; //行
        int Col = blockIdx.x * BLOCK_SIZE + threadIdx.x; //列

        float Pvalue = 0.0;
        for (int k = 0; k < WidthM; k++)
        {
                Pvalue += Md[Row * WidthM + k] * Nd[k * WidthN + Col];
        }
        //每个线程负责计算P中的一个元素
        Pd[Row * WidthN + Col] = Pvalue;
}

// 矩阵乘法
void matrixMul( double* M,double* N,double* P,int WidthM, int WidthN, int HeightM, int HeightN)
{
        double *Md, *Nd, *Pd;

    //字节长度
        int sizeM = WidthM * HeightM * sizeof(double);
    int sizeN = WidthN * HeightN * sizeof(double);
    int sizeP = WidthN * HeightM * sizeof(double);    

        cudaMalloc((void**)&Md, sizeM);
        cudaMalloc((void**)&Nd, sizeN);
        cudaMalloc((void**)&Pd, sizeP);

        //Copies a matrix from the memory* area pointed to by src to the memory area pointed to by dst
        cudaMemcpy(Md, M, sizeM, cudaMemcpyHostToDevice);
        cudaMemcpy(Nd, N, sizeN, cudaMemcpyHostToDevice);

    dim3 dimGrid( HeightM / BLOCK_SIZE , WidthN / BLOCK_SIZE);
        dim3 dimBlock( BLOCK_SIZE,  BLOCK_SIZE);        

        MatrixMulKernel<<< dimGrid, dimBlock >>>(Md, Nd, Pd, WidthM, WidthN);

        cudaMemcpy(P, Pd, sizeP, cudaMemcpyDeviceToHost);

        //释放设备上的矩阵
        cudaFree(Md);
        cudaFree(Nd);
        cudaFree(Pd);

    cudaDeviceReset();

}

mex调用程序
system('nvcc -c matrixMul.cu  -gencode arch=compute_50,code=sm_50 -ccbin "E:\VS2012\2012\VC\bin"')
mex matrixMulCuda.cpp matrixMul.obj -lcudart -L"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\lib\x64";

disp('2.Input two matrix:')

%A=rand(16);
% B=rand(16);

A=ones(4096,4096);
B=ones(4096,4096);

C_gpu =matrixMulCuda(A,B);

论坛链接:http://bbs.gpuworld.cn/forum.php?mod=viewthread&tid=10280&extra=page%3D1


第一个问题:当测试4096*4096的矩阵时,此时GPU的计算时间不仅超过了matlab的计算时间,更主要的时超出了GPU的设置时间(TDR一般为2s),测试需要打开nsight visual studio edition进行TDR的设置,至于如何设置,博客中可以找见。

第二个问题实际上是编程的一个低级错误,cuda是按列存储的,按列取出并计算,而matlab是按行来的,所以计算结果会出现很大分歧、很大误差,此时我们在调用矩阵计算函数matrixMulCuda(A,B)B之前,将其转置后再计算,或者直接变成matrixMulCuda(B,A)也可以,这样就可以和matlab的计算结果进行比对了。

在整数的计算上,是没有误差的(2048*2048随机矩阵)

浮点数的计算上,误差较小(2048*2048随机矩阵),F为误差,如下所示。


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:49923次
    • 积分:1071
    • 等级:
    • 排名:千里之外
    • 原创:54篇
    • 转载:31篇
    • 译文:0篇
    • 评论:6条
    最新评论