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 文中用(比 ...
随机推荐
- Java进程CPU使用率高排查
Java进程CPU使用率高排查 生产java应用,CPU使用率一直很高,经常达到100%,通过以下步骤完美解决,分享一下.1.jps 获取Java进程的PID.2.jstack pid >> ...
- Linux系统的启动流程以及做个小小的Linux
内核的作用 进程管理:进程间切换 内存管理:内存空间分割为内核空间和用户空间 IO管理:对底层硬件的使用必须由内来实现,不能由用户空间进程来实现 文件系统管理 ...
- CSS小注意(初级)
前言 自己的前端技术相对后台来说要薄弱了很多,这一阵子在努力的学习中,添加样式这是最简单不过的东西了,但是今天我犯了一个错误,不知道大家是不是有时候也会忽略或者做同样的事情,我觉得很大部分人不会,废话 ...
- yii2源码学习笔记(十四)
Module类是模块和应用类的基类. yiisoft\yii2\base\Module.php <?php /** * @link http://www.yiiframework.com/ * ...
- C语言和C++中动态申请内存
在C语言和C++的动态内存的使用方法是不同的,在C语言中要使用动态内存要包含一个头文件即 #include<malloc.h> 或者是#include<stdlib.h> ...
- sql 判断一个表的数据不在另一个表中
SELECT a.* FROM a LEFT JOIN b ON a.key = b.key WHERE (b.key IS NULL) end as flag from a select id fr ...
- 理解Python的迭代器
首先,廖雪峰老师的教程中解释了迭代器和生成器,这篇文章只是补充和我个人的总结. 什么是迭代 可以直接作用于for循环的对象统称为可迭代对象(Iterable). 可以被next()函数调用并不断返回下 ...
- nutch http file 截断问题
问题: 列表页预计抽取 355+6 但实际只抽取到220条链接. 原因是nutch对http下载的内容的长度进行了限制. 解决方案:这里将这个属性扩大10倍. vim conf/nutch-defal ...
- hdu 4739
一个超级超级水的题,不明白当时比赛的时候没有出来: 思路很简单,dfs暴力一下就行,枚举每个顶点,题目一共才20个点,就是20^4方的时间复杂度,完全可以承受: 代码: #include<cst ...
- 使用ListView时遇到的问题
这周练习ListView时遇到了一个问题,从数据库中查询出的数据绑定到LIstView上,长按某个item进行删除操作,每次点击item取得的id都不对,调了半天终于找到了原因,关键是自己对自定义的B ...