06. 提高缓存命中率

1.缓存行和局部性原理

2.提高缓存命中率策略


1.缓存行和局部性原理

csharp 复制代码
CPU缓存的最小存储单位是缓存行(Cache Line), 常见大小为64字节; 当CPU从内存读取数据时, 不会只读取目标字节, 而是

会把目标数据所在的整个缓存行(64字节)都加载到缓存中

a.空间局部性: 如果程序接下来要访问的数据和当前数据在内存中是连续的, 那么这些数据已经被加载到缓存里,直接读取即

可(缓存命中)

b.时间局部性: 如果程序在短时间内重复访问同一数据, 该数据会一直留在缓存中, 避免重复从内存读取

这两个局部性原理, 是所有缓存优化策略的基础

2.提高缓存命中率

csharp 复制代码
a.利用空间局部性: 让频繁访问的数据紧凑排列; 核心是"让高频访问的数据在内存中连续存储, 最大化缓存行的利用率"

- 正面例子: 遍历数组

数组是连续内存布局, 遍历数组时, CPU加载一个缓存行就能包含多个数组元素; 比如: 64字节的缓存行, 能装下16个int类

型元素(每个int4 字节); 遍历到第1个元素时, 后续15个元素已经在缓存里了, 命中率接近100%

- 反面例子: 遍历链表

链表的节点是分散内存布局(每个节点的next指针指向随机内存地址), 每次访问下一个节点都要去内存寻址,缓存行只能装一

个节点, 命中率极低

csharp 复制代码
b.利用时间局部性: 让高频数据常驻缓存; 核心是"减少高频数据的缓存驱逐, 让它在缓存里待得更久"

核心手段减少循环内的内存读写, 把循环中需要重复访问的变量, 缓存到局部变量中; 局部变量默认会被分配到CPU的寄存器

或L1缓存中, 访问速度极快

csharp 复制代码
c.避免"伪共享": 别让多线程破坏缓存行

这是多线程编程中容易踩的坑, 也是Unity C#多线程优化的关键

伪共享的本质: 多个线程同时修改同一个缓存行里的不同数据, 会导致缓存行频繁失效(缓存颠簸)

比如两个线程分别修改一个结构体的两个成员, 而这两个成员刚好在同一个缓存行: 线程A修改后, 缓存行标记为脏数据, 线

程B读取时发现缓存行失效, 必须重新从内存加载, 命中率直接归零
csharp 复制代码
现代CPU都是多核的(比如: 4核、8 核), 每个核心都有自己独立的L1、L2缓存, L3缓存是多核共享的; 为了保证所有核心读

取的数据是"一致的"(比如核心 1 修改了某个数据,核心 2 必须看到最新值,不能读旧数据), CPU有一套缓存一致性协议

最常见的是MESI协议, 这个协议有个关键规则: 当某个核心修改了自己缓存中的某个缓存行后, 会立即通知其他所有核心:你

们缓存里的这个缓存行已经失效了, 不能再用了; 其他核心如果后续要访问这个缓存行的数据,必须重新从内存或共享L3缓存

加载最新版本; 这就是伪共享的祸根 ------ 不是数据本身冲突, 而是缓存行被共用, 导致无辜的连带失效
csharp 复制代码
解决方法: 缓存行填充, 通过添加填充字节, 让每个线程操作的数据独占一个缓存行, 避免互相干扰
相关推荐
白猫不黑7 天前
Python实现简易Web弱口令爆破与防护方案
python·web安全·计算机·网络安全·黑客·信息安全·渗透测试
白猫不黑8 天前
网络安全面试题大全:22道高频题附解析与答案
web安全·计算机·网络安全·信息安全·渗透测试·编程·面试题
前端炒粉8 天前
软考知识笔记
计算机
白猫不黑8 天前
网络安全和信息安全的区别:全方位解析与学习路径
计算机·网络安全·黑客·信息安全·程序员·渗透测试·编程
白猫不黑8 天前
零基础如何学习网络安全:从入门到实战的完整路线图
web安全·计算机·网络安全·黑客·信息安全·渗透测试·代码审计
白猫不黑11 天前
CTF是什么?从零理解一场攻防竞赛
网络·web安全·计算机·网络安全·信息安全·ctf·红蓝对抗
XiHongShi201612 天前
键盘大小写指示器(代替键盘灯)
学习·计算机
无忧.芙桃16 天前
嵌入式(一):嵌入式历史与计算机基础:从 ENIAC 到 MCU 四大技术方向
c语言·单片机·嵌入式硬件·计算机
白猫不黑17 天前
大学网安方向学习路线:零基础与有基础的学习顺序整理
学习·web安全·计算机·网络安全·信息安全·编程·src漏洞
白猫不黑20 天前
AI时代如何利用AI学好网络安全
人工智能·安全·web安全·计算机·网络安全·信息安全