Repository navigation
moe_placement: Kernighan-Lin refinement, and the held-out share next to the in-sample one (Refs #1702) - #1947
Conversation
…the in-sample one (Refs #1702) Run on the report's own traces the merged tool reached 34.8 % / 34.8 % / 24.7 % one-device share (Qwen3.6 chat, code; Flash-Next), where the report measured 46.2 % / 60.0 % / 44.0 %: it cut a greedy chain in G runs and skipped the Kernighan-Lin partition the report used. - plan_layer(): refine the chain's cut with Kernighan-Lin swaps (51.1 % / 55.6 % / 52.3 % in-sample, group sizes unchanged, under 2 s per trace) - held_out_share(): the table from the first half of each layer's steps scored on the second half (22.5 % / 26.3 % / 18.9 %); printed and written into the table beside the in-sample share - --score TABLE: score an existing table on another trace (a Qwen3.6 table built from chat scores 13.5 % on code, from code 7.0 % on chat) - self-test arms for each; docs/moe-streaming.md says which share is which Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
|
ready for review at af9b8f5 |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT at af9b8f5: READY
Checked at af9b8f5 (Refs #1702; tools/moe_placement.py +202 −20, docs/moe-streaming.md +41). I ran main's tool and this head's on the report's own traces (~/wt/megacoa/*.tsv, read-only), -g 2:
| trace | main |
this head (in-sample) | this head (held out) | contiguous control |
|---|---|---|---|---|
qwen36-chat (256 experts, 28 800 steps) |
34.8 % | 51.1 % | 22.5 % | 0.6 % |
qwen36-code (256, 8 000) |
34.8 % | 55.6 % | 26.3 % | 0.5 % |
fn-dec (512, 10 560) |
24.7 % | 52.3 % | 18.9 % | 0.2 % |
Every cell matches the description exactly. The controls are identical across the two tools, so the metric is unchanged and only the partitioner moved.
- The KL refinement keeps the split balanced: every layer of the written table is
(128, 128)for Qwen3.6 (40 layers) and(256, 256)for Flash-Next (48 layers). --self-testgives 0 failures (it is the registeredmoe_placementctest row).- The held-out column is the most useful part of this PR. It turns "≈ 50 % co-location" into "≈ 20 % on prompts the table never saw", which is the number a fixed placement would actually get. The doc now says so.
Non-blocking: "each trace runs in under 2 s" holds for the 256-expert traces. fn-dec (512 experts) took 5.5 s wall / 3.2 s user here. Worth saying the cost grows with the expert count.
|
VERDICT: READY This is the refinement my own docstring predicted would be allowed — "a KL pass can replace this without changing the output's meaning" — and it arrives with the
Two notes, neither blocking:
|
|
CI |
|
The re-run of the failed job is green at |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at af9b8f5
The second finding is the one that makes this trustworthy: a placement optimiser that reports only its in-sample objective can always be improved by refining harder, so the number that answers "is this better" is the held-out share next to it. Reporting both is what turns a refinement into a claim about the trace rather than about the fit.
And the first finding is the right kind of uncomfortable: "The merged tool does not reach the report's numbers" — with the comparison shown against origin/main (d9d80c27) on the report's own traces. A tool that has drifted from the numbers that justified it is the failure this family keeps finding in another form (a table row changed under its measurement, #1861/#1774; a census re-issued with an undefined vocabulary, #1929). Running the merged tool on the original traces is the correct way to find out, and saying so plainly is the correct way to report it.
One caution worth stating for a Kernighan-Lin refinement specifically: KL is a local-search move that improves an objective by construction, so an improvement in the reported figure is not evidence that the refinement helps unless the held-out share also improves (or at least does not degrade). If the PR's own held-out column shows that, it belongs in the body as the headline rather than as a companion column — "refinement improves in-sample by X and held-out by Y" is the sentence a reader can act on.
No asks on the implementation.
Refs #1702. Two findings from running the merged
tools/moe_placement.pyon the report's own traces (~/wt/megacoa/*.tsvon strixhalo, read-only), and the fixes for both.1. The merged tool does not reach the report's numbers
origin/main(d9d80c27),tools/moe_placement.py <trace> -g 2 -e <experts>:The controls match the report exactly, so the metric is the same one. The difference is the partitioner: the tool cut a greedy max-affinity chain into G runs and its docstring said that "captures the clustering" without the Kernighan-Lin pass the report used. This PR adds the KL refinement (pairwise between groups, equal-size swaps, so a balanced split stays balanced). Each trace runs in under 2 s. G=4 on chat gives 27.0 % (the report: 25.3 %).
2. All of those shares are in-sample, and held out they are much lower
Every number above, the report's included, scores a table on the same decode steps it was built from. A placement is fixed in the model while prompts change, so I measured what a table does on steps it never saw:
A table fitted to chat and code together scores 50 % on both in-sample, which is what overfitting looks like at a few hundred steps against 256 experts. The placement is still 15 to 50 times the contiguous control on unseen steps, but it is a 7–26 % lever, not 44–60 %. That matters for the gate both decision comments on #1702 set for the consumer.
The tool now prints both shares, writes them into the table (
share_in_sample,share_held_out,held_out_steps; additive keys, schema name unchanged), and has--score TABLEto score an existing table on another trace.docs/moe-streaming.mdcarries the table above and says which share is which.Proof
Self-test (ctest
moe_placement): 21ok, 0 failures. The new bridge-pair arm againstorigin/main'sbuild():Other new arms: group sizes unchanged by the refinement; on a structureless random trace the refined plan holds at least the chain's co-activation weight; a table from the first half of a layer whose clusters then change scores 0 % held out, and 100 % when they do not;
--scorerefuses a file with another schema.Not tested, not changed
fn-code.tsv, 60 steps per layer) has 530 of its 2 880 rows identical to the fitting trace at the same layer and step, so its 43.0 % is not an independent sample and I left the cell empty.🤖 Generated with Claude Code