ChampSim 虚拟内存模型深度解析:5 级页表模拟与 minor fault 惩罚机制
【免费下载链接】ChampSimChampSim is an open-source trace based simulator maintained at Texas A&M University and through the support of the computer architecture community.项目地址: https://gitcode.com/gh_mirrors/ch/ChampSim
ChampSim 是一款由德州农工大学(Texas A&M University)维护的开源基于 trace 的微架构模拟器,在计算机体系结构研究社区中被广泛使用。它的虚拟内存模型(Virtual Memory Model)通过软件方式完整模拟了硬件页表遍历(Page Table Walk)的过程,包括默认 5 级页表、页表缓存 PSCL、TLB 缺失处理,以及最容易被新手忽略的 minor fault(小页错误)惩罚机制。本文将为你拆解 ChampSim 虚拟内存模型的核心设计,帮助你理解模拟结果中那些看似"凭空多出"的延迟到底来自哪里。
什么是 ChampSim 的虚拟内存模型
在真实 CPU 中,每个内存访问都要经历"虚拟地址 → 物理地址"的转换。ChampSim 把这条转换链路搬进了模拟器:从虚拟页到物理页的映射、页表页的分配、页表遍历的每一级访存,都被建模为可计时的流水线步骤。相关实现集中在两个核心模块:
inc/vmem.h/src/vmem.cc:虚拟内存类VirtualMemory,负责地址翻译与页表页分配inc/ptw.h/src/ptw.cc:页表遍历器PageTableWalker(PTW),负责逐级查找页表
理解这套模型,是读懂 ChampSim 输出的访存延迟、以及研究 TLB 预取、页表缓存优化的前提。
5 级页表是如何搭建的
ChampSim 的页表层级数、页表页大小都可以配置。默认配置在config/parse.py中定义:
| 参数 | 默认值 | 含义 |
|---|---|---|
pte_page_size | 4kB | 单张页表页大小 |
num_levels | 5 | 页表层级数 |
minor_fault_penalty | 200 | 小页错误惩罚(周期) |
randomization | 1 | 物理页随机分配种子 |
每一级页表页大小为 4kB,而每条页表项(PTE)是 8 字节(pte_entry),因此每张页表页可存放 512 条 PTE,恰好需要 9 位地址索引。5 级页表加上 4kB(12 位)页内偏移,虚拟地址空间总大小为 2^(12 + 9×5) = 2^57,即 128 PiB。VirtualMemory构造函数会在初始化时检查虚拟空间是否超出物理内存大小,并打印警告。
😯 顺便一提:ChampSim 允许你修改num_levels来模拟 4 级或 3 级页表(如 32 位系统场景),灵活性很高。
页表遍历:从 CR3 出发的 5 步寻址
当 TLB 缺失时,PTW 会从根页表基址(CR3_addr)出发,逐级向下查找。整个过程在PageTableWalker::step_translation中实现,每一级都向内存系统发出一次TRANSLATION类型的读请求:
- 用虚拟地址第 5 级索引找到页目录指针表地址
- 读出下一级页表的基址,继续用第 4 级索引寻址
- 逐级下降,直到第 1 级索引定位到具体的 PTE
- 最终调用
va_to_pa完成虚拟页到物理页的映射
在测试用例test/cpp/src/600-ptw-path.cc中可以看到,一个 5 级页表配置的完整遍历会恰好产生 5 次下层内存请求,与真实硬件的页表遍历行为一一对应。
PSCL:模拟器中的页表缓存
真实 CPU 会用多级页表缓存(PSCL)加速遍历,ChampSim 同样实现了这一点。默认的 PSCL 配置在inc/defaults.hpp中:
- 第 5 级:1 组 2 路
- 第 4 级:1 组 4 路
- 第 3 级:2 组 4 路
- 第 2 级:4 组 8 路
PSCL 命中后可以跳过对应层级的访存。测试 600c 清晰地展示了这一效果:同一地址第二次访问时,下层请求从 5 次降到 2 次;地址越"远",需要重新遍历的层级越多。这也是为什么研究页表预取时,PSCL 配置直接影响模拟结果的准确性。
minor fault 惩罚机制:隐藏在映射背后的延迟
这是 ChampSim 虚拟内存模型中最容易被忽视、却对性能数据影响巨大的机制。所谓 minor fault(小页错误),指目标物理页尚未被分配的页错误——不需要磁盘 I/O,只需在内存中分配一个物理页。
在src/vmem.cc中,有两处会触发 minor fault:
va_to_pa:首次访问某个虚拟页,需要从空闲物理页列表中分配物理页get_pte_pa:某级页表页尚未创建,需要分配一页存放页表项
每次触发 minor fault,都会把minor_fault_penalty(默认 200 个周期)加到翻译延迟上。在src/ptw.cc的finish_packet中,这个惩罚与页表遍历命中延迟(HIT_LATENCY)叠加,最终体现在访问的返回时间上。
这意味着:模拟器的 warmup 阶段结束后的头几次访问,往往带着一次或多次 200 周期的 minor fault 惩罚,因为所有页表页和物理页映射都是"按需"建立的。如果统计周期时没有排除这些冷启动效应,你会观察到明显偏高的延迟峰值。
如何配置与验证虚拟内存参数
修改虚拟内存配置很简单,在champsim_config.json或你自己的配置文件中,为内核的 PTW 模块设置参数即可。核心参数包括:
page_table_levels:页表层级数minor_fault_penalty:小页错误惩罚周期数page_table_page_size:页表页大小
另外,randomization种子控制物理页的随机分配,开启后可以让物理页分布更接近真实系统的随机分配行为,避免因连续分配造成的失真。
验证配置是否生效,可以直接运行项目自带的测试,例如test/cpp/src/602-walk-latency.cc会验证不同层级命中时叠加的延迟是否符合预期。对于想深入源码的读者,推荐从src/vmem.cc的va_to_pa和get_pte_pa两个函数入手,它们是整个虚拟内存模型的入口。
总结
ChampSim 的虚拟内存模型用不到一千行代码,就完整复现了从虚拟地址翻译到物理地址的整条链路:5 级页表结构、逐级页表遍历、PSCL 缓存加速,以及按需分配物理页的 minor fault 惩罚机制。理解这套模型,你不仅能更准确地解读模拟数据,还能在页表预取、TLB 设计等研究方向上有更扎实的基础。下次看到模拟结果里"神秘"的 200 周期延迟,别忘了——那可能就是一次 minor fault 的代价。
【免费下载链接】ChampSimChampSim is an open-source trace based simulator maintained at Texas A&M University and through the support of the computer architecture community.项目地址: https://gitcode.com/gh_mirrors/ch/ChampSim
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考