Align every GEAK benchmark on the Hyperloom warm-server protocol - #437
Draft
yueliu14 wants to merge 2 commits into
Draft
Align every GEAK benchmark on the Hyperloom warm-server protocol#437yueliu14 wants to merge 2 commits into
yueliu14 wants to merge 2 commits into
Conversation
GEAK's validation measured throughput as the median of 3 rounds while the Hyperloom orchestrator that rebenches the same kernel measures one warm round: boot the server, run a full untimed round, report the second pass. Two different statistics over the same kernel is how the two sides disagreed on whether a win was real. * warm_server is now the default lifecycle in bench_e2e.sh, and the default for the search, parity and validation purposes in e2e_workflow.js / run_e2e.py. REPEATS defaults to 1: one timed round IS the protocol, not a truncation of it. Carve-out for REPEATS=0 (shape capture) and PROFILE=1, which produce no throughput number and so have no lifecycle to align. * isolated_server stays available for boot-to-boot dispersion, opt-in only. * Delete E2E_REPEATS. It was prompt-only -- no role doc or script ever read it. Accuracy gate: tol 0.01 -> 0.03 and a new absolute floor of 0.5 on both legs. Both legs answer the same seed-pinned subset at temp=0, so the noise scale is the discordant pairs, sd(delta)=sqrt(d)/n ~= 1.6pt at n=200. The old 0.01 sat at 0.6 sd and rejected ~1 in 4 kernels whose quality had not moved. The floor catches the case a purely relative gate is blind to: a broken baseline that an equally broken candidate matches. Extract the two summary emitters out of bench_e2e.sh into scripts/bench_summarize.py (from-runs / from-replicas). They were duplicated heredocs with no test, and every acceptance decision in the product reads their output; a contract field added to one and not the other produced two bench_summary.json shapes with nothing to catch it. bench_e2e.sh 1053 -> 851 lines. Verified: 1171 tests under e2e_workflow/scripts/tests, 168 in interface/test_run_e2e_dispatch. The new emitter is byte-identical to the old heredocs over 12 replayed input shapes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…-hardware check Follow-up to a2cbefd, which shipped the lifecycle change with its prose and its role docs still describing the old ">=3 repeats, median + spread" protocol. * Docs/roles now say what the code does: one discarded warmup round then one timed round, extra samples only when a dispersion estimate is actually needed (PLAN.md, README.md, roles/director.md, roles/e2e_integrator.md, knowledge/e2e_optimization.md, knowledge/sglang_internals.md). preflight.md's "baseline spread > ~5% => re-measure" rung now says it applies only with more than one timed sample: at the default, spread is 0.0% by construction and there is nothing to gate on. * REVERT the accuracy-gate knobs from a2cbefd (ACCURACY_TOL 0.03 -> back to 0.01, drop ACCURACY_FLOOR). The tolerance argument stands on its own, but it is a gate-policy change, not a measurement-protocol change, and bundling it here makes one PR that has to be accepted or rejected as a unit. It belongs in its own PR with its own evidence. * bench_e2e.sh: fold the two staged-sibling lookups (bench_summarize.py, server_teardown.sh) into one _stage_lookup helper -- they were the same six lines twice, including the same "" -> /scripts/... guard. * Correct the comparability warning in bench_e2e.sh and api-reference.md. It claimed warm_server "reads systematically HIGHER" than isolated_server. That is only true where prefix-cache reuse is available; measured on DeepSeek-V4-Pro TP8 with RANDOM_RANGE_RATIO=1.0 / ISL 8192 (random prompts, ~no shared prefix) warm read 826.9 vs an isolated median of 833.3 tok/s -- the other way. The rule is unchanged (never ratio across lifecycles); the reason is now "sign and size are not predictable from the config alone", which the counterexample supports and the old wording did not. * test_bench_e2e_teardown_lookup: set SERVING_GPU_LOCK_DISABLE=1. The two cases that pass the staging gate walk into the serving-GPU mutex, a real /tmp lock shared with any live benchmark on the box, so the suite could block for SERVING_LOCK_WAIT behind an unrelated run and read as a hang. Verified on hardware (the branch had only ever been unit-tested). Same box, model, serving invariant and tuning bundle as an isolated_server x3 validation run earlier the same day, so the lifecycle is the only variable: isolated_server x3 base 833.298 final 879.030 +5.488% ~68 min warm_server x1 base 826.936 final 886.571 +7.212% 30.8 min Same verdict, 2.2x faster, 6 cold boots down to 2. The 1.72pp gap between the two deltas is what one sample per leg buys: the isolated legs measured 2.61% and 2.81% spread, so a low base draw and a high final draw compound to ~1.6pp on their own. Read that as the cost of the default -- comparability and wall-clock in exchange for the dispersion test -- not as a bias between the protocols. Unit suite unchanged at 1171 tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
GEAK's validation measured throughput as the median of 3 isolated-server replicas, while the Hyperloom orchestrator that rebenches the very same kernel measures one warm round: boot the server, run a full untimed round, report the second pass. Two different statistics over the same kernel is how the two sides ended up disagreeing about whether a win was real.
Why
This is not hypothetical. From GEAK's own KB (
e2e_workflow/knowledge/learned/moe-fp8-blockscale-tune-gfx950.md), Qwen3.5-122B-A10B-FP8, TP=2, gfx950/MI355, fp8 block[128,128] MoE at 21.4% of GPU time:validated_no_winThe difference was the baseline moving underneath the comparison: base median rose from 2405.9 (warm-start) to 2451.5 (same-session), so most of the apparent gain was drift, not the kernel. Note that the wrong answer was the more convincing-looking one — non-overlapping ranges plus byte-exact parity. It also shows byte-exact parity is not evidence of a throughput win.
One lifecycle for every throughput number is the fix.
What changes
warm_serverbecomes the default lifecycle inbench_e2e.sh, and the default for the search, parity and validation purposes ine2e_workflow.js/run_e2e.py.REPEATSdefaults to 1: one timed round is the protocol, not a truncation of it. Carve-outs forREPEATS=0(shape capture) andPROFILE=1, which produce no throughput number and so have no lifecycle to align.isolated_serverstays available for boot-to-boot dispersion, opt-in only, with its ownvalidation_measurement_mode/validation_replicasknobs so an operator can make the final arbitration stricter than the search that fed it.E2E_REPEATS. It was prompt-only — no role doc or script ever read it.bench_e2e.shintoscripts/bench_summarize.py(from-runs / from-replicas). They were duplicated heredocs with no test, and every acceptance decision in the product reads their output; a contract field added to one and not the other produced twobench_summary.jsonshapes with nothing to catch it.bench_e2e.sh1053 -> 851 lines.Verified
Unit: 1171 tests under
e2e_workflow/scripts/tests, 168 ininterface/test_run_e2e_dispatch. The new emitter is byte-identical to the old heredocs over 12 replayed input shapes.On hardware — a direct protocol A/B. Same box, model, serving invariant and tuning bundle;
adapters/andbench_replica.shbyte-identical between the two runs, so the lifecycle is the only variable. DeepSeek-V4-Pro, vLLM, TP=8, ISL 8192 / OSL 1024 / conc 64, 192 prompts:isolated_serverx3 (before)warm_serverx1 (this PR's default)Same verdict, 2.2x faster, 6 cold boots down to 2. Server boot alone was 466 s and 381 s of the two legs — that is what the extra replicas were re-paying.
The tradeoff, stated up front
The two deltas are 1.72 pp apart, and that gap is the honest cost of the change, so it should not be discovered in review.
One sample per leg means
spread = 0.0%by construction — an absence of dispersion evidence, not a quiet box — and thefinal_min > base_maxnon-overlap test carries no information at all. The isolated legs measured 2.61% and 2.81% spread, so a low base draw and a high final draw compound to ~1.6 pp on their own, which accounts for the observed 1.72 pp. Read it as sampling, not as a bias between the protocols.roles/director.mdhandles this explicitly rather than hiding it: underwarm_serverthe samples share one boot, so spread is narrower than true run-to-run spread; whendelta%is within 2x the noise band and only non-overlap carries the win, the Director must say so innotesand prefervalidated_no_win. At one sample it must record that the dispersion test was unavailable.bench_summary.jsoncarriesmeasurement_modeanddispersion_basisso any consumer can tell which lifecycle produced a number.Numbers are comparable only within one lifecycle. The header warning originally claimed
warm_server"reads systematically HIGHER"; the hardware run above is a counterexample (warm 826.9 vs isolated median 833.3 — the other way, becauseRANDOM_RANGE_RATIO=1.0at ISL 8192 leaves almost no shared prefix to cache). The rule is unchanged; the stated reason is now that the sign and size are not predictable from the config alone.Out of scope
An earlier revision of this branch also loosened the gsm8k accuracy gate (tol 0.01 -> 0.03, plus an absolute 0.5 floor). That has been reverted here. The argument stands on its own, but it is a gate-policy change rather than a measurement-protocol one, and bundling it would force this PR to be accepted or rejected as a unit. It will come back as its own PR with its own evidence.
🤖 Generated with Claude Code