几种通过降低Cache失效率来提升程序性能的方法

  • 1 将矩阵转置
  • 2 分块处理矩阵乘法
  • 3 将分块和转置结合
  • 4 总结

​ 当程序访问多个数组时,经常会出现有些数组按行访问,有些数组按列访问的情况。以矩阵的乘法为例, C = A × B C=A\times B C=A×B ,经典的计算矩阵乘法的算法如下:

void mult() {for(int i=0;i<N;i++) {for(int j=0;j<N;j++) {double res=0.0;for(int k=0;k<N;k++) {res += (matrix_a[i][k]*matrix_b[k][j]);}matrix_c[i][j] = res;}}
}

​ 可以看出,内部的两个循环 j j j , k k k, 将反复读取矩阵 m a t r i x _ b [ N ] [ N ] matrix\_b[N][N] matrix_b[N][N] 的全部的 N × N N\times N N×N 个元素,以及反复读取矩阵 m a t r i x _ a [ N ] [ N ] matrix\_a[N][N] matrix_a[N][N] 的全部的第 i i i 行的 N N N 个元素,所产生的结果 r e s res res 将存入至结果矩阵 m a t r i x _ c [ N ] [ N ] matrix\_c[N][N] matrix_c[N][N] 的第 i i i 行。

​ 考虑此时 Cache 的失效情况,抛开 Cache 大小无限制或者 Cache 的大小完全能装下这三个数组的最为理想的情况。考虑对三个数组访问时,导致 Cache 失效的情况,最坏的情况是,每次的访问都失效,这是会导致共 2 N 3 + N 2 2N^3 + N^2 2N3+N2 次的失效。为了减少失效,下面有两种方法能显著的减小 Cache 的失效率。


1 将矩阵转置

void mult() {int i,j,k;for(i=0;i<N;i++) {for(j=0;j<N;j++) matrix_c[j][i]=matrix_b[i][j];}for(int i=0;i<N;i++) {for(int j=0;j<N;j++) {double res=0.0;for(int k=0;k<N;k++) {res += (matrix_a[i][k]*matrix_c[j][k]);}matrix_c[i][j] = res;}}
}

毫无疑问的是,转置矩阵也是一个耗时的过程,但在转置处花费的时间和后面计算矩阵的乘积结果所节省的时间达到了很好的折中,下面是测试图:

(矩阵规模是 1025 × 1025 1025\times 1025 1025×1025,生成矩阵的方法是生成随机的 double 类型的浮点数 )

​ 可以看到,转置操作再加上转置后的矩阵乘的开销远远小于直接矩阵乘的开销。

​ 其中最主要的原因就是,转置后的矩阵乘法,最内部的循环 k k k ,都将反复读取矩阵 m a t r i x _ a [ N ] [ N ] matrix\_a[N][N] matrix_a[N][N] 的全部的第 i i i 行的 N N N 个元素,以及矩阵 m a t r i x _ b [ N ] [ N ] matrix\_b[N][N] matrix_b[N][N] 的全部的第 j j j 行的 N N N 个元素,而这样的读取方式,很好地利用了空间局部性,让对于程序员透明的 Cache 发挥了重要的作用。


2 分块处理矩阵乘法

​ 分块是一种经典的利用 Cache 来提升程序性能的技术。分块算法不是对数组的整行或者整列进行访问的,而是把对大数组的访问分解成对子矩阵的访问。

​ 为了保证正在访问的元素能在 Cache 中命中,把原程序内部改为仅仅对大小为 B × B B\times B B×B 的子数组进行计算,其中 B B B 称为分块因子,代码如下:

void multB() {int jj,kk,i,j,k;double r;for(jj=0;jj<N;jj+=B)for(kk=0;kk<N;kk+=B)for(i=0;i<N;i++)    //处理 BxB 大小的子矩阵for(j=jj;j<Min((jj+B),(N));j++){r=0.0;for(k=kk;k<Min((kk+B),(N));k++)r+=(matrix_a[i][k]*matrix_c[k][j]);matrix_c[i][j]+=r;}
}

​ 这时再以开始的条件考虑失效次数,可以初步判断 Cache 的失效率会降低,测试结果如下:


3 将分块和转置结合

代码如下:

void mult_T_and_B() {int jj,kk,i,j,k;double r;for(i=0;i<N;i++) {for(j=0;j<N;j++) matrix_c[j][i]=matrix_b[i][j];}for(jj=0;jj<N;jj+=B)for(kk=0;kk<N;kk+=B)for(i=0;i<N;i++)for(j=jj;j<Min((jj+B),(N));j++){r=0.0;for(k=kk;k<Min((kk+B),(N));k++)r+=(matrix_a[i][k]*matrix_c[j][k]);matrix_c[i][j]+=r;}
}

测试时间如下:


4 总结

程序的平均访存公式如下:
平 均 访 存 时 间 = 命 中 时 间 + 失 效 率 × 失 效 开 销 平均访存时间=命中时间+失效率\times 失效开销 平均访存时间=命中时间+失效率×失效开销

  • 以上讨论的提升程序性能的方法的根本就是在降低失效率

  • 虽然Cache 对程序员而言是透明的,但深入理解 Cache 的基本原理,能在不经意间提高程序的性能。


几种通过降低Cache失效率来提升程序性能的方法相关推荐

  1. 提高计算机桌面性能,win7系统降低桌面画面质感提升电脑性能的操作方法

    很多小伙伴都遇到过对win7系统降低桌面画面质感提升电脑性能进行设置的困惑吧,一些朋友看过网上对win7系统降低桌面画面质感提升电脑性能设置的零散处理方法,并没有完完全全明白win7系统降低桌面画面质 ...

  2. 神经网络模型提升算法性能的方法

    转自:https://machinelearningmastery.com/improve-deep-learning-performance/(英文原文) PS:找了好久,CSDN都分类为转载,但是 ...

  3. 内存地址对齐提升程序性能

    内存地址对齐,是一种在计算机内存中排列数据.访问数据的一种方式,包含了两种相互独立又相互关联的部分:基本数据对齐和结构体数据对齐.当今的计算机在计算机内存中读写数据时都是按字(word)大小块来进行操 ...

  4. 哪些模块可用于python性能分析_提升Python程序性能的方法有哪些?看完你就知道啦!...

    掌握一些技巧,可尽量提高Python程序性能,也可以避免不必要的资源浪费.今天就为大家带来七个可以提升python程序性能的好习惯,赶快来学习吧:. 1.使用局部变量 尽量使用局部变量代替全局变量:便 ...

  5. Win10显卡提升游戏性能的方法

    对于游戏玩家而言,一张好用的显卡是非常重要的,用户还可以对自己的电脑显卡性能进行提升,大大提高游戏体验感.下面小编就给大家分享一下NVIDIA和AMD显卡如何设置为最高性能的方法. AMD显卡驱动22 ...

  6. 降低 cache 失效率的方法

    cache 失效产生原因,可分为以下三类: (1)强制性失效 ​ 当第一次访问一个块时,该块不在cache中,需从下一级存储器中调入cache,这种失效称为强制性失效(Compulsory Miss) ...

  7. Day85.降低Cache失效率的方法 -计算机体系结构

  8. 改写(Paraphrase)是一种有效降低英文论文重复率和字数的方法

    在学术研究领域,写作是不可或缺的一部分.然而,当你提交论文时,你可能会遇到一个常见的问题:你的文章长度超过了要求的字数限制.这时候,你可以通过改写(paraphrasing)来降低文章的字数,同时保持 ...

  9. Win11如何提高游戏性能?Win11提升游戏性能的方法

    ​Win11如何提高游戏性能?随着硬件的发展,游戏的画面水平和玩法复杂度都在提高.要是做好性能优化,将能赋予游戏更大的空间去提升效果和玩法.= 更多重装系统教程尽在小白系统重装官网 方法一: 1.点击 ...

最新文章

  1. G - Mike and gcd problem
  2. linux 连接两个异构网,如何在Linux(或异构)网络上共享计算机?
  3. Windows系统下,Android Studio的安装
  4. 分治法 Strassen算法计算方阵相乘
  5. DPDK Qos之报文处理流水线
  6. JAVA之旅(五)——this,static,关键字,main函数,封装工具类,生成javadoc说明书,静态代码块...
  7. Minecraft InputFix
  8. 1067 Sort with Swap(0, i) (25 分) 好,容易出错
  9. 公告:CSDN下载频道即将全面改版
  10. 学计算机仓库管理一定打字吗,仓库管理员要会电脑吗?需要哪些电脑操作呢?...
  11. 解秘java中native方法如何实现:手把手带你实现java native方法
  12. 给宝贝女儿雅琪写的顺口溜
  13. solution类方法怎么引用_13类地下害虫,你见过多少?怎么防治?10大方法要记牢!...
  14. 【开源毕设】一款精美的家校互动APP分享——爱吖校推 [你关注的,我们才推](持续开源更新2)
  15. 如何从手机上恢复误删的微信聊天记录
  16. 讲座笔记 | 陆铭 城市、区域和国家发展:空间政治经济学的理论和实证研究
  17. Guava:Striped锁
  18. 为什么你宁愿吃生活的苦,也不愿吃学习的苦
  19. 办公室设计公司关于办公室装修全过程解剖
  20. 坎坎坷坷的深度学习之路(一)-环境搭建

热门文章

  1. Nginx+Tomcat集群的安装与配置
  2. 什么是标书?有哪些类型?
  3. matplotlib的配色(随机颜色函数,各种渐变色,彩虹色)
  4. 【java IO流项目】实现多人实时聊天室,需连接同一WiFi
  5. 联想笔记本没有wlan这一选项?
  6. 【原创】MT4中四种交易类型详解
  7. Unity_移动端安卓解压缩Zip
  8. 安卓java百度人脸识别SDK简单使用
  9. ik php分词,ik中英文混合分词器
  10. deepin安装java_Deepin 安装jdk1.8