perf_support 设计
设计目标
数值内核的基准测试只有在可复现、可比较时才有用:每次运行、每台机器上的输入都相同,测量的是计算而不是准备工作,并且保证被测代码确实运行了。perf_support 为本仓库的基准测试子系统提供这些保证。
数学背景
确定性的输入
输入由每个用例的种子通过 SplitMix64 生成器生成,并映射到目标分布(例如 上的均匀分布)。结构化族由这些抽样按构造得到,例如对称正定矩阵取 ,它对任意 都是 SPD,因为对 有 。相同的种子总是给出相同的比特,因此 fixture 可以重新生成,而无需存储。
校验和
每次运行用 FNV 风格的混合把结果的比特模式折叠成一个 64 位值,
其中 是第 个输出值的 IEEE 比特模式(矩阵先计入形状)。校验和有两个用途:防止编译器把计算当作死代码删除,以及检测不同运行、目标或版本之间结果比特的变化。它不是密码学哈希。
设计决策
运行时加载 fixture,注册表写在代码中
用例列表由 bench/datasets/manifest.json 生成为 MoonBit 代码(generated_registry.mbt),而大型输入数组存放在运行时加载的 JSON 文件中。这使基准二进制保持小巧,代码体积不会扭曲测量结果,也让 Rust 基线可以使用同一批 fixture。
自修复的 fixture
当 fixture 文件缺失时,会根据注册表中的种子重新生成并写出,因此干净的检出也能运行任意用例。当文件存在但其版本、元数据或形状与注册表不一致时,运行会中止:悄悄不匹配的输入会让数字失去意义。
修改策略
有些操作会改变输入(例如 reduce_row_elimination)。因此 mutation_policy = "scratch_per_sample" 的用例在全新副本上运行,使每个样本测量的是相同的工作。
非受检内核
基准测试调用 unchecked_* 方法,因为已知输入满足前置条件,而且要测量的并不是校验的开销。
正确性与不变量
- 对固定的数据集版本,
prepare_case(c)在每次运行中都产生逐位相同的输入。 run_prepared_case_inplace(p, true)不改变p。- 校验和依赖于每个输出值以及输出形状。
被否决的方案
- 把所有输入嵌入代码。 大型字面量数组会使二进制体积和编译时间膨胀。
- 每次运行使用随机输入。 结果将无法在不同运行之间比较。
边界
perf_support 本身不做任何测量;计时和统计位于 perf_runner、perf 和 bench/run.py 中。它只覆盖使用 Double 输入的 @mutable 包,也不属于默认测试关卡。