今天,我们继续深入计算机体系结构中缓存的话题。在上一篇文章探讨了缓存的基本查找方式后,本篇将作为一个小结,对PIPT、VIPT、VIVT这三种主流的缓存查找方式进行一次系统的梳理和对比,为后续讲解缓存的读写、一致性等更复杂的操作打下基础。
缓存的核心作用在于弥合CPU与主存之间的速度鸿沟,而如何高效、正确地根据虚拟地址(VA)或物理地址(PA)找到缓存中的数据行,是设计的关键。不同的查找模式(PIPT, VIPT, VIVT)决定了缓存面临的不同挑战和解决方案。
缓存查找模式核心对比
下表清晰地概括了三种模式在面对“别名问题”(多个虚拟地址映射到同一个物理地址)、“同名问题”(同一个虚拟地址映射到多个物理地址)、以及因缓存结构导致的特殊场景时的表现与处理策略。
| 缓存模式 |
别名问题(多VA对应1PA) |
同名问题 (1VA对应多PA) |
单个way容量超过页面大小 |
变更页表是否需要刷cache |
| PIPT |
不受影响 |
不受影响 |
不受影响 |
不需要 |
| VIPT |
只有在单个way容量超过页面大小时,才会产生;可采用以下办法之一解决:<br> a. 硬件以正确顺序更新所有的备份;<br> b. 对应的VA不能被选择;<br> c. 不被用作共享缓存和超线程场景,且在进程变换时,清空缓存;<br> d. 采用页面着色; |
不受影响 |
会产生别名问题 |
需要 |
| VIVT |
a. 对应va不能被缓存;<br> b. 不被用作共享缓存,且在进程切换时,清空缓存 |
a. 在非超线程时,采用清空缓存解决;<br> b. 在超线程时,采用线程ID做区分; |
不受影响 |
需要 |
总结与展望
从对比中可以看出,PIPT 由于直接使用物理地址进行索引和标记比较,从根本上避免了地址映射不一致带来的“别名”和“同名”问题,也无需在页表变更时刷新缓存,是逻辑上最简洁、最安全的设计,但查找过程需要先完成地址转换(TLB查询),可能增加延迟。
VIPT 是一种折衷方案,它利用虚拟地址进行索引(快),但用物理地址作为标签(保证一致性)。它的主要挑战在于,当缓存的路(Way) 容量超过操作系统内存页面大小时,索引位可能涵盖部分物理地址信息,从而可能引发别名问题,需要额外的硬件或软件机制(如页面着色)来处理。
VIVT 则完全使用虚拟地址,虽然查找速度最快,但严重依赖于进程上下文,在多进程、多线程环境下会引发严重的“别名”和“同名”问题,通常需要操作系统在上下文切换时频繁清空缓存,或增加进程ID(ASID)、线程ID作为标签的一部分来区分,现代高性能CPU的一级数据缓存已很少采用纯VIVT设计。
理解这些查找模式的差异,是深入分析缓存一致性协议、内存屏障以及多核编程中各种微妙问题的基石。掌握了这些计算机基础知识,我们才能在后续面对更复杂的系统行为时,做到知其然也知其所以然。
参考资料
[1] CPU基础知识-缓存(3)-补充, 微信公众号:mp.weixin.qq.com/s/ckXofik-Rp0XfB0lMKX6jQ
版权声明:本文由 云栈社区 整理发布,版权归原作者所有。
|