降低Cache失效率--编译器优化

简介: PS<<EOF 之前看了酷壳上 @我的上铺叫路遥 投稿的"七个示例科普CPU Cache",其实没认真看完! 丫的,我翻阅了一下《计算机系统结构》的书,把cache那章阅读了下! 发现了新大陆,对自己当时学到的知识的领悟和体会似乎有了新的感受!计算机专业课,其实我都挺认真的学过的,哈哈,只不过...... 我把我觉得有用的摘录下!! 为什么好多那么些开源滴优秀滴代

PS<<EOF

之前看了酷壳 @我的上铺叫路遥 投稿的"七个示例科普CPU Cache",其实没认真看完!

丫的,我翻阅了一下《计算机系统结构》的书,把cache那章阅读了下!

发现了新大陆,对自己当时学到的知识的领悟和体会似乎有了新的感受!计算机专业课,其实我都挺认真的学过的,哈哈,只不过......

我把我觉得有用的摘录下!!

为什么好多那么些开源滴优秀滴代码读不懂咧, 语言不熟练和算法素养很低是一方面, 其实还有好多方面…偶还是太菜了…

EOF


降低Cache失效率的方法

许多相关Cache的研究都致力于降低Cache的失效率。这里就讨论这个!

按照产生失效的原因不同,可以把失效分为以下3类(简称为"3C"):

(1). 强制性失效 (Compulsory miss): 当第一次访问一个块时,该块不在 Cache中, 需从下一级存储中调入 Cache, 这就是强制性失效。这种失效也称为冷启动失效,或首次访问失效。(增加块大小,预取)

(2). 容量失效 (Capacity miss): 如果程序执行时所需的块不能全部调入 Cache 中, 则当某些块被替换后, 若又重新被访问, 就会发生失效。这种失效称为容量失效。(增加容量) 抖动现象。

(3). 冲突失效 (Conflict miss): 在组相联或直接映像 Cache 中, 若太多的块映像到同一组(块)中,则会出现改组中某个块被别的块替换、然后又被重新访问的情况。这就是发生了冲突失效。这种失效也称为碰撞失效 (collision) 或干扰失效 (interference)。(提高相联度)

SPEC92基础测试程序给出了这三种失效在不同容量不同相联度下的失效率情况略。总结的情况如下:

(1) 相联度越高,冲突失效就越少。

(2) 强制性失效和容量失效不受相联度的影响。

(3) 强制性生效不受 Cache 容量的影响,但容量失效却随着容量的增加而减少。

(4) 表中的数据符合 2:1 的 Cache 经验规则,即大小为N的直接映像 Cache 的失效率约等于大小为 N/2 的 2 路组相联 Cache 的失效率


编译器优化

前面所介绍的技术(增加块大小、增加Cache容量、提高相联度、伪相联、硬件预取以及预取指令等)都需要改变或者增加硬件。下面介绍的方法,无需对硬件做任何改动就可以降低失效率。或许,这也是能对我们的程序效率有帮助的地方

我们能很容易地重新组织程序而不影响程序的正确性。例如,把一个程序中的几个过程重新排序,就可能会减少冲突失效,从而降低指令失效率。McFarling研究了如何使用记录信息来判断指令组之间可能发生的冲突,并将指令重新排序以减少失效。他发现,这样可将容量为2KB、块大小为4KB的直接映像指令Cache的失效率降低50%;对于容量为8KB的 Cache,可将失效率降低75%。他还发现当能够是某些指令根本就不进入 Cache 时,可以得到最佳性能。但即使不这么做,优化后的程序在直接映像 Cache 中的失效率也低于未优化程序在同样大小的8路组相联映像 Cache 中的失效率。

数据对存储位置的限制比指令对存储位置的限制还要少,因此更便于调整顺序。我们对数据进行变换的目的是改善数据的空间局部性和时间局部性。例如,可以把对数据的运算改为对存放在同一 Cache 块中的所有数据进行操作,而不是按照程序员原来随意书写的顺序访问数组元素。

1. 数组合并 ( merging arrays )

这种技术通过提高空间局部性来减少失效次数。有些程序同时用相同的索引来访问若干数组中的同一维。这些访问可能会相互干扰,导致冲突失效。我们可以这样来消除这种危险:将这些相互独立的数组合并成为一个复合数组,使得一个 Cache 块中能包含全部所需的元素。

/* 修改 */


/* 修改 */


这个例子有一个有趣的特点:如果程序员能正确地使用记录数组,他就能获得与本优化相同的益处。

2. 内外循环交换 ( loop interchange )

有些程序中含有嵌套循环,程序没有按照数据在存储器中存储的顺序进行访问。在这种情况下,只要简单地交换循环的嵌套关系,就能使程序按数据在存储器中存储的顺序进行访问。和前一个例子一样,这种技术也是通过提高空间局部性来减少失效次数,重新排列访问顺序使得在一个 Cache 块被替换之前,能最大限度地利用块中的数据。

/* 修改 */


/* 修改 */


修改前程序以100个字的跨距访问存储器,而修改后的程序顺序地访问一个 Cache 块中的元素,然后再访问下一块中的元素。这种优化技术在不改变执行的指令条数的前提下,提高了 Cache 的性能。

简单测试:


编译: 

> gcc -Wall a.c -o a

> gcc -Wall b.c -o b

结果: //没看CPU的情况,看起来貌似有效。。。


3. 循环融合 ( loop fusion )

有些程序含有几部分独立的程序段,它们用相同的循环访问同样的数组,对相同的数据做不同的运算。通过将它们融合为单一的循环,能使读入 Cache 的数据在被替换出去之前,得到反复的使用。和前面的两种技术不同,这种优化的目标是通过改进时间局部性来减少失效次数。

/* 修改前 */

/* 修改后 */

修改前的程序在两个地方访问数组a 和 c,一次是在第一个循环里,另一次是在第二个循环里。两次循环分隔较远,可能会产生重复失效,即在第一个循环中访问某个元素失效之后,虽已将相应块调入 Cache,但在第二个循环中再次访问该元素时,还可能产生失效。而在修改后的程序中,第二条语句直接利用了第一条语句访问 Cache 的结果,无需再到存储器去取。


4. 分块

这种优化可能是 Cache 优化技术中最著名的一种,它也是通过改进时间局部性来减少时效。下面仍考虑对多个数组的访问,有些数组是按行访问,而有些规则是按列访问。无论数组是按行优先还是按列优先存储,都不能解决问题,因为在每一次循环中既有按行访问也有按列访问。这种正交的访问意味着前面的变换方法,如内外循环交换,对此军无能为力。

分块算法不是对数组的整行或整列进行访问,而是对子矩阵或块进行操作。其目的仍然是使一个 Cache 块在被替换之前,对它的访问次数达到最多。下面这个矩阵乘法程序有助于我们理解为什么要采用这种优化技术。


还有好多哭



#坚持:有一定的理论素养,却又始终以实践为本!




目录
相关文章
|
存储 NoSQL 算法
从一个crash问题展开,探索gcc编译优化细节
问题分析的过程也正是技术成长之路,本文以一个gcc编译优化引发的crash为切入点,逐步展开对编译器优化细节的探索之路,在分析过程中打开了新世界的大门……
|
机器学习/深度学习 存储 人工智能
谷歌Gemma介绍、微调、量化和推理
谷歌的最新的Gemma模型是第一个使用与Gemini模型相同的研究和技术构建的开源LLM。这个系列的模型目前有两种尺寸,2B和7B,并且提供了聊天的基本版和指令版。
862 2
|
存储 NoSQL Unix
【Core dump】关于core的相关配置:关于核心转储文件core dump的显示和设置位置
【Core dump】关于core的相关配置:关于核心转储文件core dump的显示和设置位置
1203 11
|
机器学习/深度学习 自然语言处理 PyTorch
使用Python实现循环神经网络(RNN)的博客教程
使用Python实现循环神经网络(RNN)的博客教程
1139 1
|
9月前
|
机器学习/深度学习 人工智能 自然语言处理
RoBERTa-Large的IA3微调
本文介绍了在ModelArts平台上使用MindSpore NLP组件对Roberta-Large模型进行IA3微调训练的过程。具体要求包括使用GLUE-MRPC数据集,加载Roberta-Large模型并配置IA3算法进行微调。训练过程中遇到了参数更新问题,通过官方修复后得以解决。最终,模型在验证集上进行了评估,并输出了准确率和F1值。此外,还详细描述了数据集GLUE-MRPC的特征、RoBERTa-Large模型的结构以及IA3微调的具体配置。
285 18
|
传感器 机器学习/深度学习 人工智能
人工智能在自动驾驶中的挑战与机遇
【7月更文挑战第2天】自动驾驶技术融合AI、传感器和机器学习,革新交通,但也遭遇多重挑战:传感器在恶劣天气下性能下降,数据处理需高速决策,法规与伦理待明晰,社会接受度低。机遇在于技术创新提升驾驶安全,多模态交通生态,共享出行及物流革命,以及催生新商业模式。面对挑战,各方需合力推动法规完善和社会信任建设,以实现自动驾驶的潜力。
|
机器学习/深度学习 传感器 人工智能
【探索AI未来】自动驾驶时代下的人工智能技术与挑战
【探索AI未来】自动驾驶时代下的人工智能技术与挑战
841 0
|
IDE Linux 网络安全
使用vscode远程连接服务器或虚拟机进行编码
使用vscode远程连接服务器或虚拟机进行编码
1078 0
|
存储 缓存 监控
10 分钟搞懂缓存设计策略
10 分钟搞懂缓存设计策略
1266 0