一、DMA与cache一致性问题(内存屏障)
Cache数据与主存数据不一致是指:在采用Cache的系统中,同样一个数据可能既存在于Cache中,也存在于主存中,两者数据相同则具有一致性,数据不相同就叫做不一致性。
解决一致性问题可以采用内存屏障:rmb/wmb/mb
二、提高cache命中率
1.(数据紧凑)数据结构及内存边界cache line对齐
2.(数据紧凑)要将频繁访问的数据集中存放
3.(数据紧凑)顺序访问数据
4.(数据紧凑)静态变量在静态区,尽量少用静态变量引用
5.(数据紧凑)避免同时遍历多个比较大的数据buffer
6.(程序紧凑)使用分支预判likely/unlikely
7.(程序紧凑)循环体内的代码要尽量精简
三、流水线局部性原理与并发
程序的运行存在时间和空间上的局部性,前者是指只要内存中的值被换入缓存,今后一段时间内会被多次引用,后者是指该内存附近的值也被换入缓存。如果在编程中特别注意运用局部性原理,就会获得性能上的回报
比如C语言中应该尽量减少静态变量的引用,这是因为静态变量存储在全局数据段,在一个被反复调用的函数体内,引用该变量需要对缓存多次换入换出,而如果是分配在堆栈上的局部变量,函数每次调用CPU只要从缓存中就能找到它了,因为堆栈的重复利用率高
再比如循环体内的代码要尽量精简,因为代码是放在指令缓存里的,而指令缓存都是一级缓存,只有几K字节大小,如果对某段代码需要多次读取,而这段代码又跨越一个L1缓存大小,那么缓存优势将荡然无存
关于CPU的流水线(pipeline)并发性简单说说,Intel Pentium处理器有两条流水线U和V,每条流水线可各自独立地读写缓存,所以可以在一个时钟周期内同时执行两条指令。但这两条流水线不是对等的,U流水线可以处理所有指令集,V流水线只能处理简单指令
CPU指令通常被分为四类,第一类是常用的简单指令,像mov, nop, push, pop, add, sub, and, or, xor, inc, dec, cmp, lea,可以在任意一条流水线执行,只要相互之间不存在依赖性,完全可以做到指令并发
第二类指令需要同别的流水线配合,像一些进位和移位操作,这类指令如果在U流水线中,那么别的指令可以在V流水线并发运行,如果在V流水线中,那么U流水线是暂停的
第三类指令是一些跳转指令,如cmp,call以及条件分支,它们同第二类相反,当工作在V流水线时才能通U流水线协作,否则只能独占CPU
第四类指令是其它复杂的指令,一般不常用,因为它们都只能独占CPU
如果是汇编级别编程,要达到指令级别并发,必须要注重指令之间的配对。尽量使用第一类指令,避免第四类,还要在顺序上减少上下文依赖
四、流水线优化
1.尽量避免使用跳转语句,使用分支预判likely/unlikely
2.循环体内的代码要尽量精简
3.考虑流水线并发性(并发依赖)
五、VM通过页表转换成PM,MMU、Cache、TLB在转换过程中发挥作用:
(1)PTE和PA都在Cache或者Memory中:
(2)将Cache和Memory拆开描述,PTE和PA是否在Cache中命中:
(3)PTE在Cache或Memory中,但是PA不在Cache或Memory中,只能访问Disk:
(4)查找PTE时,直接在TLB中命中:
(5)查找PTE时,TLB没有命中,后续处理和没有TLB的情况类似:
六、MMU、Cache、TLB,通过页表,将VA转换成PA,完整流程:
参考文献:
MMU、Cache、TLB 的作用
CPU cache 与内存对齐
MMU&Cache
7个示例科普CPU Cache line
|