MFU Metric and Metric-History Gate#

This page documents the performance-accounting and CI regression-gate tooling ported from miles (source miles@ba28991834).

FLOPs model and the V5 oracle#

vime/utils/flops_model.py computes analytical forward and training FLOPs of a decoder-only model from its Hugging Face config. It covers dense GQA, MoE, MLA, Gated DeltaNet / KDA linear attention, DSA/QSA sparse-attention indexers, DeepSeek-V4 compressed attention, and Nemotron-H Mamba2 hybrid blocks. MTP layers are intentionally not counted (parity with miles); adding a vime-only MTP term is a documented follow-up.

The vendored oracle tests/ci/flops_oracle/flops_utils_miles_ba28991834.py pins miles’ implementation as ground truth. The verifier compares any implementation against it over 8 architecture configs and fails on a relative error of 1e-6 or more:

python tests/ci/flops_oracle/verify_flops.py --impl vime/utils/flops_model.py

Exit code 0 means pass (or SKIP while the implementation file does not exist yet); exit code 1 means mismatch.

MFU metric#

log_perf_data logs perf/actor_train_mfu (plus perf/mfu_peak_tflops and perf/actor_train_tflops_hf) per rollout, alongside the slime-origin perf/actor_train_tflops, which is unchanged. The MFU numerator comes from the HF-config FLOPs model (model_flops_from_hf_config on args.hf_checkpoint, cached per checkpoint); the denominator is --mfu-peak-tflops when set, else the built-in device table in vime/utils/device_flops.py (NVIDIA A100/H100/ H200/GH200/B200/B300/GB200/GB300 and AMD MI300X/MI325X/MI355X). When neither is available for the local device, no perf/mfu* keys are logged.

Metric-history store#

tests/ci/metric_history/storage/ defines the metric-history contract (MetricHistoryStore, RunIdentity, RunProvenance) and a SQLite backend. A run’s baseline is scoped by (test_path, backend, suite); the comparison coordinate is (metric_key, step); trust is a run-level flag revocable via mark_untrusted (by run_id, ci_run_id, or commit_sha). Provenance columns use CI-neutral names (ci_run_id = Buildkite build number, ci_run_attempt = retry count, pipeline = pipeline slug).

Metric-history gate (capture + evaluation)#

When the CI harness sets VIME_CI_GATE_RECORD_DIR, every logging_utils.log() call captures the whitelisted metrics (train/grad_norm, train/ppo_kl, train/train_rollout_logprob_abs_diff, train/train_rollout_kl, rollout/raw_reward, the two rollout/tito_session_mismatch_rate/* keys, and perf/actor_train_mfu) into a per-process JSONL snapshot (atomic temp+rename; non-finite values become "NaN"/"Infinity"/"-Infinity" markers).

A test opts into gating with a top-level declaration, parsed from the AST:

register_ci_gate(metric_key="rollout/raw_reward")  # band filled from GATE_DEFAULTS
register_ci_gate(metric_key="perf/actor_train_mfu")  # tracked, never judged

tests/ci/metric_history/run_gate.py merges the records, evaluates each spec against the mean of up to 20 trusted baselines, and exits 1 when an enforced spec errors or fails with at least 10 baselines. The store path comes from --db / --metric-history-path, else $VIME_METRIC_HISTORY_PATH, else ./metric_history.db. --write-baseline records trusted history (scheduled builds only); --mark-untrusted-sha SHA revokes a bad commit’s runs. The end-to-end check is python tests/ci/metric_history/verify_gate_e2e.py.

Buildkite wiring#

The CPU verifiers run in the plugin-contracts step of .buildkite/pipeline.yml: tests/ci/flops_oracle/verify_flops.py (V5), pytest tests/ci/metric_history, and tests/ci/metric_history/verify_gate_e2e.py (V1). GPU-suite opt-in: a test exports VIME_CI_GATE_RECORD_DIR (per-build directory, uploaded as a build artifact) and a follow-up step runs run_gate.py --write-baseline on scheduled builds with VIME_METRIC_HISTORY_PATH naming the shared SQLite store. No hostPath persistence is assumed; the store travels as a Buildkite artifact.