跳转至

CPU Cache

1 L1、L2、L3 缓存

title: 对于各级Cache的访问时间?
对于各级Cache的访问时间, 在英特尔的处理器上一直都保持着非常稳定, 一级Cache访问是4个指令周期, 二级Cache是12个指令周期, 三级Cache则是26~31个指令周期。 这里所谓的稳定, 是指在不同频率、 不同型号的英特尔处理器上, 处理器访问这三级Cache所花费的指令周期数是相同的。
  • CPU缓存(CPU Cache)的目的是为了提高访问内存(RAM)的效率,这虽然已经涉及到硬件的领域,但它仍然与我们息息相关,了解了它的一些原理,能让我们写出更高效的程序,另外在多线程程序中,一些不可思议的问题也与缓存有关。
  • 现代多核处理器,一个CPU由多个核组成,每个核又可以有多个硬件线程,比如我们说4核8线程,就是指有4个核,每个核2个线程,这在OS看来就像8个并行处理器一样。
  • CPU缓存有多级缓存,比如L1, L2, L3等:
    • L1容量最小,速度最快,每个核都有L1缓存,L1又专门针对指令和数据分成L1d(数据缓存),L1i(指令缓存)。一般处理器只需要3~5个指令周期就能访问到数据。
    • L2容量比L1大,速度比L1慢,每个核都有L2缓存。处理器大约需要十几个处理器周期才能访问到数据。
    • L3容量最大,速度最慢,多个核共享一个L3缓存。处理器需要几十个处理器周期才能访问到数据。在多核处理器内部, 三级Cache由所有的核心所共有。 这样的共享方式, 其实也带来一个问题, 有的处理器可能会极大地占用三级Cache, 导致其他处理器只能占用极小的容量, 从而导致Cache不命中, 性能下降。 因此, 英特尔公司推出了Intel ® CAT技术, 确保有一个公平, 或者说软件可配置的算法来控制每个核心可以用到的Cache大小。
  • 有些CPU可能还有L4缓存,不过不常见;此外还有其他类型的缓存,比如TLB(translation lookaside buffer),用于物理地址和虚拟地址转译,这不是我们关心的缓存。
  • 下图展示了缓存和CPU的关系:

2 缓存行

  • 缓存行 (Cache Line) 是 CPU Cache 中的最小单位,CPU Cache 由若干缓存行组成,一个缓存行的大小通常是 64 字节(这取决于 CPU),并且它有效地引用主内存中的一块地址。
  • CPU从主存中加载数据时,是以一个缓存行(64B)作为单位的,这意味着即使只加载1B数据,也会将内存地址中其后连续63B数据加载到缓存中。

2.1 伪共享问题

  • 引入缓存行,有其优点也有其缺点,缺点之一就是伪共享问题。
title: 什么是伪共享?
当不同线程操作不同变量(A线程修改a变量,B线程修改b变量),且此变量在内存地址上很近(可以存放在同一个缓存行内)时,即使A线程修改了变量a,而不修改变量b,线程B的缓存行也变脏,导致B线程需要重新读取b数据到缓存行中。
title: 怎么避免伪共享问题?
以上例来说明。可以将变量a、b地址距离控制在大于一个缓存行大小(64B)。通常可以才有填充补位字节,或者字节对齐方法。

3 查看cpu信息

$ getconf -a | grep CACHE
LEVEL1_ICACHE_SIZE                 32768
LEVEL1_ICACHE_ASSOC                8
LEVEL1_ICACHE_LINESIZE             64
LEVEL1_DCACHE_SIZE                 32768
LEVEL1_DCACHE_ASSOC                8
LEVEL1_DCACHE_LINESIZE             64
LEVEL2_CACHE_SIZE                  262144
LEVEL2_CACHE_ASSOC                 8
LEVEL2_CACHE_LINESIZE              64
LEVEL3_CACHE_SIZE                  31457280
LEVEL3_CACHE_ASSOC                 20
LEVEL3_CACHE_LINESIZE              64
LEVEL4_CACHE_SIZE                  0
LEVEL4_CACHE_ASSOC                 0
LEVEL4_CACHE_LINESIZE              0

4 参考资料