CPU缓存简述
在计算机系统中,CPU高速缓存(英语:CPU Cache,在本文中简称缓存)是用于减少处理器访问内存所需平均时间的部件。在金字塔式存储体系中它位于自顶向下的第二层,仅次于CPU寄存器。其容量远小于内存,但速度却可以接近处理器的频率。
当处理器发出内存访问请求时,会先查看缓存内是否有请求数据。如果存在(命中),则不经访问内存直接返回该数据;如果不存在(失效),则要先把内存中的相应数据载入缓存,再将其返回处理器。
缓存之所以有效,主要是因为程序运行时对内存的访问呈现局部性(Locality)特征。这种局部性既包括空间局部性(Spatial Locality),也包括时间局部性(Temporal Locality)。有效利用这种局部性,缓存可以达到极高的命中率。
在处理器看来,缓存是一个透明部件。因此,程序员通常无法直接干预对缓存的操作。但是,确实可以根据缓存的特点对程序代码实施特定优化,从而更好地利用缓存。
CPU缓存结构
单核CPU缓存结构
多核CPU缓存结构
CPU缓存访问原理
现今缓存也是分级的,可以有L1,L2,L3,L4级缓存。其中L1缓存分为指令缓存(L1i cache)和数据缓存(L1d cache)
一级缓存的容量基本在4KB到64KB之间,二级缓存的容量则分为128KB、256KB、512KB、1MB、2MB等。
一级缓存容量各产品之间相差不大,而二级缓存容量则是提高CPU性能的关键
单核CPU缓存访问原理
一个指令或者数据,先从L1缓存中获取,如果没有得到则从L2中获取,L2中没有则从L3中获取,如果L3中没有,则去内存中获取
多核CPU缓存访问原理
L1是CPU核心私有的,而L2可能是核心之间共用,也可能是核心私有;L3是核心共用。
CPU缓存访问时间
本图来自极客时间性能高手,点击链接可查看
CPU缓存命中率
CPU缓存整体上命中率超过90%,10%左右需要去内存中读取。L3的缓存命中率可能达到80%。
使用valgrind查看cpu cache命中率
# valgrind --tool=cachegrind ls
==7667== Cachegrind, a cache and branch-prediction profiler
==7667== Copyright (C) 2002-2017, and GNU GPL'd, by Nicholas Nethercote et al.
==7667== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==7667== Command: ls
………………………………
==7667==
==7667== I refs: 673,912
==7667== I1 misses: 1,597
==7667== LLi misses: 1,529
==7667== I1 miss rate: 0.24%
==7667== LLi miss rate: 0.23%
==7667==
==7667== D refs: 265,594 (176,087 rd + 89,507 wr)
==7667== D1 misses: 7,101 ( 5,798 rd + 1,303 wr)
==7667== LLd misses: 4,135 ( 2,965 rd + 1,170 wr)
==7667== D1 miss rate: 2.7% ( 3.3% + 1.5% )
==7667== LLd miss rate: 1.6% ( 1.7% + 1.3% )
==7667==
==7667== LL refs: 8,698 ( 7,395 rd + 1,303 wr)
==7667== LL misses: 5,664 ( 4,494 rd + 1,170 wr)
==7667== LL miss rate: 0.6% ( 0.5% + 1.3% )
使用perf查看cpu缓存命中率
# perf stat -e cache-references,L1-dcache-loads,L1-dcache-load-misses,L1-icache-loads,L1-icache-load-misses ls
274,762 cache-references (68.61%)
5,046,519 L1-dcache-loads (68.35%)
42,711 L1-dcache-load-misses # 0.85% of all L1-dcache hits (93.31%)
1,492,453 L1-icache-loads
19,698 L1-icache-load-misses # 1.32% of all L1-icache hits (69.74%)
CPU缓存查看
lscpu
# lscpu | grep cache
L1d cache: 64K
L1i cache: 64K
L2 cache: 512K
dmodecode
# dmidecode -t processor | grep Cache
L1 Cache Handle: Not Provided
L2 Cache Handle: Not Provided
L3 Cache Handle: Not Provided
# dmidecode -t cache
# dmidecode 3.0
Getting SMBIOS data from sysfs.
SMBIOS 2.8 present.
可以看到同一个机器的CPU的缓存,lscpu显示出了大小,而dmidecode 却显示Not Provided
cat /sys/devices/system/cpu/cpu0/cache/index0/size
# cat /sys/devices/system/cpu/cpu0/cache/index0/size
64K
# cat /sys/devices/system/cpu/cpu0/cache/index1/size
64K
# cat /sys/devices/system/cpu/cpu0/cache/index2/size
512K
index0和index1分别是数据缓存和指令缓存,index2是二级缓存,如果有三级缓存则是index3
CPU缓存一次载入多少内容到缓存?
与coherency_line_size参数有关
# cat /sys/devices/system/cpu/cpu0/cache/index3/coherency_line_size
64