fix(bench): skip an unsupported slot count instead of aborting the sweep - #153
fix(bench): skip an unsupported slot count instead of aborting the sweep#153rakhimovv wants to merge 2 commits into
Conversation
The default sweep derives slot counts as [experts, int(0.4 * layers * experts)] per profile. For minimax-m2.5-marlin that second value is 6348, which OffloadMoeCache rejects because the marlin backend caps padded experts at 1024. The ValueError was uncaught, so the run died on the 4th of 8 profiles and the remaining four never ran -- and the table it left behind looked finished rather than truncated. Catch it in print_table and skip that one combination with a printed line. Clamping was the alternative and would have been worse: it changes the size the row measures without saying so. Build the cache before printing the header. The header and column titles used to be printed first, so a skip there would leave an orphan header with no rows under it -- the same shape the abort produced. The limit stays the backend's: the benchmark asks by constructing rather than copying 992 into a file that would not learn when a backend changes. Fixes FlashML-org#146
MR-1124
left a comment
There was a problem hiding this comment.
Checked the diff — looks right to me. Builds the cache before printing the header, asks the backend for the limit rather than hardcoding it, matches what we discussed. Thanks for the quick fix!
Reworks the previous commit after review. A run that measured nothing still exited 0. print_table now reports whether it measured anything and main tallies the skips, following the shape bench_decode_moe already uses. The exit status distinguishes the two cases that are not alike: a derived default one backend cannot satisfy is expected output and stays 0, so the documented no-arg sweep is not red forever, while naming a geometry by hand and getting nothing -- or measuring nothing at all -- returns 1. The comment was wrong twice. The cap is 992 slots; "caps padded experts at 1024" is the constraint that makes 992 the limit, not the limit itself. And MARLIN_MAX_CACHE_SIZE is a public constant in the module this file already imports from, so "it would drift" was not the reason to catch rather than pre-check. The real reason is that the guard also covers the num_experts floor, so pre-checking would duplicate the rule rather than the number. Also notes that a device OOM is a RuntimeError and still aborts, which is right: it is not a statement about the geometry being illegal.
|
Thanks for the review. Before it goes further I have to walk back two things I told you, both my error — I pushed corrections and updated the description. The row counts were wrong. I quoted 56 before / 120 after / 64 for the subset. The real figures are 112 / 240 / 128. Rows print with "Asks the backend for the limit rather than hardcoding it" was not a real argument. One behaviour change while I was in there: the first version exited 0 even when a run measured nothing. Now Also worth flagging since the description previously implied otherwise: "8 of 8 profiles" is a property of an 80 GB card. Re-review whenever suits. |
MR-1124
left a comment
There was a problem hiding this comment.
Thanks for the transparency and the fix. Checked the second diff — the exit-status logic matches what you described (0 for a partial default skip, 1 if everything's skipped or an explicit geometry fails), and the corrected comment reads right (992 limit, num_experts floor, RuntimeError still aborts). Appreciate you catching your own mistakes here.
Fixes #146. Sending this per @MR-1124's offer in the issue thread — happy to take review notes on it.
Problem
benchmarks/bench_offload_cache_copy.pyderives its default slot counts as[profile.experts, int(0.4 * profile.layers * profile.experts)]. Forminimax-m2.5-marlin(L=62, E=256) the second value is
6348, whichOffloadMoeCacherejects — the marlinbackend is capped at 992 slots. The
ValueErrorwas uncaught, so a plainpython benchmarks/bench_offload_cache_copy.pydied on the 4th of 8 profiles.The part that makes it worth fixing rather than documenting: the four profiles after it
never ran, and the output left behind reads as a completed sweep.
Fix
Catch it in
print_table, skip that one combination with a printed line, and report theskip in the exit status.
Clamping to the cap was the alternative and is worse — it silently changes the size the row
measures, so a reader comparing tables would be comparing different configurations without
being told.
Three details:
print_tableprinted theprofile header and column titles first, so a skip at the old call site would leave an
orphan header with no rows under it — the same shape the abort produced.
validate_rebuildruns in__post_init__ahead of the allocations, so the refused pathcosts nothing.
backend cannot satisfy is expected output and stays
0, so the documented no-arg sweep isnot red forever. Naming a geometry by hand and getting nothing — or measuring nothing at
all — returns
1. This follows the shapebench_decode_moe.pyalready uses for a failedbackend.
num_expertsfloor, so a pre-check would duplicate the rule, not just the number. (
MARLIN_MAX_CACHE_SIZEis a public constant in the module this file already imports from, so "the number would
drift" would not have been a real argument.) A device OOM is a
RuntimeError, so it stillaborts — which is right, since it is not a statement about the geometry being illegal.
Before / after
Default invocation, no arguments, on
bd372b6:15 tables rather than 16 is the point: 8 profiles × 2 slot counts, minus the one refused
combination, which is now reported instead of fatal. Every table is 16 rows (4 batch sizes ×
4 miss rates).
After, the skip is one line and names the reason, and the run ends with a tally:
Asking for that geometry explicitly now fails instead of passing quietly:
Explicitly naming the profiles that used to be unreachable is unchanged — still 128 rows,
exit 0:
"8 of 8" is a property of an 80 GB card, not of this change. The default sweep's largest
slot cache is
glm4.7-nvfp4@ 5696 = 70.5 GiB, thenminimax-m2.5-triton@ 6348 = 47.2 GiB.On a smaller GPU the sweep still dies partway through with a device OOM — that is a separate
limitation of the default slot counts and out of scope here.
Tested on
0.1.2, branched frombd372b6uv pip install -e ".[accel,dev]"The benchmark is synthetic, so no checkpoint is involved.
No test is added: nothing under
tests/importsbenchmarks/, and the guard is onlyreachable with a CUDA device.
What was wrong in the first version
from
grep '^[0-9]', and rows are printed withf"{batch_size:2d}", which right-aligns —so
bs=1andbs=4begin with a space and were silently dropped, losing exactly half ofevery table. The table counts and the profile counts were unaffected.
992into a file where it would drift.
MARLIN_MAX_CACHE_SIZEis public and already importablehere, so that was not the real argument; the real one is the
num_expertsfloor, above.