读书人

从Java角度理解CPU缓存(CPU Cache)

发布时间: 2012-09-09 09:27:54 作者: rapoo

从Java视角理解CPU缓存(CPU Cache)
从Java视角理解系统结构连载, 关注我的微博(链接)了解最新动态

众所周知, CPU是计算机的大脑, 它负责执行程序的指令; 内存负责存数据, 包括程序自身数据. 同样大家都知道, 内存比CPU慢很多. 其实在30年前, CPU的频率和内存总线的频率在同一个级别, 访问内存只比访问CPU寄存器慢一点儿. 由于内存的发展都到技术及成本的限制, 现在获取内存中的一条数据大概需要200多个CPU周期(CPU cycles), 而CPU寄存器一般情况下1个CPU周期就够了.

CPU缓存
网页浏览器为了加快速度,会在本机存缓存以前浏览过的数据; 传统数据库或NoSQL数据库为了加速查询, 常在内存设置一个缓存, 减少对磁盘(慢)的IO. 同样内存与CPU的速度相差太远, 于是CPU设计者们就给CPU加上了缓存(CPU Cache). 如果你需要对同一批数据操作很多次, 那么把数据放至离CPU更近的缓存, 会给程序带来很大的速度提升. 例如, 做一个循环计数, 把计数变量放到缓存里,就不用每次循环都往内存存取数据了. 下面是CPU Cache的简单示意图.

随着多核的发展, CPU Cache分成了三个级别: L1, L2, L3. 级别越小越接近CPU, 所以速度也更快, 同时也代表着容量越小. L1是最接近CPU的, 它容量最小, 例如32K, 速度最快,每个核上都有一个L1 Cache(准确地说每个核上有两个L1 Cache, 一个存数据 L1d Cache, 一个存指令 L1i Cache). L2 Cache 更大一些,例如256K, 速度要慢一些, 一般情况下每个核上都有一个独立的L2 Cache; L3 Cache是三级缓存中最大的一级,例如12MB,同时也是最慢的一级, 在同一个CPU插槽之间的核共享一个L3 Cache.


32位机器中的java的数组对象头共占16字节(详情见 链接), 加上62个long型一行long数据一共占512字节. 所以这个二维数据是顺序排列的.


编译后运行,结果如下
$ perf stat -e L1-dcache-load-misses java L1CacheMiss starting....duration = 21095062165 Performance counter stats for 'java L1CacheMiss':     1,421,402,322 L1-dcache-load-misses                                             32.894789436 seconds time elapsed

这回产生了1,421,402,322次 L1-dcache-load-misses, 所以慢多了.

以上我只是示例了在L1 Cache满了之后才会发生的cache miss. 其实cache miss的原因有下面三种:
1. 第一次访问数据, 在cache中根本不存在这条数据, 所以cache miss, 可以通过prefetch解决.
2. cache冲突, 需要通过补齐来解决.
3. 就是我示例的这种, cache满, 一般情况下我们需要减少操作的数据大小, 尽量按数据的物理顺序访问数据.
具体的信息可以参考这篇论文.

下一篇将介绍CPU cache的另一种误区: 伪共享(False Sharing).
1 楼 wang_scu 2012-04-15 非常好的文章 顶 多写些关于jvm与系统交互的一些东西 不错 很受用 2 楼 pingyuyue 2012-05-29 "就像数据库cache一样, 获取数据时首先会在最快的cache中找数据, 如果没有命中(Cache miss) 则往下一级找, 直到三层Cache都找不到,那只要向内存要数据了. 一次次地未命中,代表取数据消耗的时间越长. "

求这句话的出处或者依据,感觉如果这样设计的话,效率非常低

《深入理解计算机系统》存储器的层次结构中写道:当程序需要K+1层中的某个数据对象d时,它首先会在第k层的一个块中查找d。。。。





3 楼 coderplay 2012-05-30 pingyuyue 写道"就像数据库cache一样, 获取数据时首先会在最快的cache中找数据, 如果没有命中(Cache miss) 则往下一级找, 直到三层Cache都找不到,那只要向内存要数据了. 一次次地未命中,代表取数据消耗的时间越长. "

求这句话的出处或者依据,感觉如果这样设计的话,效率非常低

《深入理解计算机系统》存储器的层次结构中写道:当程序需要K+1层中的某个数据对象d时,它首先会在第k层的一个块中查找d。。。。


出处就是我这儿~ 4 楼 pingyuyue 2012-05-30 coderplay 写道pingyuyue 写道"就像数据库cache一样, 获取数据时首先会在最快的cache中找数据, 如果没有命中(Cache miss) 则往下一级找, 直到三层Cache都找不到,那只要向内存要数据了. 一次次地未命中,代表取数据消耗的时间越长. "

求这句话的出处或者依据,感觉如果这样设计的话,效率非常低

《深入理解计算机系统》存储器的层次结构中写道:当程序需要K+1层中的某个数据对象d时,它首先会在第k层的一个块中查找d。。。。


出处就是我这儿~


假如有个数据不在cache中,有3层缓存的话,就意味着要失效3次才能找到数据;

其实数据不在cache中的情况是非常普遍的,所以我感觉不是这样的,不会直接先从最快的,然后一层一层的往下找 5 楼 coderplay 2012-05-30 pingyuyue 写道coderplay 写道pingyuyue 写道"就像数据库cache一样, 获取数据时首先会在最快的cache中找数据, 如果没有命中(Cache miss) 则往下一级找, 直到三层Cache都找不到,那只要向内存要数据了. 一次次地未命中,代表取数据消耗的时间越长. "

求这句话的出处或者依据,感觉如果这样设计的话,效率非常低

《深入理解计算机系统》存储器的层次结构中写道:当程序需要K+1层中的某个数据对象d时,它首先会在第k层的一个块中查找d。。。。


出处就是我这儿~


假如有个数据不在cache中,有3层缓存的话,就意味着要失效3次才能找到数据;

其实数据不在cache中的情况是非常普遍的,所以我感觉不是这样的,不会直接先从最快的,然后一层一层的往下找

感觉是没有用的, 你可以做个测试. 不断地变大线程要操作的数据集, 然后看Cache miss

读书人网 >编程

热点推荐