本文目的:读《What every programmer should know about memory》一文,结合之前的经验理解,进行一下小结
参考网址:http://lwn.net/Articles/255364/
- 前言
首先该文是针对x86架构来讲的,因此很多地方仅参考一下即可。 - 存储器访问优化的主题
①提升局部性(时间、空间)②对齐code和data
主要方法:
a. 让数据顺序被访问(比如矩阵乘,先对被乘矩阵做转置T)√
b. 充分让cacheline读取的数据一次性都进行处理(比如矩阵乘划分到8x8的tile方法)√
c. 注意结构体的packed,尽量压缩在一个cacheline上
结构体还有需要注意的地方:常用的变量尽量放在起始位置、尽量按顺序访问结构体变量
结构体对齐2种方法:memalign和__attribute((aligned(64))),前者在.heap,后者可在.data、.bss或.stack中√
d. 防止存储区间位置都存储在cache相联的相同位置 - L1 指令Cache优化
a. 尽量降低代码总量,要和循环unroll以及inline达到平衡
-Os选项在编译器不能很好的unroll和inline时有不错的效果
对于多次调用的函数,如果距离很近,没有必要inline,因为首先增大代码尺寸导致cache miss,其次分支预测(跳转)对已经见过的代码有很好的支持;但如果函数只调用一次,可以inline(可以用always_inline属性)
b. 代码执行尽量线性,不要等待什么资源
c. 代码的align
需要align:函数开始位置、jump跳转开始位置(、loop开始位置(有可能会造成过多的nop和jump损耗))
语法:汇编里可以用 .align ,
d. 如果if() { statement }语句中的条件经常为false,则其statement内容最好单独封装为一个函数,并且不要inline
可以使用2个宏来调节if()中条件出现的可能性,并配合-freorder-blocks选项
“#define unlikely(expr) __builtin_expect(!!(expr), 0)”
“#define likely(expr) __builtin_expect(!!(expr), 1)” - L2 Cache及更大的Cache优化
尽量让程序全部在cache中 - TLB优化
减少pages的使用,并降低page的级数 - 关于预取
分为硬件预取以及软件预取,其中硬件预取不能跨page - 总结
最近忘性太大了,都是以前看过的东西,权当复习一遍了。。。