feat(hw/sim): distinguish query-only and end-to-end performance cycles in retrieval benchmark

Add explicit separation between query-only cycles (accept→last) and end-to-end cycles
(load + write + noise + queries) in hardware retrieval benchmarks.

- Add query_only_cycles_per_query, load_write_noise_cycles, end_to_end_cycles metrics
- Refactor summarize_query_timings() to use accept_to_last_result_cycles as query-only base
- Add build_hardware_performance() to compute end-to-end performance separately
- Add current_sim_cycle() helper using cocotb get_sim_time
- Update CSV/Markdown outputs and RETRIEVAL_PERF_RESULT log format
- Update documentation to clarify cycle-counting methodology
- Update tests to cover new performance measurement logic
This commit is contained in:
2026-05-28 13:46:09 +08:00
parent 42d4a9728d
commit 97e53d44f8
4 changed files with 195 additions and 56 deletions

View File

@@ -41,6 +41,7 @@ just remote "python scripts/sw_retrieval_benchmark.py --dataset outputs/cam_retr
```bash
just cam-test-retrieval-artifact outputs/cam_retrieval_benchmark/datasets/cifar10_hash512_rows512_queries128.npz 512
just cam-test-retrieval-artifact outputs/cam_retrieval_benchmark/datasets/cifar100_hash512_rows512_queries128.npz 512
```
## 2. 软件检索速度与质量
@@ -133,38 +134,40 @@ benchmark。实现位置
- `hw/sim/tests/top/utils.py::query_topk_once_with_latency`
- `hw/sim/benchmarks/retrieval/test_retrieval_benchmark.py::cam_retrieval_benchmark`
周期口径如下
周期口径如下。本节只报告Cocotb/Verilator仿真周期不将cycle直接换算为ns或queries/s。
| 指标 | 含义 |
|---|---|
| `accept_to_first_result_cycles` | query`query_valid && query_ready` 接受后,到首个 `result_valid` beat 的周期数。 |
| `accept_to_last_result_cycles` | query 被接受后,到 `result_last` 断言的周期数,即完整 Top-K 串行结果输出完成。 |
| `total_query_cycles` | 从拉高 `query_valid` 到 Top-K 输出完成的完整事务周期数。 |
| `cycles_per_query` | 当前报告中的主指标,等于平均 `accept_to_last_result_cycles`。 |
| `queries_per_cycle` | `num_queries / total_query_cycles`,用于观察仿真事务吞吐率。 |
| `query_only_cycles_per_query` | 主指标。每个query`query_valid && query_ready`握手成功的时钟沿,到对应`result_valid && result_ready && result_last`完成的平均周期数。 |
| `query_only_total_cycles` | 所有query-only事务周期之和不包含装载、写入、噪声注入和查询间统计代码。 |
| `query_only_queries_per_cycle` | `num_queries / query_only_total_cycles`。 |
| `load_write_noise_cycles` | 写入CAM行以及可选写噪声注入阶段的周期数。无噪声模式下仍包含CAM行写入周期。 |
| `end_to_end_cycles` | 从开始写入数据集到最后一个query完成的完整benchmark硬件仿真周期数。 |
| `end_to_end_queries_per_cycle` | `num_queries / end_to_end_cycles`。 |
| `accept_to_first_result_cycles` | query被接受后到首个结果beat完成握手的平均周期数。 |
| `accept_to_last_result_cycles` | query被接受后`result_last`结果beat完成握手的平均周期数。 |
| `cycles_per_query``total_query_cycles``queries_per_cycle` | 兼容旧字段当前均为query-only口径不代表end-to-end。 |
选择 `accept_to_last_result_cycles` 作为主 `cycles_per_query` 的原因是Top-K
检索只有在串行结果流输出到 `result_last` 后才算完整完成;仅用首个
`result_valid` 会低估实际 Top-K 检索事务成本。
选择query-only的`accept→last`作为主cycles/query是因为Top-K检索只有在串行结果流输出到`result_last`并被接收后才算完整完成;仅用首个`result_valid`会低估实际Top-K查询事务成本。`load_write_noise_cycles``end_to_end_cycles`单独报告避免把非查询阶段混入query-only性能。
### CIFAR-10 无噪声硬件周期结果
### 无噪声硬件周期结果
配置512 rows × 128 queries × 512-bit hash`TOPK_K=5``LANES=8`
配置512 rows×128 queries×512-bit hash`TOPK_K=5``LANES=8`
`WRITE_NOISE_EN=0`
| 数据集 | 模式 | 查询数 | accept→first | accept→last / cycles/query | total query cycles | queries/cycle | 状态 |
|---|---|---:|---:|---:|---:|---:|---|
| CIFAR-10 | hardware no-noise | 128 | 1027.000000 | 1031.000000 | 132096 | 0.000968992 | pass |
| 数据集 | 模式 | 查询数 | query-only cycles/query | query-only total cycles | query-only queries/cycle | load/write/noise cycles | end-to-end cycles | end-to-end cycles/query | end-to-end queries/cycle | accept→first | accept→last | 状态 |
|---|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---|
| CIFAR-10 | hardware no-noise | 128 | 1031.000000 | 131968 | 0.000969932 | 1024 | 133628 | 1043.968750 | 0.000957883 | 1027.000000 | 1031.000000 | pass |
| CIFAR-100 | hardware no-noise | 128 | 1031.000000 | 131968 | 0.000969932 | 1024 | 133628 | 1043.968750 | 0.000957883 | 1027.000000 | 1031.000000 | pass |
对应日志标记:
```text
RETRIEVAL_PERF_RESULT mode=no_noise num_queries=128 cycles_per_query=1031.000000 accept_to_first_result_cycles=1027.000000 accept_to_last_result_cycles=1031.000000 total_query_cycles=132096 queries_per_cycle=0.000968992 status=pass
RETRIEVAL_PERF_RESULT mode=no_noise num_queries=128 query_only_cycles_per_query=1031.000000 query_only_total_cycles=131968 query_only_queries_per_cycle=0.000969932 load_write_noise_cycles=1024 end_to_end_cycles=133628 end_to_end_cycles_per_query=1043.968750 end_to_end_queries_per_cycle=0.000957883 cycles_per_query=1031.000000 accept_to_first_result_cycles=1027.000000 accept_to_last_result_cycles=1031.000000 total_query_cycles=131968 queries_per_cycle=0.000969932 status=pass
```
该结果说明:在当前 `NUM_ROWS=512, LANES=8, TOPK_K=5` 的硬件仿真配置下,
一次完整 Top-K 检索事务约为 **1031 cycles/query**。首个结果 beat 约在
1027 cycles 后出现,完整 Top-K 输出额外消耗约 4 个周期。
一次完整Top-K查询事务的query-only成本为**1031cycles/query**。首个结果beat约在1027cycles后出现完整Top-K输出额外消耗约4cycles。完整benchmark端到端口径为**1043.968750cycles/query**其中数据写入阶段为1024cycles。
> 注:以上数据来自 Verilator/Cocotb 仿真,不是 FPGA 板上实测。它可用于
> 架构级周期趋势分析,但不能直接等同于板级频率、吞吐或端到端系统延迟。
@@ -180,8 +183,11 @@ RETRIEVAL_PERF_RESULT mode=no_noise num_queries=128 cycles_per_query=1031.000000
| Golden Match@K / `exact_match_rate` | Top-K row index 列表是否与参考模型完全一致。该指标比 Hit@K 更严格。 |
| `ns_per_query` | 软件 Top-K 匹配阶段平均耗时;不含加载和写盘。 |
| `queries_per_second` | 软件 Top-K 匹配阶段吞吐率。 |
| `cycles_per_query` | 硬件仿真中一次完整 Top-K 检索事务的平均周期数,当前采用 accept→last 口径。 |
| `queries_per_cycle` | 硬件仿真中完成 query 数除以query 事务周期数。 |
| `query_only_cycles_per_query` | 硬件仿真中一次完整Top-K查询事务的平均周期数,采用`query_valid && query_ready``result_last`完成握手口径。 |
| `query_only_queries_per_cycle` | 硬件仿真中完成query数除以query-only总事务周期数。 |
| `load_write_noise_cycles` | CAM行装载、写入及可选写噪声注入阶段周期数。 |
| `end_to_end_cycles` | 从开始写入数据到最后一个query完成的完整benchmark硬件仿真周期数。 |
| `end_to_end_queries_per_cycle` | 硬件仿真中完成query数除以end-to-end总周期数。 |
## 7. 当前结论
@@ -191,9 +197,8 @@ RETRIEVAL_PERF_RESULT mode=no_noise num_queries=128 cycles_per_query=1031.000000
2. **当前软件基线速度约为 4.86k queries/s。**
该结果来自 Python integer brute-force Hamming scan数据规模为 512 rows × 128 queries × 512 bits。
3. **硬件检索质量基准现在已经报告 cycles/query**
CIFAR-10 512-row/128-query 无噪声配置下,完整 Top-K 检索为
**1031 cycles/query**,首个结果为 **1027 cycles/query**
3. **硬件检索质量基准现在显式拆分query-only与end-to-end周期**
在CIFAR-10和CIFAR-100的512-row/128-query无噪声配置下完整Top-K查询事务均为**1031cycles/query**,首个结果为**1027cycles/query**;写入阶段为**1024cycles**,端到端为**1043.968750cycles/query**。
4. **写噪声对精确排序影响显著。**
即使 Hit@K 保持较高Golden Match@K 也会快速下降,说明噪声首先破坏精确排序,再进一步破坏类别命中。
@@ -203,11 +208,10 @@ RETRIEVAL_PERF_RESULT mode=no_noise num_queries=128 cycles_per_query=1031.000000
## 8. 后续建议
1. 对 CIFAR-100 也运行同样的硬件周期检测,补齐与软件质量表同尺度的硬件周期表。
2.`docs/exps` 中继续维护:
1. `docs/exps` 中继续维护:
- 软件检索速度表;
- 硬件无噪声一致性表;
- 硬件噪声鲁棒性表;
- 硬件 `cycles/query` 表。
3. 对软件基线补充 NumPy/PyTorch vectorized Hamming scan以区分“朴素 Python baseline”和“优化软件 baseline”。
4. 增加 `NUM_ROWS` sweep例如 512、1024、2048、4096 rows观察软件 brute-force scan 的线性增长趋势。
- 硬件query-only、load/write/noise、end-to-end周期表。
2. 对软件基线补充 NumPy/PyTorch vectorized Hamming scan以区分“朴素 Python baseline”和“优化软件 baseline”。
3. 增加 `NUM_ROWS` sweep例如 512、1024、2048、4096 rows观察软件 brute-force scan 的线性增长趋势。