Repository navigation
Kimi K3.1 recipe: route 9..20 decode rows through the pushed pair gather and standalone top-16 - #24
Open
tunamitom wants to merge 1 commit into
Conversation
…op-16 (numerics change on re-export) Above eight rows the recipe left the route exchange entirely: the general path's latent all-reduce (rows x 3584 BF16), router all-gather, two copies and the native route top-k. MAX_ROWS goes 8 -> 20 so decode rounds of nine to twenty rows (two concurrent speculative streams verifying up to 2 x (depth + 1) rows, or four-stream rounds up to twenty) stay on the route exchange: the paired gather plus the standalone top-16 selects their experts; the fused single-exchange select stays at <= 8 rows. The decoder routes every 9-20-row round onto this path unconditionally; the recipe prepares 1-20 rows or raises at preparation, with no pin detection and no fallback to the general path. Transport and speed: the route path is not push-gated -- it runs on whatever paired-gather transport the b12x plan selects. The per-layer speed evidence (30.75 / 38.35 / 48.57 / 59.63 us saved at 9 / 12 / 16 / 20 rows; slowest-rank medians, >= 200 graph replays x 5; general path 47.05-80.52 us vs route path 16.30-20.89 us per MoE layer) was measured on a push-planned exchange. The pull transport at nine to twenty rows is UNMEASURED -- that is the path a default upstream deployment takes at these widths. The push path carries the evidence, no speed claim is made for the pull transport, and measuring it at 9/12/16/20 rows is a follow-up before this path is relied on by default. Numerics change on re-export at 9-20-row rounds (flagged in the subject): the latent arrives by gather instead of the BF16 all-reduce, so the hidden-shard sums regroup -- 2.63e-3 relative RMS against the general path at every width, one BF16 unit roundoff of the general path's partial sums. The route path is strictly closer to the FP32 product (1.66e-3 vs 2.36e-3 rel RMS). Selected ids are identical to the general path at 9/10/12/16 rows over 6 banks x 8 ranks (weights within 5 fp32 ULP), with one near-tie 16th-slot swap row in 960 at 20 rows (near-tie gate re-run: 3.2M rows at 9/12/16/20, every set difference a 1-for-1 swap within 2 fp32 ULP, set rate <= 5e-5, 0 violations). Existing captured packages are unaffected; every re-exported Kimi package changes arithmetic at those widths on two- and four-stream decode, and the maintainer must accept that trade. Pin dependency: rows 17-20 need the FlashInfer standalone top-16 that accepts the full range (the pin declares KIMI_TOPK16_MAX_ROWS = 20). Their route-gather pull request NVIDIA#101 covers 9-16 rows; this change extends the recipe to 20 rows and needs NVIDIA#102's standalone select. The FlashInfer pin bumps when NVIDIA#102 merges; until then, preparation for 9-20-row rounds requires it -- on an older pin the top-16's row check raises at preparation of those widths, loudly, by design. Tests: tests/recipes/test_kimi31.py 33 passed (1/2/8/9/12/16/20-row route-gather surface selections -- one row fuses the select, two to twenty rows pair the exchange with the standalone top-16 -- plus the 21-row envelope rejection and the 25 existing tests); with test_kimi3_preparation.py 57 passed. The Flare test mocks the b12x plan surfaces: it proves which surfaces are planned, not results. The GPU evidence is the flashinfer side's CUDA tests for the top-16 row-range change; no Flare-level GPU route test was run on this tree. Earlier end-to-end round numbers were measured with a full settings bundle and are dropped rather than misattributed. Validation: tests/recipes/test_kimi31.py + test_kimi3_preparation.py 57 passed on this branch against the release-lane base's 49 (the 8 new items; the remaining tests are identical and pass at base -- base-failure parity holds, no test that passes at base fails here). Material limitations: no Flare-level GPU route test and no pull-transport measurement (above); the route-vs-general arithmetic comparison is from the recorded measurements (6 banks x 8 ranks), not re-run here. Numerics class: NUMERICS-LIGHT, BF16-structural -- ids identical except the quantified near-tie swaps; the latent regrouping above is the documented one-BF16-roundoff difference, closer to FP32 than the general path. Design-Signed-Off-By: Hermes Agent (hermes-agent); design-review=a38f
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.
release/k31-exl3-tp8-20261108(intake lane, tip 1d4007f)pr/flare-pr9-route-rows-9-20-lane@95757eebWhat / why
Above eight rows the recipe left the route exchange entirely (latent
all-reduce rows x 3584 BF16, router all-gather, two copies, native route
top-k).
MAX_ROWS8 -> 20 keeps decode rounds of 9-20 rows (twoconcurrent speculative streams up to 2 x (depth + 1) rows, or
four-stream rounds up to 20) on the route exchange: paired gather plus
the standalone top-16; the fused single-exchange select stays at <= 8
rows. The decoder routes every 9-20-row round onto this path
unconditionally — there is no FlashInfer pin detection and no feature
fallback: the recipe prepares 1-20 rows or raises at preparation.
Claims and caveats
transport the b12x plan selects. The per-layer speed evidence
(30.75 / 38.35 / 48.57 / 59.63 us saved at 9 / 12 / 16 / 20 rows;
slowest-rank medians, >= 200 replays x 5) was measured on a
push-planned exchange. The pull transport at 9-20 rows is
unmeasured — that is the path a default upstream deployment takes at
these widths. The push path carries the evidence; no speed claim is
made for the pull transport, and measuring it at 9/12/16/20 rows
(slowest-rank medians, same method) is a stated follow-up before this
path is relied on by default.
title): the latent arrives by gather instead of the BF16 all-reduce —
2.63e-3 relative RMS vs the general path at every width (one BF16
unit roundoff of the general path's partial sums); the route path is
strictly closer to FP32 (1.66e-3 vs 2.36e-3). Ids identical at
9/10/12/16 rows (6 banks x 8 ranks, weights within 5 fp32 ULP); one
near-tie 16th-slot swap row in 960 at 20 rows (near-tie gate over 3.2M
rows: every set difference a 1-for-1 swap within 2 fp32 ULP, set rate
<= 5e-5, 0 violations). Existing captured packages are unaffected;
re-exported packages change arithmetic at those widths — maintainer
acceptance required.
Dependency — flashinfer PR NVIDIA#102 (standalone top-16 select)
The standalone top-16 in the FlashInfer pin must accept the full 1-20
row range (the pin declares
KIMI_TOPK16_MAX_ROWS = 20). The actualrelationship to the two upstream changes: their route-gather PR (NVIDIA#101)
covers 9-16 rows; this PR extends the recipe to 20 rows and needs NVIDIA#102's
standalone select (the 17-20-row work, now open as
local-inference-lab/flashinfer#102). The pin bumps when NVIDIA#102 merges;
until then, preparation for 9-20 rows requires it — on an older pin
the top-16's row check raises at preparation of those widths, loudly and
by design. There is no feature detection and no fallback to the general
path: 9-20-row rounds either route with the pinned select or preparation
fails visibly. Merge blocker: the pin bump lands with or immediately
after NVIDIA#102 merges.
Numerics class
NUMERICS-LIGHT, BF16-structural (see above).
Tests
tests/recipes/test_kimi31.py— 33 passed (route-gather surfaceselections at 1/2/8/9/12/16/20 rows: one row fuses the select, two to
twenty rows pair the exchange with the standalone top-16; a 21-row
envelope-rejection check; the 25 existing tests). With
test_kimi3_preparation.py: 57 passed vs base's 49 (the 8 newitems; base-failure parity holds — no test that passes at base fails
here). Re-run on the final head in this pass.
are planned, not results. The GPU evidence is the flashinfer side's
CUDA tests for the top-16 row-range change (Consult ignore_eos when classifying a finish reason at the output limit NVIDIA/hyperflare-inference#102); no Flare-level
GPU route test was run on this tree. The earlier end-to-end round
numbers were measured with a full settings bundle and are dropped
rather than misattributed to this change.
Dependencies
FlashInfer PR NVIDIA#102 (local-inference-lab/flashinfer#102, standalone
top-16 select extended to 20 rows) for the pin bump; their route-gather
PR NVIDIA#101 covers 9-16 rows, ours extends the recipe to 20 and needs NVIDIA#102's
standalone select. Preparing 9-20-row packages requires the NVIDIA#102 pin
until it merges (dependency note above).