CUDA中使用shared_memory可以加速运算,在矩阵乘法中是一个体现。

矩阵C = A * B,正常运算时我们运用 C[i,j] = A[i,:] * B[:,j] 可以计算出结果。但是在CPU上完成这个运算我们需要大量的时间,设A[m,n],B[n,k],那么C矩阵为m*k,总体,我们需要做m*n*k次乘法运算,m*(b-1)*k次加法运算,并且是串行执行,总体的复杂度为O(m*n*k) 。

矩阵类:

 class Matrix
{
public:
int cols; // x
int rows; // y
float *data; //数据,一位数组
}

CPU上的程序,一个三层循环

for(int i =;i< C.rows;i++)
{
for(int j =;j< C.cols;j++)
{
float *a = A.data;
float *b = B.data;
for(int k=;k<A.cols;k++)
C.data[i*C.cols+j]+=a[i*A.cols+k] * b[k*B.cols+j];
}
}
}

我们想到用GPU加速,在CUDA上实现,我们这么写kernel:

__global__ void matrixMulKernel(const Matrix A, const Matrix B, Matrix C)
{
// Each thread computes one element of C
// by accumulating results into Cvalue
float Cvalue = ;
int row = blockIdx.y * blockDim.y + threadIdx.y;
int col = blockIdx.x * blockDim.x + threadIdx.x;
for (int e = ; e < A.cols; ++e)
Cvalue += A.data[row * A.cols + e]* B.data[e * B.cols + col];
C.data[row * C.cols + col] = Cvalue;
}

此时,计算过程是并行的,但是访问A,B矩阵时,不能同时访问,因此主要的时间花在内存读取,每个线程读取A的一行,B的一列,计算C的对应值;所以这样需要从global memory中读n次A,m次B。时间复杂度是O(m+n)次内存访问,以及k次乘法运算。

实际上还有一种办法,可以用shared memory,这里我们把A,B矩阵按照blocksize划分为子矩阵subA[blocksize][blocksize]、subB[blocksize][blocksize]。并将子矩阵设置为__shared__。 thread block内所有threads共用(可读可写)shared memory。如此一来,A只从global memory读了n/block_size次,B只读了m/block_size次;时间复杂度是O(m/block_size+n/block_size)次内存访问,以及k次乘法运算。进一步减少的时间复杂度。代码如下:

__global__ void matrixMulKernel(const float *A, const float *B, float *C,int Aw ,int Bw)
{
const int bs = CUDA_LG::block_size;
int tx = threadIdx.x;
int ty = threadIdx.y;
int bx = blockIdx.x;
int by = blockIdx.y; int aBlockFisrt = by * bs * Aw ;
int aBlockStep = bs ;
int aBlockLast = by * bs * Aw + Aw - ;
int bBlockFisrt = bx * bs ;
int bBlockStep = bs * Bw ; float subC=; for(int a = aBlockFisrt,int b = bBlockFisrt; a <= aBlockLast ;a+=aBlockStep,b+=bBlockStep )
{
//定义两个shared memory的子矩阵
__shared__ float subA[bs][bs];
__shared__ float subB[bs][bs]; subA[ty][tx] = A[a + ty * Aw + tx];
subB[ty][tx] = B[b + ty * Bw + tx]; __syncthreads(); for(int i = ;i<bs;i++)
{
subC += subA[ty][i] * subB[i][tx];
} __syncthreads();
}
C[ by*bs*Bw + bx*bs + ty * Bw +tx] = subC; }

参考sample_6.5\0_Simple\matrixMul程序。里面注释详细

参考Rachel zhang的博客CUDA学习系列之二:http://blog.csdn.net/abcjennifer/article/details/42528569

CUDA学习之二:shared_memory使用,矩阵相乘的更多相关文章

  1. MPI学习笔记(二):矩阵相乘的两种实现方法

    mpi矩阵乘法(C=αAB+βC) 最近领导让把之前安装的软件lapack.blas里的dgemm运算提取出来独立作为一套程序,然后把这段程序改为并行的,并测试一下进程规模扩展到128时的并行效率.  ...

  2. pgloader 学习(二)特性矩阵&&命令行

    pgloader 对于各种数据库支持的还是很完整的,同时有一套自己的dsl 特性矩阵 操作命令 命令格式 pgloader [<options>] [<command-file> ...

  3. CUDA学习(二)之使用clock()函数

    clock()函数是C/C++中的计时函数,相关的数据类型是clock_t,使用clock函数可以计算运行某一段程序所需的时间,如下所示程序计算从10000000逐渐减一直到0所需的时间. #incl ...

  4. CUDA学习之一:二维矩阵加法

    今天忙活了3个小时,竟然被一个苦恼的CUDA小例程给困住了,本来是参照Rachal zhang大神的CUDA学习笔记来一个模仿,结果却自己给自己糊里糊涂,最后还是弄明白了一些. RZ大神对CUDA关于 ...

  5. CUDA学习笔记(二)【转】

    来源:http://luofl1992.is-programmer.com/posts/38847.html 编程语言的特点是要实践,实践多了才有经验.很多东西书本上讲得不慎清楚,不妨自己用代码实现一 ...

  6. CUDA编程-(2)其实写个矩阵相乘并不是那么难

    程序代码及图解析: #include <iostream> #include "book.h" __global__ void add( int a, int b, i ...

  7. dp方法论——由矩阵相乘问题学习dp解题思路

    前篇戳:dp入门——由分杆问题认识动态规划 导语 刷过一些算法题,就会十分珍惜“方法论”这种东西.Leetcode上只有题目.讨论和答案,没有方法论.往往答案看起来十分切中要害,但是从看题目到得到思路 ...

  8. 利用Hadoop实现超大矩阵相乘之我见(二)

    前文 在<利用Hadoop实现超大矩阵相乘之我见(一)>中我们所介绍的方法有着“计算过程中文件占用存储空间大”这个缺陷,本文中我们着重解决这个问题. 矩阵相乘计算思想 传统的矩阵相乘方法为 ...

  9. java学习-zxing生成二维码矩阵的简单例子

    这个例子需要使用google的开源项目zxing的核心jar包 core-3.2.0.jar 可以百度搜索下载jar文件,也可使用maven添加依赖 <dependency> <gr ...

随机推荐

  1. PL SQL安装

    首先,在官网下载PL SQL 的对应版本,本机是64位的就下载64位的,网址:https://www.allroundautomations.com/downloads.html#PLS 点击应用程序 ...

  2. Spring----组合注解与元注解

    1.概述 1.1.Spring提供了大量的注解, 尤其是相同的注解用到各个类中,会相当的啰嗦: 1.2.元注解: 可以注解到别的注解上的注解: 组合注解: 被注解注解的注解称为 组合注解: 组合注解  ...

  3. python 爬取<a>标签内href的方法及遇到的问题

    原博客地址: https://www.cnblogs.com/dengyg200891/p/6060010.html # -*- coding:utf-8 -*- #python 2.7 #XiaoD ...

  4. [原创] Delphi InputBox、InputQuery函数

    Delphi InputBox.InputQuery函数 两个函数都是弹框提示输入信息 function InputQuery(const ACaption, APrompt: string; var ...

  5. 设置element表格透明样式

    1.element table 表格 修改背景为透明并去除边框 .el-table{ /* 表格字体颜色 */ color:white; /* 表格边框颜色 */ /* border: 0.5px s ...

  6. SPOJ - FTOUR2 (点分治+树状数组)

    题目:https://vjudge.net/contest/307753#problem/I 题意:有一颗树,上面有白色黑色点,每个点上有一个权值,权值可以为负,现在我要求一条路径,权值和最大,这条路 ...

  7. (转)Docker入门——Dockerfile详解

    转:https://www.cnblogs.com/sorex/p/6481407.html 基本示例 FROM MAINTAINER LABEL RUN ADD COPY CMD ENTRYPOIN ...

  8. 2016亚洲城市GDP50强出炉

    2017年年1月,中国各省GDP排名,台湾排第6:广东,江苏,山东,浙江,河南,台湾,四川,湖北,河北,湖南,我国台湾地区去年的GDP增长率为1.4%,总量折合人民币约为37329.1亿元,加入全国榜 ...

  9. 控件识别工具Inspect.exe下载

    一.Inspect.exe 控件识别工具.官网上说通过下载安装Windows SDK后,可以在目录C:\Program Files (x86)\Microsoft SDKs\Windows Kits\ ...

  10. Java + selenium 元素定位(3)之By TagName

    本篇介绍findElement接口中的By TagName方法.首先,要知道什么是tagname.之前我们使用F12开发者工具查看网页元素是,发现每行代码前都有<input>.<bo ...