H20 heuristics on the bounded-candidates flow + measured-config autotune - #62
Draft
guzekai01 wants to merge 12 commits into
Draft
H20 heuristics on the bounded-candidates flow + measured-config autotune#62guzekai01 wants to merge 12 commits into
guzekai01 wants to merge 12 commits into
Conversation
Signed-off-by: mgoin <mgoin64@gmail.com> Assisted-by: AI
Signed-off-by: mgoin <mgoin64@gmail.com>
Signed-off-by: mgoin <mgoin64@gmail.com>
Signed-off-by: mgoin <mgoin64@gmail.com>
Signed-off-by: mgoin <mgoin64@gmail.com>
Signed-off-by: mgoin <mgoin64@gmail.com>
First H20 family on the candidate flow from PR inclusionAI#59; adds register-budget analysis (launch-bounds model, measured 232-reg demand) and a 1188-point parity suite locking family output to the legacy heuristic.
…base Port cache/measure/measured/space/worker/CLI from the autotune branch, adapted to the LayerConfig API and refactored testing utils; fixes five latent breaks in that branch's committed state. E2E validated on H20.
…e family explain_tuning_config exposes the TuningDecision behind a served config; the H20 search space prunes analysis-illegal candidates per shape_m and drops dead 8-bit warp_n=16 configs (smoke compile failures 300+ -> 54); the long-K small-tile MoE path joins the candidate family.
Dense joins the candidate flow with plain / TMA-warp-spec / deep-pipeline arms; the small-M dense override is out of scope by dtype (integer B), verified by negative-boundary tests. 288-point parity grid, all arms exercised.
tools/tune_sweep.py drives per-spec tunes and reports tuned-vs-heuristic per m; fixes found by running it: baseline timing visibility via Measurer semantics, fastest-correct selection when the baseline fails the golden gate, shared-GPU OOM (spares CLI + allocator release), chunked expert weight generation for TP-only E=384 layers, explicit sweep failures.
guzekai01
force-pushed
the
pinyi/h20-bounded-candidates
branch
from
August 19, 2026 03:08
4ec0204 to
c7c8ed1
Compare
…istic Follows upstream's policies/seed-selection revision: the former legacy get_config body moves into sm90_h20_families as build_h20_seed_config (the single implementation for all dtypes); sm90_h20 becomes a thin dispatcher. Zero-drift verified on a 1644-point pre/post snapshot spanning both parity grids and the out-of-scope dtype universes.
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.
What
Builds on #59's bounded schedule candidates flow (
problem → bounded candidates → shared analysis → explicit selection → audit trail) in threedirections:
this PR's base revision ("policies own seed selection"), the former H20
legacy
get_configbody now lives in the policy file asbuild_h20_seed_config— the single seed implementation for everydtype/construction — and
sm90_h20.pyis a thin dispatcher; the movewas verified by a 1644-point pre/post snapshot (both grids plus the
out-of-scope dtype universes): zero drift. ** The fused-E8M0 8-bit
universe — MoE (all tile sizes, including the long-K small-tile residency
tuner) and dense (plain / TMA warp-spec / deep-pipeline arms) — now
selects through
ScheduleCandidate/CandidateAnalysis/TuningDecision.Selection reproduces the legacy heuristic bit-for-bit (guarded by
~1.8k-point parity grids); what changes is that every decision now
records which alternatives were considered and why one was preferred.
CandidateAnalysisgainsregister_budget_per_thread(launch-bounds model, 8-aligned, 255 cap)and
register_pressured(against a family-supplied measured demand).This institutionalizes the H20 finding that motivated the earlier CTA
clamp: at 128 threads x 3 CTAs/SM the budget (168) sits below the
measured demand (~236) of grouped-input-scale mainloops, forcing
local-memory spills (measured 1.4x latency).
python -m humming.tunesweepsthe bounded search space per shape_m with a two-stage measurement
(coarse → top-k fine) gated by a golden-output correctness check, and
saves an m-bucket table keyed by layer+gemm+flags and fingerprinted by
gpu/sm/num_sms/humming/cuda versions. Runtime:
get_tuning_config()serves the measured winner on a valid cache hit and falls back to the
heuristics otherwise. The search space itself is analysis-driven: shared
candidate analysis prunes provably-illegal configs before any benching
(every pruning rule is backed by a kernel static_assert), which removed
~82% of the compile-failing candidates a sweep used to burn time on.
Usage
Offline tuning (per layer/gemm; writes ~/.humming/tune_cache/):
Sweep + report (reusable evidence/regression tool):
python tools/tune_sweep.py --out-dir /tmp/tune_sweep --fast # per-m table: heuristic ms vs tuned ms vs speedup, plus win/tie countsRuntime:
Audit ("why this config?"):
Effect (H20, fused-E8M0 fp8xfp4, DSV4-Pro TP8 shapes, m swept to 8192)
Produced by
tools/tune_sweep.py(fast space, strict golden gate); themeasurement gate never selects a config slower than the heuristic baseline,
so the floor is a tie. Shapes are the moe_tp=8/ep=1 per-rank projections of
DSV4-Pro (hidden 7168, moe_intermediate 6144, E=384, top_k=8).
Zero sub-1.0x rows and zero missing-baseline rows across all sweeps. Tune
winners are stable across the terminal-form refactor (flips only between
near-tied candidates, speedup drift within 3%).
Validation
passed / 86 device-skipped; the 33 failures are pre-existing hadamard
suite failures reproduced identically on this PR's base). Grids for the
three families (selector output == seed heuristic on every in-scope
point; negative boundaries served by the seed), Refactor SM90 tuning around bounded schedule candidates #59's own suites, and
the tune pipeline suites (cache round-trip/corruption, measurement
orchestration incl. worker death and correctness-gate semantics, CLI
validation).
branch turns the corresponding grid red.
snapshot: zero drift, including the out-of-scope dtype universes.
lookup serves the measured winner; cache misses and stale fingerprints
fall back to heuristics.
A finding from the sweep: stream-K tail-error vs the golden gate
While validating the sweep we found that stream-K schedules fail the golden
gate on ~0.002-0.004% of output elements (individual absolute errors of 2-3;
the remaining 99.996% sit inside quantization noise; the same schedule with
use_stream_k=False has zero violations, on both dense and indexed). The gate
is an all-element assert (rtol=0.05/atol=0.5), so every stream-K candidate —
including the stream-K heuristic baseline — is rejected, and tuned tables
select from the non-stream-K space only (which still beats the heuristic
substantially, see the tables above). This is a pre-existing kernel-side
numeric behavior, not introduced here. Kept as-is for this PR (conservative
gate); follow-ups tracked separately: (a) root-cause the stream-K reduction
tail, (b) discuss a statistical gate (violation-fraction + percentile bound)
that matches e2e accuracy sensitivity.
Not in this PR (planned follow-ups)
MoE) onto the candidate flow with their own parity grids.
compile-failing sweep candidates; absorbed by the poison machinery today).
exact humming_version match (every commit), and the JIT cache keys on
.cuh mtimes (any reinstall/image rebuild). Planned: (a) switch both to
content hashes of the sources that actually participate (the generated
kernel source is already part of the JIT key, so only the .cuh mtime
component needs replacing), so no-op updates reuse caches; (b) a
re-validation fast path for tune tables — on fingerprint mismatch, the
old winner is re-benched against the heuristic behind the same golden
correctness gate (incl. bucket-interior checks) instead of being
discarded: it passes the identical verification a full re-tune would
apply, trading only optimality (marked validated-stale, refreshed by a
background re-tune) and never correctness.
get_tuning_configinto SGLang's hummingMoE runner so serving picks up tuned tables (env-gated, heuristic
fallback), plus a deployment story for shipping tune caches with images.
We run this stack in production-like H20 serving and will follow up with
the SGLang-side PR.