对于绝大多数程序员来说,优化程序往往是在算法方面。但了解一定的计算机硬件知识后,可以隐式地优化程序。下面以矩阵乘法为例,探讨计算机硬件在程序优化中的作用。

原理

学过计算机组成原理的都知道,CPU访问内存的速度比CPU计算速度慢得多,为了解决速度不匹配的问题,在CPU与内存之间加了高速缓存cache。cache的存在大大提高了CPU访问数据的速度。由于价格等原因,cache都比较小。因此,较好地利用cache可以加速程序运行。

方式一:ijk式

可以说是逻辑最为简单的方法来实现矩阵乘法。
i表示A的行标,j表示B的列标,k是A的列标同时也是B的行标,以实现对应位置的乘法,之后不再赘述。
思想:一行一行地遍历A,一列一列地遍历B,A的一行与B的一列对应数值相乘(A[ i ][ k ]*B[ k ][ j ])最后累加起来就得到了C的对应位置(C[ i ][ j ])上的值。与手动计算矩阵乘法的普通方式一致。(乘法逻辑见下图)。

方式二:jki式

思想:B是一列中单个元素单个元素地访问,A仍然是一行一行地遍历。A一行中的各个元素都与该元素相乘,得到的值放入C的一行里面。注意,此时C中各个位置上的值都是部分积,在遍历过程中需要累加这些部分积。当B的一行的元素都访问完毕后,才能得到最终结果。(乘法逻辑见下图)

方式三:kij式

思想:与方法二相似。A是一行中单个元素单个元素地访问,B是一列一列地遍历。A的这个元素与B一列中的各个元素相乘,得到的值放入C的一列里面。注意,此时C中各个位置上的值都是部分积,在遍历过程中需要累加这些部分积。当A的一列的元素都访问完毕后,才能得到最终结果。(乘法逻辑见下图)。

方式四:转置

思想:将矩阵B转置,得到BT。这时要实现A*BT=C。就是A的一行与BT的一行相乘,可以采用方式一,只不过BT的遍历方式为一列一列地遍历。(乘法逻辑见下图)。

方式五:分块

思想:将大矩阵(N*N)划分成若干小矩阵(B*B,B≪N)。对小矩阵做矩阵乘法得到的结果累加到C的对应位置中。注意,这时得到的也是部分积,当对应小矩阵全部计算累加完毕后,才能得到正确结果。对小矩阵的乘法可以采用以上方法,这里使用的是方式一。(乘法逻辑见下图)。

源代码(C语言)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 512 //矩阵维度
#define b 64  //分块矩阵大小int A[N][N];
int B[N][N];
int C[N][N];void init(){ //初始化矩阵for(int i=0;i<N;i++){for(int j=0;j<N;j++){A[i][j]=rand();B[i][j]=rand();}}
}void Transport(){ //矩阵B转置int temp;for(int i=0;i<N;i++){for(int j=0;j<N;j++){if(i>j){temp = B[i][j];B[i][j] = B[j][i];B[j][i] = temp;}}}
}void IJK(){ //法1 ijk型int sum;int i, j, k;for(i=0; i<N; i++){for(j=0; j<N; j++){sum=0;for(k=0; k<N; k++){sum+=A[i][k] * B[k][j];C[i][j]=sum;}}}
}void JKI(){ //法2 jki型int r;int i, j, k;for(j=0;j<N;j++){for(k=0;k<N;k++){r=B[k][j];for(i=0;i<N;i++){C[i][j]+=A[i][k]*r;}}}
}void KIJ(){ //法3 kij型int r;int i, j, k;for(k=0;k<N;k++){for(i=0;i<N;i++){r=A[i][k];for(j=0;j<N;j++){C[i][j]+= r*B[k][j];}}}
}void T(){ //法4 转置Transport();int sum;int i, j, k;for(i=0;i<N;i++){for(j=0;j<N;j++){sum=0;for(k=0;k<N;k++){sum+=A[i][k]*B[j][k];C[i][j]=sum;}}}
}void Blocked() { //法5 分块矩阵int i, j, k;int i1, j1, k1;for (i = 0; i < N; i+=b)for (j = 0; j < N; j+=b)for (k = 0; k < N; k+=b)for (i1 = i; i1 < i+b; i1++)for (j1 = j; j1 < j+b; j1++)for (k1 = k; k1 < k+b; k1++)C[i1][j1] += A[i1][k1] * B[k1][j1];
}

实验结果

以512*512矩阵为例,探究以上五种方式的性能比较

int main(int argc,char*argv[])
{//ijk式init();clock_t start1, finish1;start1=clock();IJK();finish1=clock();double t1 = (double)(finish1-start1)/CLOCKS_PER_SEC;printf("ijk式:%f s\n",t1);//jki式init();clock_t start2, finish2;start2=clock();JKI();finish2=clock();double t2 = (double)(finish2-start2)/CLOCKS_PER_SEC;printf("jki式:%f s\n",t2);//kij式init();clock_t start3, finish3;start3=clock();KIJ();finish3=clock();double t3 = (double)(finish3-start3)/CLOCKS_PER_SEC;printf("kij式:%f s\n",t3);//转置init();clock_t start4, finish4;start4=clock();T();finish4=clock();double t4 = (double)(finish4-start4)/CLOCKS_PER_SEC;printf("转置:%f s\n",t4);//分块init();clock_t start5, finish5;start5=clock();Blocked();finish5=clock();double t5 = (double)(finish5-start5)/CLOCKS_PER_SEC;printf("分块:%f s\n",t5);return 0;
}

结果:

可以看到虽然得到相同的结果但是时间消耗差距很大。

利用硬件实现矩阵乘法加速相关推荐

  1. 基于PYNQ-Z2开发板实现矩阵乘法加速详细流程

    基于PYNQ-Z2开发板实现矩阵乘法加速 主要内容 1.在Vivado HLS中生成矩阵乘法加速的IP核. 2.在Vivado中完成Block Design. 3.在Jupyter Notebook上 ...

  2. c++的矩阵乘法加速trick

    c++的矩阵乘法加速trick 最近读RNNLM的源代码,发现其实现矩阵乘法时使用了一个trick,这里描述一下这个trick. 首先是正常版的矩阵乘法(其实是矩阵乘向量) void matrixXv ...

  3. BZOJ 1009 GT考试 (AC自动机 + 矩阵乘法加速dp)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1009 题意: 准考证号为\(n\)位数\(X_1X_2....X_n(0<=X_ ...

  4. 利用分块矩阵计算矩阵乘法可以有效利用Cache

    以如下矩阵乘法为例解释分块乘法可以有效利用cache. 设: 如下两个8∗88 *88∗8的矩阵A,BA,BA,B,按4∗44*44∗4进行分块乘法. Cache有12行,每行可以存放4个Int.(目 ...

  5. 利用Python实现矩阵乘法并与numpy的结果比较

    文章目录 1.导入numpy库备用 2.生成两个随机矩阵 3.用`list` 实现矩阵相乘 4.直接采用`numpy`矩阵乘法 5.算法结果比较 6.结论 1.导入numpy库备用 import nu ...

  6. CUDA加速计算矩阵乘法进阶玩法(共享内存)

    CUDA加速计算矩阵乘法&进阶玩法~共享内存 一.基础版矩阵乘法 二.为什么可以利用共享内存加速矩阵乘法 1.CUDA内存读写速度比较 2.申请共享内存 三.改进版矩阵乘法(利用共享内存) 一 ...

  7. P1306-斐波那契公约数【矩阵乘法,数论】

    正题 题目链接: https://www.luogu.org/problemnew/show/P1306 题目大意 求出第x项和第y项斐波那契额数的最大公约数. 解题思路 首先第x项和第y项斐波那契额 ...

  8. SPOJ 1676 矩阵乘法+DP

    题意: 给定N (1 ≤ N ≤ 10)个长度不超过6的单词,求由大写字母组成长度为L的包含至少一个给定单词的字符串有多少种,答案 mod 10007,(1 ≤ L ≤ 10^6). 题解: 这个题最 ...

  9. 数学知识——矩阵乘法

    矩阵乘法 文章目录 矩阵乘法 引入 例题 斐波那契前 n 项和 思路 代码 佳佳的斐波那契 思路 代码 引入 由于线性递推式可以表示成矩阵乘法的形式,也通常用矩阵快速幂来求线性递推数列的某一项. 利用 ...

最新文章

  1. C语言的单链表逆序和指定范围逆序
  2. Debian 下通过Bonding 实现双网卡单IP
  3. Machine Learning On Spark——基础数据结构(一)
  4. 混合云的承诺,收益和产品
  5. 香辣弹簧:自动接线的不同方法
  6. Java Collections list()方法与示例
  7. BZOJ-2535 航空管制 toposort
  8. TypeScript Never 与 Unknown
  9. js版palppy brid代码_从 JS 引擎到 JS 运行时(上)
  10. 在linux上ansi格式转换换utf-8格式会乱码吗?,c++对编码格式ANSI utf8 unicode 进行转换...
  11. 使用Postfix与Dovecot部署邮件系统
  12. linux系统批量杀掉进程命令,[Linux]使用awk批量杀进程的命令
  13. tp5设置session过期时间
  14. redis雪崩、击穿、穿透
  15. 惠普局域网共享打印机设置_打印机usb转网络?打印机共享怎么设置?怎样设置hp打印机共享器操作方法...
  16. 【PS】抠图,魔棒工具、橡皮擦工具
  17. 项目管理学习总结(20)——小团队管理与大团队管理
  18. 我的第一篇随笔-------吹起启程之风
  19. 读书笔记《推荐系统实战》| 好的推荐系统
  20. linux 字幕制作工具,Arctime可视化字幕编辑器–做字幕从未如此简单

热门文章

  1. seo好用的查询收录工具有哪些
  2. linux在线安装gcc
  3. 大数据基础(5) - Raft协议
  4. R语言:常用数据格式及其操作
  5. 监听mysql表内容变化 使用canal,canal 监听同步指定数据库,所有表
  6. 计算机属于文科教育,文科生如何过计算机等级考试
  7. Rundeck 腾讯企业邮箱配置
  8. InetAddress.getByAddress(byte[] arr)源码解析
  9. 删除连续相同字符python_Python 删除连续出现的指定字符的实例
  10. docker 镜像源大全