如何选择合适的DRAM调度策略?Ramulator 2.1 FRFCFS与Row Policy完整对比

发布时间:2026/11/2 1:22:00
如何选择合适的DRAM调度策略?Ramulator 2.1 FRFCFS与Row Policy完整对比

【免费下载链接】ramulator2

Ramulator 2.0 is a modern, modular, extensible, and fast cycle-accurate DRAM simulator. It provides support for agile implementation and evaluation of new memory system designs (e.g., new DRAM standards, emerging RowHammer mitigation techniques). Described in our IEEE CAL 2023 paper: https://arxiv.org/pdf/2308.11030.

项目地址:https://gitcode.com/gh_mirrors/ram/ramulator2
点击查看免费下载

Ramulator 2.1 是一款模块化、可扩展、周期精确(cycle-accurate)的 DRAM 模拟器,用于快速实现与评估新的内存系统设计。在它的内存控制器中,DRAM 调度策略由两个正交部件决定:请求调度器(scheduler)决定"下一个发哪条请求",行策略(row_policy)决定"何时关闭打开的行"。选对两者的组合,直接影响模拟出的延迟、带宽与 RowHit 命中率。本文带你完整对比 FRFCFS、FRFCFS-RowHit 调度器与 Open、ClosedCAP 行策略,帮你在几分钟内为实验做出正确选择。

为什么调度策略会决定 DRAM 性能

DRAM 的访问遵循"先开行(ACT)再读列(RD)"的协议。当连续访问落在同一行时,命中行缓冲(RowHit),延迟最低;若访问另一个行,则必须关行再开行(RowConflict),代价最高。调度器和行策略,本质上就是在"让正确的行保持打开"这件事上做权衡:

现象含义对性能的影响
RowHit访问已在打开的行最低延迟,省 ACT
RowMiss访问未打开的行需 ACT,中等代价
RowConflict打开行后又要访问别的行需 PRE+ACT,代价最高

理解了这个背景,再看两种调度器就顺理成章了。

Ramulator 2.1 的两大请求调度器

调度器接口 i_scheduler.h 只有一个核心方法get_best_request():从待处理队列里挑出"下一条最值得发出的请求"。它优先选时序就绪的请求,就绪相同时按到达顺序(先到先得)打破平局。

FRFCFS:先到先得,优先就绪

最基础的调度器,实现见 frfcfs.cpp,Python 包装为 frfcfs.py。它只做一件事:在队列里扫描一遍,挑出时序已就绪的请求;若多个就绪,则取到达最早的那个。

  • 简单、无额外状态,适合绝大多数基准场景
  • 不做"行"维度的前瞻,可能让一条未就绪的旧请求"占着坑"
  • 是 Ramulator 官方示例的默认选择(见 example_config.py)

FRFCFS-RowHit:为行命中"让路"

在 FRFCFS 基础上增加了行感知,实现见 frfcfs_rowhit.cpp,Python 包装为 frfcfs_row_hit.py。它分两轮扫描:

  1. 第一轮:标记出队列里所有"行命中"请求,并记录每个 bank 最早的命中到达时刻;
  2. 第二轮:执行 FRFCFS,但跳过那些会抢占已有行命中的关行请求(would_preempt_rowhit)。

直觉:当 nRTP < nCCD_L 时,一旦行被打开,继续访问同行比"抢先关行去访问另一行"更划算。FRFCFS-RowHit 就是防止后者打乱前者。

对比项FRFCFSFRFCFS-RowHit
核心逻辑就绪优先 + 到达顺序就绪优先 + 保护行命中
额外状态无每 bank 的命中标志与到达时刻
适用场景通用基准、基线高局部性负载、想最大化 RowHit
复杂度低略高(两轮扫描)

Row Policy:Open 与 ClosedCAP 怎么选

行策略接口 i_row_policy.h 定义了 4 个钩子:pre_schedule()(调度前,可注入关行命令)、try_upgrade_command()(选定时可把命令升级为自动预充电版)、on_issue()(命令发出后)、post_schedule()(本 tick 收尾)。

Open 行策略

最宽松的策略:访问后不主动关行,让行一直开着。实现极简,见 open.cpp 与 open.py(所有钩子均为空操作)。

  • 局部性好的负载 → RowHit 高、延迟低
  • 访问模式跳跃 → 打开行长期占用,可能引发不必要的 RowConflict 与能耗

ClosedCAP 行策略:访问 N 列后自动关行

带"列访问计数上限"的关闭策略,见 closed_cap.cpp 与 closed_cap.py。它给每个 bank 记一个列访问计数器,达到上限cap(默认 4)后主动关行:

  • 优先尝试命令升级:把RD→RDA、WR→WRA(自动预充电,读/写同时关行),这是最省时序的方式;
  • 若标准不支持 AP 命令或时序未就绪,则回退到注入显式PREpb关行;
  • 一旦发出关行命令,该 bank 的计数器立即清零重新计数。
对比项OpenClosedCAP
关行时机从不主动关列访问达到cap后关
关行手段—优先 AP 升级,回退 PREpb
参数无cap(默认 4)
适用场景高局部性、求低延迟跳跃访问、平衡能耗与延迟

调度策略与行策略如何协同

在 generic_ddr_controller.cpp 的tick()中,两者的协作流程清晰可见:

  1. 推进时钟、刷新队列统计、排空已完成读请求;
  2. 刷新管理器与行策略pre_schedule()先行(ClosedCAP 可能在此注入PREpb);
  3. 按active > priority > read/write的优先级,调用调度器挑出最佳候选;
  4. 行策略try_upgrade_command()可能把候选升级为自动预充电命令;
  5. 向 DRAM 发出命令,行策略与插件on_issue()记录;
  6. 请求退休(retire)或升级为 active;
  7. 行策略post_schedule()收尾。

也就是说:调度器选"发谁",行策略在选前、选中后、发出后三个时刻介入,共同决定最终命令序列。改其中任一方,都可能改变 RowHit/Conflict 的统计。

三步上手:在示例中切换调度策略

仓库自带的 examples/example_config.py 是最快的起点。它用SimpleO3前端 + DDR4 + GenericDDR 控制器,默认就是FRFCFS+Open:

ctrl = ramulator.controller.GenericDDR( dram=ddr4, scheduler=ramulator.scheduler.FRFCFS(), # 可换成 FRFCFSRowHit() refresh_manager=ramulator.refresh_manager.AllBank(), row_policy=ramulator.row_policy.Open(), # 可换成 ClosedCAP(cap=4) addr_mapper=ramulator.addr_mapper.RoBaRaCoCh(), )

三步即可对比:

  1. 换调度器:把FRFCFS()改为FRFCFSRowHit();
  2. 换行策略:把Open()改为ClosedCAP(cap=4)(cap可调);
  3. 跑并看指标:执行python3 examples/example_config.py,从sim.stats里读row_hits/row_misses/row_conflicts/avg_read_latency。

小技巧:同一负载分别用 4 种组合(2 调度器 × 2 行策略)各跑一遍,对比row_conflicts与avg_read_latency,往往就能看出哪个组合更贴合你的访问模式。

如何验证你的选择:关键指标与测试

sim.stats中memory_system → controller下有几个最直接的计数器:

指标含义
row_hits/row_misses/row_conflicts三类行访问的总数
avg_read_latency平均读延迟(控制器周期)
read_queue_len_avg/write_queue_len_avg读/写队列平均占用

想从"命令序列"层面确认行为是否符合预期,仓库的controller_scheduling测试套件就是范本,见 test_controller_genericddr.py:

  • test_frfcfs_prefers_ready_request_over_older_blocked_request:验证 FRFCFS 优先发就绪请求;
  • test_frfcfs_rowhit_keeps_same_bank_row_hits_before_conflict_close:验证 FRFCFS-RowHit 在关行前保住同行命中;
  • test_closedcap_upgrades_second_access_to_rda:验证 ClosedCAP 在cap=1时把第二次访问升级为RDA。

运行方式:

PYTHONPATH=python pytest tests/controller_scheduling -q

选型速查清单

  • 追求基线、通用评估→FRFCFS+Open(官方示例默认,最简单)。
  • 高局部性、想压 RowHit 延迟→FRFCFS-RowHit+Open。
  • 访问跳跃、想控制能耗与 RowConflict→FRFCFS-RowHit+ClosedCAP(cap=4),并可按负载调小/调大cap。
  • 想确认行为正确→ 用controller_scheduling套件断言命令序列与gap。

小结

在 Ramulator 2.1 里,DRAM 调度策略 =调度器+行策略的组合。FRFCFS简单稳健,FRFCFS-RowHit在行局部性上更聪明;Open释放行命中之利,ClosedCAP用列计数上限在延迟与能耗间找平衡。读懂 generic_ddr_controller.cpp 的 tick 流程与上述几个计数器,你就能为自己的工作负载挑出最合适的组合,并用controller_scheduling测试快速验证它确实按预期工作。

【免费下载链接】ramulator2

Ramulator 2.0 is a modern, modular, extensible, and fast cycle-accurate DRAM simulator. It provides support for agile implementation and evaluation of new memory system designs (e.g., new DRAM standards, emerging RowHammer mitigation techniques). Described in our IEEE CAL 2023 paper: https://arxiv.org/pdf/2308.11030.

项目地址:https://gitcode.com/gh_mirrors/ram/ramulator2
点击查看免费下载

相关推荐

上一篇:终极指南:Karakeep移动端开发如何利用React Native与Expo打造全平台书签应用
下一篇:SVGR性能监控设置:跟踪转换效率的方法

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考