fix(trace): keep per-tuner failure signal in the GEMM-tuning audit row - #1212
fix(trace): keep per-tuner failure signal in the GEMM-tuning audit row#1212iraj465 wants to merge 5 commits into
Conversation
CI E2E report — ✅ Succeeded
|
|
One correctness nit worth fixing, plus two comment inaccuracies. None of them block. The envelope promotion is broader than its own comment claims# The envelope leaves ``error_class`` unset even when every tuner failed;
# promote the first tuner's class so a failed run is greppable.
"error_class": result.get("error_class") or tuner_error_class,The comment says "even when every tuner failed", but the code promotes whenever any tuner carries a class, regardless of the run's own status. In elif has_candidate:
status = "ok"
micro_decision = "candidate"
elif all_failed:
status = "failed"So a run where one tuner produced a candidate and another died lands on envelope_failed = str(result.get("status") or "").strip().lower() == "failed"
...
"error_class": result.get("error_class") or (tuner_error_class if envelope_failed else None),
|
|
All three are fixed. HEAD is now The envelope promotionFixed, exactly as you wrote it. envelope_failed = str(result.get("status") or "").strip().lower() == "failed"
...
"error_class": result.get("error_class") or (tuner_error_class if envelope_failed else None),Sixth test added: You were right about the ordering in
|
A/B on the claw CI corpus: what this PR changes about GEMM-tuning visibilityScope, stated up front. This PR does not move Hyperloom e2e, and no table Backend disclosure. Of the 388 Replay limitation. A true two-arm replay is not possible here. The handler's Corpus, measured 18 Aug 2026 over 1. What the audit row holds
2. The population that is currently unreadable135 of 366 tuner entries carry no speedup. Today a crash and an honest "found
By tuner: 3. Ground truth: how many of those "no improvement" verdicts are realFrom the
So 93 runs died before tuning anything, every one of them reported success, and 4. What this PR does NOT fix
5. Review items, closed
Counts in the source comments are re-measured and date-stamped as of 18 Aug 2026 |
``_trace_gemm_tuning_run`` copied only ``tuner`` / ``best_micro_speedup`` / ``kept`` out of each ``tuners_run`` entry. A tuner that crashed and a tuner that ran to completion and found nothing both arrive with no speedup, so the audit trail could not tell them apart, and the run envelope leaves ``error_class`` unset even when every tuner failed. Keep the tuner's own ``status``, ``elapsed_s``, ``error_class`` and the head of its ``error`` (400 chars), and promote the first tuner's ``error_class`` to the envelope when the envelope has none. The three legacy keys stay unconditional; the new ones are omitted when empty, so a clean row is unchanged. Campaign evidence (/shared_nfs/hyperloom-claw, 300 gemm_tuning.jsonl files, 361 rows): 23 tuner runs exited non-zero and every one is recorded today as an ordinary result. Replaying the real result.json through the patched function: Qwen3-8B/20260813T091428Z a8w8 failed -9 500.4s subprocess_error DeepSeek-V4-Pro/20260815T002915Z fmoe_ck failed 1 288.5s subprocess_error Llama-3.1-8B-Instruct/20260813T091520Z sglang_dense_bf16 no_improvement 11.2s Qwen3-8B/20260730T122359Z sglang_dense_bf16 ok 15.63x 1584.9s The last two rows are the point: both are ``sglang_dense_bf16``, both were audited identically before this change, and 11.2s against 1584.9s is the only thing that separates a tuner that died in argparse from one that tuned 28 of 28 shapes.
Three review items on the GEMM-tuning audit row.
1. The promotion was ungated. A run can succeed on one tuner while another
fails, and `result.get("error_class") or tuner_error_class` stamped that
run's row with the failing tuner's class -- reporting the whole run as
failed by it. Gate on the envelope's own verdict.
Measured over the 320 `gemm_tuning.jsonl` traces in the claw campaign
(386 rows, 364 tuner entries):
ok rows carrying an error_class today 0 of 318
ok rows with >=1 tuner that produced no speedup 119
failed rows the promotion makes greppable <=12
`error_class implies the run did not succeed` holds perfectly in the
corpus today. Ungated, the promotion risks that invariant on up to 119
rows to reach at most 12. Every one of the 12 is `status: failed`, so
gating on `failed` keeps the entire benefit and gives up none of it.
(119 is an upper bound on exposure: the pre-patch trace drops per-tuner
error_class, so which of those tuners carried one cannot be read back.)
2. The `_TRACE_ERROR_CHARS` comment offered "an argparse rejection" as the
failure it identifies. That is the one failure it cannot see. A rejected
argument reaches neither side of the wrapper: the downstream tuner's
rejection is a returncode out of `subprocess.run`, and the wrapper's own
is a `SystemExit`, which its `except Exception` does not catch. Either
way the run arrives with no `error` field at all. Replaced with failures
that do produce one, and said what identifies the other kind instead.
3. `_TRACE_TUNER_KEEP_NULL` claimed "existing readers index on them" for all
three keys, and that a clean run's row "stays as compact as it was".
Neither is right for `kept`: nothing on the GEMM path writes it, and it
is null in all 364 tuner entries on record, so a reader can only be
indexing on its presence. And the row is not as compact as it was --
`status` and `elapsed_s` are new and non-null on clean runs, which is
what `test_gemm_trace_clean_run_row_stays_compact` itself asserts.
`kept` stays emitted, for shape only; both claims now say what is true.
Sixth test asserts a `status: ok` run with one failed tuner keeps a clean
row while the tuner's own error_class survives on its entry. 337 tests in
the file pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The comment quoted 364 tuner entries across 320 traces. The campaign is live, so re-measured 18 Aug 2026: 366 entries across 322 traces, 0 of them non-null. The claim holds; the numbers are now current. Also names the producer that would populate the field, per review: `_validate_forge_gemm_tuning_e2e` writes a separate `e2e_results` list and runs after this trace fires. Saying "nothing writes it" without saying what almost does left the reader to re-derive it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The campaign is live, so the census drifted: 320 ok rows, not 318, and 121 of them carry a tuner with no speedup, not 119. The invariant the comment justifies is unchanged -- 0 ok rows carry an error_class -- so only the sample size is restated, now date-stamped so the next reader knows when. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
280e222 to
363a8ba
Compare
Parked as draftIn last few Hyperloom CI runs, there is little evidence that GEAK gemm tuning Supporting split, re-measured over
All 4 GEAK rows are
Related issues #1210 and #1211 stay open. Nothing here is retracted. The 337 unit tests pass and the review items in the Corpus counts date-stamped 19 Aug 2026; the campaign is live and they drift |
|
@lishuoshuo-amd all four are addressed; taking this out of draft.
On On "stays as compact as it was": corrected to "keeps a failure's row about as small as a clean one's rather than making either smaller than before", which is what the test actually asserts. Re-measured your Also merged |
|
Closing this — not being pursued. Returned to draft first so the branch and its history stay intact if anyone picks it up. The review items from @lishuoshuo-amd were all addressed before closing (envelope Note for anyone reusing this: the body's |
Branch:
fix/gemm-tuning-trace-keeps-failures→mainBase:
origin/main=25d914cCommit:
45af0b8Closes: #1210
NOTE:
In last few Hyperloom CI runs (14thAug-19thAug), there is little evidence that GEAK gemm tuning
integrate result into Hyperloom does have downstream issues, so parking it for
now to reduce last minute regressions due to low testing.
What was wrong
Forge Gemm-tuning has drop in effect on integration when multiple proposals of gemm-tuning through Hyperloom.
_trace_gemm_tuning_runwrote three fields per tuner —tuner,best_micro_speedup,kept— and droppedstatus,elapsed_s,erroranderror_class. The envelope carried noerror_classeven when a tuner namedone. A crashed tuner and a tuner that ran and found nothing produced the same
row.
38 of the 337
tuners_runrows in/shared_nfs/hyperloom-claw/arefailedorempty_output. The trace showed none of them. Worked examples and the fullbreakdown are in the issue.
What this changes
Each row now carries
status,elapsed_s,error_classand a truncatederror. Keys whose value isNoneare dropped, except the three the schemaalready always emits — so a clean run's row is today's row plus
statusandelapsed_s, and nothing else grows.The envelope gains
"error_class": result.get("error_class") or tuner_error_class,so a per-tuner class is promoted only when the envelope has none of its own.
Generic by construction: no tuner name, no error string, and no exit code is
special-cased. The row records whatever the tuner reported.
Verification 1 — the patched function against real result.json
Executed the patched
_trace_gemm_tuning_runagainst four unmodifiedresult.jsonfrom the campaign, and compared its output with the row currentlyon disk.
/shared_nfs/hyperloom-claw/Qwen3-8B/20260813T091428Z/runs/gemm_tuning/kernel_entry_gemm_tuninga8w8failed(exit -9)subprocess_error, promoted to the envelope/shared_nfs/hyperloom-claw/DeepSeek-V4-Pro/20260815T002915Z/runs/gemm_tuning/kernel_entry_gemm_tuningfmoe_ckfailed(exit 1)subprocess_error/shared_nfs/hyperloom-claw/Llama-3.1-8B-Instruct/20260813T091520Z/runs/gemm_tuning/kernel_entry_gemm_tuningsglang_dense_bf16no_improvement/shared_nfs/hyperloom-claw/Qwen3-8B/20260730T122359Z/runs/gemm_tuning/kernel_entry_gemm_tuningsglang_dense_bf16ok, 15.6349xRows 3 and 4 are the contrast the trace could not previously express: an
11-second run and a 1585-second run, both recorded today as an unremarkable
kept: null.Verification 2 — tests
Five new unit tests in
src/hyperloom/inference_optimizer/tests/test_kernel_request_handlers_units.py,with a
_gemm_trace_rows(tmp_path, result)helper that reads back the JSONL thefunction actually wrote:
test_gemm_trace_keeps_tuner_failuretest_gemm_trace_promotes_tuner_error_class_to_envelopetest_gemm_trace_envelope_error_class_wins_over_tunertest_gemm_trace_clean_run_row_stays_compacttest_gemm_trace_survives_non_mapping_tuner_entriestuners_runentry does not raiseThe 7 request-handler / gemm test files, same interpreter, same machine:
The 110 failures are pre-existing and the failure sets are byte-identical on
both sides (
diffof the twoFAILEDlists is empty). The full repositorysuite does not complete on this machine — it exceeds a 2-minute budget and hits
collection errors in
test_multinode_server_log_dir.pyandtest_gpu_probe_remote.py, identically before and after — so the run is scopedto the files this change touches.
Related
This change makes a second defect visible rather than fixing it: 82 of the 96
sglang_dense_bf16tuner runs are rejected by argparse(
gemm_tuner.py: error: unrecognized arguments: --libtype hipblaslt) andrecorded as
no_improvement. Its root cause is in the standaloneforge_gemm_tunepackage, which is not in this repository. Filed separately.That second defect is #1211.