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

原创 2016年05月31日 14:03:03

主要探讨的有两个问题:

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为误差,如下所示。


版权声明:本文为博主原创文章,未经博主允许不得转载。

并行计算矩阵乘法

  • 2015年12月11日 14:44
  • 1.36MB
  • 下载

java 浮点数值计算误差

问题 当我们运行如下函数时 public void test() { System.out.println(2.0-1.1); //=>0.8999999999999999 } 我们发现...

CUDA矩阵乘法计算

  • 2016年08月26日 22:26
  • 15KB
  • 下载

矩阵乘法求运行时间

  • 2017年04月15日 20:38
  • 1013B
  • 下载

SICP 习题 (2.13)解题总结:区间计算误差

SICP 习题 2.13 又像是一道数学证明题,和编程关系不大,不过这不能阻挡我们去完成它。题目要求我们证明,当误差百分比很小的时候,可以使用一个简单的公式,根据被乘区间的误差去计算乘积的误差。同时,...

java 多线程并行计算之矩阵乘法继承Thread类实现(星星笔记)

用java编写两个n阶的方阵A和B的相乘程序,结果存放在方阵C中,其中使用Runnable接口实现矩阵的乘法。 方阵A和B的初始值如下:(同时开两个线程)...

用于计算误差函数

  • 2015年09月12日 10:47
  • 1KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:矩阵乘法中的高阶计算时间和计算误差问题
举报原因:
原因补充:

(最多只允许输入30个字)