cuda(2) 矩阵乘法优化过程
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) 矩阵乘法优化过程的更多相关文章
- [转]OpenBLAS项目与矩阵乘法优化
课程内容 OpenBLAS项目介绍 矩阵乘法优化算法 一步步调优实现 以下为公开课完整视频,共64分钟: 以下为公开课内容的文字及 PPT 整理. 雷锋网的朋友们大家好,我是张先轶,今天主要介绍一下我 ...
- [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】
题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...
- 【BZOJ 3326】[Scoi2013]数数 数位dp+矩阵乘法优化
挺好的数位dp……先说一下我个人的做法:经过观察,发现这题按照以往的思路从后往前递增,不怎么好推,然后我就大胆猜想,从前往后推,发现很好推啊,维护四个变量,从开始位置到现在有了i个数 f[i]:所有数 ...
- bzoj4870: [Shoi2017]组合数问题(DP+矩阵乘法优化)
为了1A我居然写了个暴力对拍... 那个式子本质上是求nk个数里选j个数,且j%k==r的方案数. 所以把组合数的递推式写出来f[i][j]=f[i-1][j]+f[i-1][(j-1+k)%k].. ...
- 形态形成场(矩阵乘法优化dp)
形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 ...
- HDU 5863 cjj's string game (矩阵乘法优化递推)
题目大意:用k种字符构建两个长度为n的字符串(每种字符有无限多个),要求对应位置字符相同的连续子串最长长度为m,问方法数. 其中k,n,m是输入,n(1<=n<=1000000000), ...
- 斐波那契数列 矩阵乘法优化DP
斐波那契数列 矩阵乘法优化DP 求\(f(n) \%1000000007\),\(n\le 10^{18}\) 矩阵乘法:\(i\times k\)的矩阵\(A\)乘\(k\times j\)的矩 ...
- 洛谷2151[SDOI2009]HH去散步(dp+矩阵乘法优化)
一道良好的矩阵乘法优化\(dp\)的题. 首先,一个比较\(naive\)的想法. 我们定义\(dp[i][j]\)表示已经走了\(i\)步,当前在点\(j\)的方案数. 由于题目中限制了不能立即走之 ...
- 矩阵乘法优化DP复习
前言 最近做毒瘤做多了--联赛难度的东西也该复习复习了. Warning:本文较长,难度分界线在"中场休息"部分,如果只想看普及难度的可以从第五部分直接到注意事项qwq 文中用(比 ...
随机推荐
- 服务器卡死,重启报错: INFO: task blocked for more than 120 seconds
问题:服务器负载很高,但是CPU利用率不高.服务器经常夯住,网站打不开,SSH连接非常不稳定,输入命令夯住. 重启服务器报错: INFO: task blocked for more than 120 ...
- scp 命令使用
scp 是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且 scp传输是加密的.可能会稍微影响一下速度.当你服 ...
- html定义对象
<object>定义一个对象<param>为对象定义一个参数 参数的名称:name = "" 参数的值:value=""classid: ...
- javascript下动态this与动态绑定实例代码
this 的值取决于 function 被调用的方式,一共有四种, 如果一个 function 是一个对象的属性,该 funtion 被调用的时候,this 的值是这个对象. 如果 function ...
- Oracle课堂实验一“表的使用”代码。
--创建本地管理表空间CustomerTBSCREATE TABLESPACE CustomerTBS DATAFILE 'd:\Oracle11\product\11.2.0\ora ...
- jinja2 宏的简单使用总结(macro)
Table of Contents 1. 简介 2. 用法 3. 参数和变量 4. 注意事项 4.1. macro的变量只能为如下三种: 4.2. 和block的关系: 5. 参考文档 1 简介 ji ...
- C++ static全局变量与全局变量的区别/static全局函数与全局函数的区别
全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量.全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式.这两者在存储方式上并无不同.这两者的区别虽在于非静态全局变量 ...
- pyes-elasticsearch的python客户端使用笔记
elasticsearch入门: http://www.qwolf.com/?p=1387 一.重要的概念 http://834945712.iteye.com/blog/1915432 这篇文章很 ...
- load-store/register-memory/register-plus-memory比较
在理解ARM的load-store架构时,我在百度上搜索了很长时间,但是始终找不到一篇像样的中文文章.最后,在用谷歌搜索的英文网站上终于找到了一些蛛丝马迹.让我们先看一下一篇英文资料. Process ...
- Marsonry
前言 1 MagicNumber -> autoresizingMask -> autolayout 以上是纯手写代码所经历的关于页面布局的三个时期 在iphone1-iphone3gs时 ...