Created on 2013-8-5
URL : http://blog.sina.com.cn/s/blog_a502f1a30101mjch.html
@author: zhxfl
转载请说明出处

 #include <stdio.h>
#include <time.h>
#include <cuda_runtime.h>
__global__ void matrixMulCUDA(int *A,int *B,int * C,
dim3 dimsA,dim3 dimsB, dim3 dimsC)
{
int i = blockIdx.x;
int j = threadIdx.x; for(int k = ; k < dimsA.y; k++)
{
C[i * dimsC.y + j] += A[i * dimsA.y + k] * B[k * dimsB.y + j];
//printf("id = %d %d %d A = %d B = %d C = %d \n", i,j,k, A[i * dimsA.y + k],
// B[k * dimsB.y + j],
// C[i * dimsC.y + j]);
}
} int* matrixMultiplyByGpu(int *h_A, int n1,int m1,int *h_B,int n2,int m2)
{
int *d_A, *d_B, *d_C;
int *h_C; dim3 dimsA(n1,m1);
dim3 dimsB(n2,m2);
dim3 dimsC(n1,m2); int mem_size_A = dimsA.x * dimsA.y * sizeof(int);
int mem_size_B = dimsB.x * dimsB.y * sizeof(int);
int mem_size_C = dimsC.x * dimsC.y * sizeof(int); cudaMalloc((void**)&d_A, mem_size_A);
cudaMalloc((void**)&d_B, mem_size_B);
cudaMalloc((void**)&d_C, mem_size_C); cudaMemcpy(d_A, h_A, mem_size_A, cudaMemcpyHostToDevice);
cudaMemcpy(d_B, h_B, mem_size_B, cudaMemcpyHostToDevice); h_C = (int*)malloc(sizeof(int)*mem_size_C);
for(int i = ; i<dimsC.x * dimsC.y;i++)h_C[i] = ;
cudaMemcpy(d_C, h_C, mem_size_C, cudaMemcpyHostToDevice);
dim3 grid(dimsC.x,dimsC.y);
matrixMulCUDA<<<dimsC.x,dimsC.y>>>(d_A,d_B,d_C,dimsA,dimsB,dimsC);
cudaMemcpy(h_C, d_C, mem_size_C, cudaMemcpyDeviceToHost);
cudaFree(d_A);
cudaFree(d_B);
cudaFree(d_C);
return h_C;
} int* matrixMultiplyByCpu(int *h_A, int n1,int m1,int *h_B,int n2,int m2)
{
int *h_C = new int [n1 * m2];
for(int i = ; i < n1 * m2; i++)h_C[i] = ; for(int i = ; i < n1; i ++)
{
for(int j = ; j < m2; j++)
{
for(int k = ; k < m1; k++)
{
//h_C[i][j] = h_A[i][k] * h_B[k][j];
h_C[i * m2 + j] += h_A[i * m1 + k] * h_B[k * m2 + j];
}
}
}
return h_C;
} void outPutMatrix(char c,int *g, int n,int m)
{
return;
printf("matrix %c [%3d %3d]\n", c, n, m);
for(int i = ; i < n * m;i++)
{
printf("%5d ", g[i]);
if((i + ) % m == )printf("\n");
}
} const int base = ;
const int large = ;
int main()
{
int n1 = base;
int m1 = base + ;
int n2 = m1;
int m2 = base;
int *g1 = new int[n1 * m1];
int *g2 = new int[n2 * m2];
for(int i = ; i < n1 * m1;i++)g1[i] = rand() % large;
for(int i = ; i < n2 * m2;i++)g2[i] = rand() % large;
outPutMatrix('A',g1,n1,m1);
outPutMatrix('B',g2,n2,m2);
int *gg1,*gg2; clock_t start, finish; start = clock();
gg1 = matrixMultiplyByGpu(g1,n1,m1,g2,n2,m2);
finish = clock();
printf("GPU time = %f\n",(double)(finish - start) / CLOCKS_PER_SEC); start = clock();
gg2 = matrixMultiplyByCpu(g1,n1,m1,g2,n2,m2);
finish = clock();
printf("CPU time = %f\n",(double)(finish - start) / CLOCKS_PER_SEC); printf("check---");
for(int i = ; i< n1*m2;i++)
{
if(gg1[i] != gg2[i])
{
printf("wrong ans\n");
break;
}
}
outPutMatrix('',gg1,n1,m2);
outPutMatrix('',gg2,n1,m2);
}

版本一

版本一分析:

n 约等于 maxThreadsPerBlock

这里我们的矩阵空间复杂度大概是o(n^2),两个这样矩阵的乘法复杂度大概是0(n^3),这里使用GPU优化的方案是开启n个block,每个block有n个thread。这样我们的并发量就是n^2,也就是计算复杂度大概是0(n)。

版本一测试:

n 约等于 maxThreadsPerBlock

这里请注意,你的base + 1 < min(maxThreadsPerBlock,maxGridSize[0]),不然将超过cuda的最大计算量,会导致你的计算结果错误。

根据我的机子的情况 n = 1000,运行时间如下,可以看出计算时间大概是13.87倍

 #include <stdio.h>
#include <time.h>
#include <cuda_runtime.h>
__global__ void matrixMulCUDA(float *A,float *B,float * C,
dim3 dimsA,dim3 dimsB, dim3 dimsC)
{
int i = blockIdx.x;
int j = threadIdx.x; for(int k = ; k < dimsA.y; k++)
{
C[i * dimsC.y + j] += A[i * dimsA.y + k] * B[k * dimsB.y + j];
//printf("id = %d %d %d A = %d B = %d C = %d \n", i,j,k, A[i * dimsA.y + k],
// B[k * dimsB.y + j],
// C[i * dimsC.y + j]);
}
} float* matrixMultiplyByGpu(float *h_A, int n1,int m1,float *h_B,int n2,int m2)
{
float *d_A, *d_B, *d_C;
float *h_C; dim3 dimsA(n1,m1);
dim3 dimsB(n2,m2);
dim3 dimsC(n1,m2); int mem_size_A = dimsA.x * dimsA.y * sizeof(float);
int mem_size_B = dimsB.x * dimsB.y * sizeof(float);
int mem_size_C = dimsC.x * dimsC.y * sizeof(float); cudaMalloc((void**)&d_A, mem_size_A);
cudaMalloc((void**)&d_B, mem_size_B);
cudaMalloc((void**)&d_C, mem_size_C); cudaMemcpy(d_A, h_A, mem_size_A, cudaMemcpyHostToDevice);
cudaMemcpy(d_B, h_B, mem_size_B, cudaMemcpyHostToDevice); h_C = (float*)malloc(sizeof(float)*mem_size_C);
for(int i = ; i<dimsC.x * dimsC.y;i++)h_C[i] = ;
cudaMemcpy(d_C, h_C, mem_size_C, cudaMemcpyHostToDevice);
dim3 grid(dimsC.x,dimsC.y);
matrixMulCUDA<<<dimsC.x,dimsC.y>>>(d_A,d_B,d_C,dimsA,dimsB,dimsC);
cudaMemcpy(h_C, d_C, mem_size_C, cudaMemcpyDeviceToHost);
cudaFree(d_A);
cudaFree(d_B);
cudaFree(d_C);
return h_C;
} float* matrixMultiplyByCpu(float *h_A, int n1,int m1,float *h_B,int n2,int m2)
{
float *h_C = new float [n1 * m2];
for(int i = ; i < n1 * m2; i++)h_C[i] = ; for(int i = ; i < n1; i ++)
{
for(int j = ; j < m2; j++)
{
for(int k = ; k < m1; k++)
{
//h_C[i][j] = h_A[i][k] * h_B[k][j];
h_C[i * m2 + j] += h_A[i * m1 + k] * h_B[k * m2 + j];
}
}
}
return h_C;
} void outPutMatrix(char c,float *g, int n,int m)
{
return;
printf("matrix %c [%3d %3d]\n", c, n, m);
for(int i = ; i < n * m;i++)
{
printf("%5f ", g[i]);
if((i + ) % m == )printf("\n");
}
} const int base = ;
const int large = ;
int main()
{
int n1 = base;
int m1 = base + ;
int n2 = m1;
int m2 = base;
float *g1 = new float[n1 * m1];
float *g2 = new float[n2 * m2];
for(int i = ; i < n1 * m1;i++)g1[i] = rand() % large + 1.0f / 3.0f;
for(int i = ; i < n2 * m2;i++)g2[i] = rand() % large + 1.0f / 3.0f;
outPutMatrix('A',g1,n1,m1);
outPutMatrix('B',g2,n2,m2);
float *gg1,*gg2; clock_t start, finish; start = clock();
gg1 = matrixMultiplyByGpu(g1,n1,m1,g2,n2,m2);
finish = clock();
printf("GPU time = %f\n",(double)(finish - start) / CLOCKS_PER_SEC); start = clock();
gg2 = matrixMultiplyByCpu(g1,n1,m1,g2,n2,m2);
finish = clock();
printf("CPU time = %f\n",(double)(finish - start) / CLOCKS_PER_SEC); printf("check---");
for(int i = ; i< n1*m2;i++)
{
if(fabs(gg1[i] - gg2[i]) > 0.01)
{
printf("%f\n %f\nwrong ans\n",gg1[i],gg2[i]);
break;
}
}
outPutMatrix('',gg1,n1,m2);
outPutMatrix('',gg2,n1,m2);
}

版本二

版本一分析:

在版本一的基础上改成float运算

版本一测试:

结果如下,没有太大区别,本来预期是GPU的浮点计算能力会比CPU好很多的,但这里看来,并没有很明显的区别。

cuda(2) 矩阵乘法优化过程的更多相关文章

  1. [转]OpenBLAS项目与矩阵乘法优化

    课程内容 OpenBLAS项目介绍 矩阵乘法优化算法 一步步调优实现 以下为公开课完整视频,共64分钟: 以下为公开课内容的文字及 PPT 整理. 雷锋网的朋友们大家好,我是张先轶,今天主要介绍一下我 ...

  2. [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

    题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...

  3. 【BZOJ 3326】[Scoi2013]数数 数位dp+矩阵乘法优化

    挺好的数位dp……先说一下我个人的做法:经过观察,发现这题按照以往的思路从后往前递增,不怎么好推,然后我就大胆猜想,从前往后推,发现很好推啊,维护四个变量,从开始位置到现在有了i个数 f[i]:所有数 ...

  4. bzoj4870: [Shoi2017]组合数问题(DP+矩阵乘法优化)

    为了1A我居然写了个暴力对拍... 那个式子本质上是求nk个数里选j个数,且j%k==r的方案数. 所以把组合数的递推式写出来f[i][j]=f[i-1][j]+f[i-1][(j-1+k)%k].. ...

  5. 形态形成场(矩阵乘法优化dp)

    形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 ...

  6. HDU 5863 cjj's string game (矩阵乘法优化递推)

    题目大意:用k种字符构建两个长度为n的字符串(每种字符有无限多个),要求对应位置字符相同的连续子串最长长度为m,问方法数. 其中k,n,m是输入,n(1<=n<=1000000000), ...

  7. 斐波那契数列 矩阵乘法优化DP

    斐波那契数列 矩阵乘法优化DP 求\(f(n) \%1000000007​\),\(n\le 10^{18}​\) 矩阵乘法:\(i\times k\)的矩阵\(A\)乘\(k\times j\)的矩 ...

  8. 洛谷2151[SDOI2009]HH去散步(dp+矩阵乘法优化)

    一道良好的矩阵乘法优化\(dp\)的题. 首先,一个比较\(naive\)的想法. 我们定义\(dp[i][j]\)表示已经走了\(i\)步,当前在点\(j\)的方案数. 由于题目中限制了不能立即走之 ...

  9. 矩阵乘法优化DP复习

    前言 最近做毒瘤做多了--联赛难度的东西也该复习复习了. Warning:本文较长,难度分界线在"中场休息"部分,如果只想看普及难度的可以从第五部分直接到注意事项qwq 文中用(比 ...

随机推荐

  1. 【DP_背包专题】 背包九讲

    这段时间看了<背包九讲>,在HUST VJUDGE上找到了一个题单,挑选了其中16道题集中做了下,选题全部是HDU上的题,大多是简单题.目前做了点小总结,大概提了下每道题的思路重点部分,希 ...

  2. php中CURL技术模拟登陆抓取数据实战,抓取某校教务处学生成绩。

    这两天有基友要php中curl抓取教务处成绩的源码,用于微信公众平台的开发.下面笔者只好忍痛割爱了.php中CURL技术模拟登陆抓取数据实战,抓取沈阳工学院教务处学生成绩. 首先,教务处登录需要验证码 ...

  3. bounds的深入研究

    一.bounds的深入研究 1>frame:是以父控件的左上角为原点,描述的是一块区域的可视范围,    bounds:是以自己内容左上角为原点,描述的是可视范围在内容范围显示的区域 2> ...

  4. raywenderlich-iOS设计模式Part 1/2【译】

    原文地址:http://www.raywenderlich.com/86477/introducing-ios-design-patterns-in-swift-part-1 Update 04/22 ...

  5. 2014年度辛星html教程夏季版第三节

    接下来我们继续学习HTML中的标签,希望大家能够再接再厉,同时辛星也会支持大家,我们一起努力,一起加油.我们本小节来认识另外几个标签. *************空格和换行************** ...

  6. MOS管应用之放反接电路

    一.典型电路 1.电路1 说明: GND-IN 为电源接口的负极 GND 为内部电路的公共地 原理分析 正向接: VCC-IN通过R1.R2.MOS体二极管,最后回到GND-IN;然后GS电压升高,紧 ...

  7. 每天学点管理学知识——情绪ABC理论

    什么是ABC理论 ABC理论(ABC Theory of Emotion)是由美国心理学家埃利斯创建的.就是认为激发事件A(activating event 的第一个英文字母)只是引发情绪和行为后果C ...

  8. C++笔记1: 单例模式。(一个简单的设计模式在C++中复杂出翔。。)

    C++ 如果用指针new一个单例,内存不容易释放,所以Java和C#等语言中的单例模式在C++不适用... C++中,new申请的内存必须由delete释放,例如: Point p1; Point * ...

  9. EF5.0 对一个或多个实体的验证失败。有关详细信息,请参见“EntityValidationErrors”属性

    使用asp.net+EF5.0练习的时候,遇到这样一个问题: 对一个或多个实体的验证失败.有关详细信息,请参见“EntityValidationErrors”属性 但是感到很疑惑,去百度,说是关闭EF ...

  10. Length of Last Word | Leetcode

    Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the l ...