Siamese-MicroPerf 是一个面向编译优化效果预测的性能建模项目。它通过采集程序运行时的 PMU 计数器和 LBR 分支轨迹,构造时序特征,再使用 Siamese 网络预测两个二进制版本之间的相对性能差异。
当前仓库同时包含两部分能力:
- 一个 Linux PMU 采样器
pmu_monitor,负责按固定时间间隔采集硬件事件。 - 一套 Python 训练与推理流水线,负责从采样日志构建张量、训练模型并做性能对比预测。
项目默认面向 LLVM test-suite 及其不同编译/后链接优化变体,例如 O1-g、O3-g、O2-bolt、O2-bolt-opt、O3-bolt、O3-bolt-opt。
给定同一程序的两个版本 v1 和 v2,模型输出一个连续值 Y_hat。这个标签有三种物理定义,取决于数据集构建模式:
- 固定时间机制:
Y = N_v1 / N_v2,表示固定时间窗口内的吞吐量倍率 - 固定工作量机制:
Y = T_v2 / T_v1,表示完成同等工作量时的耗时倍率 - 退役指令总数机制:
Y = Σinst_v1 / Σinst_v2,表示固定时间窗口内退役指令总数之比
三种机制的统一说明见 docs/label-mechanisms.md。
三种模式的物理含义不同,但判定方向一致:
Y_hat > 1.0:模型判断v1更快Y_hat < 1.0:模型判断v2更快- 推理脚本默认用
±5%作为近似持平区间
这个设计适合用于回答类似问题:
- 某个 BOLT 优化版本是否真的比基线更快
- 不同编译选项是否带来了稳定的微架构收益
- 仅从 PMU/LBR 行为能否预测程序版本间的相对速度关系
pmu_monitor 由 C 代码实现,负责周期性采集:
inst_retired.anyL1-icache-load-missesiTLB-loadsiTLB-load-missesbranch-instructionsbranch-misses- LBR 统计特征
lbr_avg_span/lbr_log1p_span
它支持:
- 指定 PID 监控
- 全系统模式
- 自定义采样间隔
-T线程跟踪模式,用于为新线程挂载 LBR 采样-E输出time_enabled/time_running字段
输出会写到 log/pmu_monitor_*.csv,并维护软链接 log/pmu_monitor.csv 指向最新文件。
Python 侧会把原始计数器转换为模型可用的时序特征:
- 5 个 PMU 事件转换为 MPKI
- 1 个 LBR 特征
lbr_log1p_span - 序列统一为时间步
T - 默认做全局 Z-score 标准化
最终每个样本的输入维度为 6 个特征。
模型定义在 python/model_cnn.py、python/model_lstm.py、python/model_transformer.py,并由 python/model_factory.py 统一分发。当前支持三种主干:
- CNN: Siamese 1D-CNN + Attention Pooling
- LSTM: Siamese Bidirectional LSTM + Attention Pooling
- Transformer: Siamese Transformer Encoder + Attention Pooling
三者都由三部分组成:
- 共享权重的 Backbone(CNN / BiLSTM / Transformer Encoder)
- Mask-aware Attention Pooling
- MLP 回归头
(Seq_v1, Seq_v2) -> Shared Encoder -> Pooling -> [V_v1; V_v2; V_v1 - V_v2] -> MLP -> Continuous Scalar
其中各阶段含义为:
Seq_v1/Seq_v2:两个程序版本的 PMU/LBR 时序特征序列Shared Encoder:共享参数的时序编码器,用于把两个版本映射到同一表示空间Pooling:将时间维隐藏状态压缩为定长向量表示V_v1和V_v2[V_v1; V_v2; V_v1 - V_v2]:拼接两个版本的绝对表示和差分表示,显式保留对比信息MLP:把融合后的对比特征映射到回归输出Continuous Scalar:最终预测的连续标量Y_hat,表示v1相对v2的性能倍率
从整体前向流程看,模型遵循下面这条 Siamese 框架链路:
对应的结构图如下:
- 内嵌可交互渲染(浏览器打开):docs/diagrams/forward_sequence.html
- 文档内使用静态 SVG(点击图片可打开可交互视图):
其中各阶段含义为:
-
$S_{v1}$ 和$S_{v2}$ :两个程序版本对应的 PMU/LBR 时序特征序列 -
$f_{\theta}$ :共享参数的时序编码器,用于把两个版本映射到同一表示空间 -
$\mathrm{Pool}(\cdot)$ :时间维聚合算子,将隐藏状态压缩为定长表示$V_{v1}$ 和$V_{v2}$ -
$[V_{v1}; V_{v2}; V_{v1} - V_{v2}]$ :同时保留两个版本的绝对表示与差分表示,以显式编码对比关系 -
$g_{\phi}$ :MLP 回归头,将融合后的对比特征映射为最终预测值 -
$\hat{Y}$ :模型输出的连续标量,表示版本$v1$ 相对版本$v2$ 的性能倍率预测
更具体地说,两个版本的输入序列先经过同一个共享编码器得到隐藏表示,再通过池化得到向量
训练脚本 python/train.py 负责:
- 加载一组或多组版本对张量
- 划分训练集/验证集
- 使用 Huber Loss 训练模型
- 通过
--model/--arch选择 CNN、LSTM 或 Transformer - 可通过
--output-model单独指定最佳模型输出位置 - 自动保存最佳检查点到
checkpoints/best_model.pt
推理脚本 python/infer.py 支持两种模式:
- 基于已有
.pt张量批量推理 - 基于两份原始 CSV 做实时特征提取后单次推理
.
├── Makefile # 编译 pmu_monitor
├── src/ # PMU / LBR / 输出 / 线程跟踪实现
├── test/ # C 侧测试工作负载
├── python/ # 数据集构建、模型、训练、推理、可视化
├── train_set/ # 数据采集脚本、manifest、训练张量、变体数据
├── checkpoints/ # 训练输出模型
├── log/ # PMU、训练、推理日志
├── docs/ # 项目设计说明
└── llvm-test-suite/ # 基准测试来源
- Linux
- 支持
perf_event_open - 支持 LBR(如 Intel Skylake 及以上)
- 建议 x86_64 Linux 主机
- 需要足够权限访问硬件性能计数器
如果 perf_event_paranoid > 1,跨进程采样可能失败。常见处理方式:
echo 1 | sudo tee /proc/sys/kernel/perf_event_paranoid采集脚本通常建议直接使用 sudo 运行。
gccmake- 标准 Linux 开发环境
requirements.txt 当前包含:
numpypandasmatplotlibtorch
训练与推理脚本现在默认使用 --device auto,设备优先级为 directml -> cuda -> cpu。
如果你希望默认命中 DirectML,需要在支持的平台上额外安装 torch-directml:
pip install torch-directml如果当前环境没有 DirectML,脚本会自动回退到 CUDA 或 CPU;也可以显式传入 --device directml、--device cuda 或 --device cpu。
安装方式:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtmake默认会生成可执行文件:
./pmu_monitor
./test_pmu_monitor.sh这个脚本会:
- 编译
pmu_monitor - 编译测试工作负载
test/test_workload - 启动工作负载并监控
- 检查输出 CSV 是否存在、行数是否合理、时间列是否单调递增
如果 train_set/tensors/ 下已经存在构建好的张量,可以直接训练:
python3 python/train.py --model cnn如果你想把最佳模型输出到其他位置,可以显式指定:
python3 python/train.py --model cnn \
--output-model checkpoints/experiments/cnn_best.pt训练输出:
- 最佳模型:
checkpoints/best_model.pt - 日志文件:
log/train_*.log
python3 python/infer.py --checkpoint checkpoints/best_model.pt推理输出会写到控制台和 log/infer_*.log。
默认情况下,推理脚本会根据 checkpoint 中记录的元信息自动识别模型类型;也可以通过 --model / --arch 显式指定。
如果你希望从 PMU 采集开始完整跑通,可以按下面流程执行。
在执行采集脚本前,先进入 llvm-test-suite 的构建目录生成一份 O3 基线版本:
cd llvm-test-suite/build-O3-g
cmake -DCMAKE_C_COMPILER=/usr/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/bin/clang++ \
-C ../cmake/caches/O3-g.cmake \
..
make -j8这一步会在 llvm-test-suite/build-O3-g/ 下完成基准程序的配置与编译,供后续数据采集脚本使用。
项目提供了自动脚本:
cd train_set
sudo ./generate_train_set.sh这个脚本会依次处理:
O1-gO3-gO2-boltO2-bolt-optO3-boltO3-bolt-opt
内部调用的关键脚本包括:
train_set/extract_elf.shtrain_set/collect_dataset_testbench.shtrain_set/bolt_optimize.sh
采集产物主要有两类:
train_set/data/<variant>/...csv:每个程序的 PMU 时序train_set/manifest_<variant>.jsonl:每个程序的元数据和run_count
默认机制是固定时间窗口,标签定义为运行次数之比:
python3 python/build_dataset_fixedtime.py输出目录默认是:
train_set/tensors/fixed_time/
每个版本对会生成:
X_v1.ptX_v2.ptY.ptlen_v1.pt/len_v2.pt(若存在)programs.jsonstats.json
此时标签为:
Y = N_v1 / N_v2Y > 1表示在同一采样时间内v1完成了更多工作,因此v1更快
项目还提供固定工作量视角的数据构建脚本:
python3 python/build_dataset_fixedwork.py输出目录默认是:
train_set/tensors/fixed_work/
这个版本会把有效序列长度也作为重要信息保留下来,更适合表达“完成同等工作量所需时间”的差异。
此时标签为:
Y = T_v2 / T_v1Y > 1表示v2耗时更长、v1更快
也就是说,两种模式的标签定义不同,但 Y > 1 / Y < 1 的快慢方向保持一致。
项目还提供基于退役指令总数比的标签构建脚本:
python3 python/build_dataset_instret.py输出目录默认是:
train_set/tensors/inst_retired/
这个版本保持固定时间窗口的输入对齐方式,但将标签从外部 harness 的运行次数比替换为 PMU 硬件事件 inst_retired.any 的总和之比。
此时标签为:
Y = Σinst_v1 / Σinst_v2Y > 1表示在同一采样时间内v1退役了更多指令,因此v1吞吐量更高Y < 1表示v2吞吐量更高
其物理动机是:在固定的 PMU 采样窗口(默认 30 秒)内,CPU 经历的总时钟周期数近似恒定,因此程序完成的退役指令总数可以被视为“工作吞吐量”的直接硬件度量。
python3 python/train.py --model cnnpython3 python/train.py --model lstmpython3 python/train.py --model transformerpython3 python/train.py --model cnn --tensor-base train_set/tensors/fixed_workpython3 python/train.py --model cnn --tensor-base train_set/tensors/inst_retiredpython3 python/train.py --model cnn --pairs O1-g_vs_O3-gpython3 python/train.py \
--model cnn \
--eval-only \
--checkpoint checkpoints/best_model.pt常用训练参数:
--model/--arch,cnn、lstm或transformer--epochs,默认 150--batch-size,默认 32--lr,默认1e-3--weight-decay,默认1e-4--patience,默认 30--noise-std,默认 0.05
LSTM 常用附加参数:
--lstm-hidden,默认 64--lstm-out,默认 128--num-layers,默认 2(LSTM 层数,与 Transformer 共用参数名)--bidirectional/--no-bidirectional,默认双向
Transformer 常用附加参数:
--d-model,默认 128--nhead,默认 4--num-layers,默认 3--dim-feedforward,默认 256--pos-encoding,learnable或sinusoidal
python3 python/infer.py --checkpoint checkpoints/best_model.ptpython3 python/infer.py \
--checkpoint checkpoints/best_model.pt \
--model transformerpython3 python/infer.py \
--checkpoint checkpoints/best_model.pt \
--tensor-base train_set/tensors/fixed_workpython3 python/infer.py \
--checkpoint checkpoints/best_model.pt \
--tensor-base train_set/tensors/inst_retiredpython3 python/infer.py \
--checkpoint checkpoints/best_model.pt \
--pairs O2-bolt_vs_O2-bolt-optpython3 python/infer.py \
--checkpoint checkpoints/best_model.pt \
--csv-v1 path/to/v1.csv \
--csv-v2 path/to/v2.csv \
--stats train_set/tensors/fixed_time/O2-bolt_vs_O2-bolt-opt/stats.json推理时常用模型参数:
--model auto:从 checkpoint 自动识别模型类型--model cnn--model lstm--model transformer
基本用法:
sudo ./pmu_monitor [PID] [-i interval_ms] [-T] [-E]示例:
sudo ./pmu_monitor
sudo ./pmu_monitor 12345
sudo ./pmu_monitor 12345 -i 200
sudo ./pmu_monitor 12345 -T
sudo ./pmu_monitor 12345 -E说明:
- 不传 PID 时默认做全系统采样
-i控制采样周期,默认1000 ms-T为新线程单独挂载 LBR 事件,只适用于指定 PID 模式-E在 CSV 中额外输出复用修正相关字段
当前代码默认训练和推理以下 3 组版本对:
O1-g_vs_O3-gO2-bolt_vs_O2-bolt-optO3-bolt_vs_O3-bolt-opt
log/pmu_monitor_*.csvtrain_set/data/<variant>/*.csvtrain_set/manifest_<variant>.jsonl
checkpoints/best_model.ptlog/train_*.log
log/infer_*.log
如果你想看更细的设计说明,可以从这些文档继续阅读:
- 该项目强依赖 Linux 性能计数器环境,不能简单移植到无
perf_event_open的平台。 - PMU 采集对系统噪声敏感,训练数据质量很大程度上取决于采集隔离度。
- 固定时间机制、固定工作量机制和退役指令总数机制的标签物理定义不同,但大小方向一致;训练、推理和
--stats必须使用同一机制下生成的产物。 train_set/manifest_*.jsonl中run_count=0的样本会在数据构建阶段被跳过。
如果你只是想快速验证仓库功能,建议直接执行:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
mkdir -p llvm-test-suite/build-O3-g
cd llvm-test-suite/build-O3-g
cmake -DCMAKE_C_COMPILER=/usr/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/bin/clang++ \
-C ../cmake/caches/O3-g.cmake \
..
make -j8
cd ../..
sudo train_set/generate_train_set.sh
python3 python/build_dataset_fixedtime.py
python3 python/train.py --model cnn --tensor-base train_set/tensors/fixed_work
python3 python/infer.py --checkpoint checkpoints/best_model.pt --tensor-base train_set/tensors/fixed_work --model cnn如果 train_set/tensors/fixed_time/ 已经存在,这条路径就可以直接跑通训练与推理。