estimate CLI, plus two opt-in engine corrections - #1
Merged
Merged
Conversation
Derived from the B300 entry the way GB200 derives from B200; the header comment spells out each number so the datasheet can replace it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
memoryFootprint charged one recurrent state per resident sequence, the
physics floor. Hybrid KV managers reserve several per request (SGLang: 3
to 5 depending on the radix-cache strategy) plus speculative slots, and
on Kimi K3 that pool, not the paged cache, caps concurrency: the
simulator admitted 4x what an 8x B300 node measures.
EvalOptions.statePool {slotsPerSeq, specSlots, stateDtypeBytes} threads
into the three capacity gates; the default is bit-identical to before.
MemoryFootprint now also reports the paged and state parts and the slot
count. Five slots at 0.9 static fraction lands within 16% of the
measured 101-request ceiling.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The naive backend hides two hand-set fractions of the memory and comms
streams behind the widest one; nothing in the trace informs them and
they are the largest lever on every number shown. The dag backend keeps
the same per-op prices and runs each segment as a software-pipelined
loop over its repeats: the period is the larger of the fullest stream
and the longest dependency chain (each op as wide as its slowest
stream), the first iteration also waits for its weights. Time always
lands in [widest stream, serial sum]; busy and busyPerOp are the naive
backend's op for op, so bound-by and the DAG view keep working.
makeCostBackend({memoryOverlap, commsOverlap, scheduler}) selects; the
default stays naive. The UI gains an overlap source picker and the
step-time bar draws a scheduled trace's own visible split.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
machines.ts becomes core/hardware/machines.ts (plus parseMachine for a machine spelled on a command line) and the worker's toRow becomes optimizer/enrich.ts enrichCandidate, returning a ConfigResult the UI's row type extends. A Candidate now carries the backend that priced it, and the search's per-placement scorer is exported. No behavior change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The explorer's pipeline, scriptable: models and chips tables, a streaming sharding search with a ranked top-N, explain for one worked sharding (memory split, batch, step time, bound-by, and the vLLM/SGLang flags the roles spell as), a threaded sweep over chips x machines x phases x SLOs, and report to re-render its rows. --json emits one row per line. The two engine corrections are flags, off by default: --state-slots (and --spec-slots, --state-dtype, --mem-fraction) for the recurrent-state slots a hybrid KV manager holds per sequence, --scheduler dag to read overlap off the op graph. scripts/search.ts is gone, superseded. esbuild bundles src/cli into one dependency-free dist/cli/estimate.mjs; node cannot run the sources directly under moduleResolution bundler. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
Adds the
estimatecommand line over the existing engine, so sweeps and pinned configurations can live in other repos instead of throwaway scripts, and corrects the two places the simulator misleads. Both corrections are opt-in: engine defaults are unchanged and every upstream suite passes untouched.The CLI
src/cli, bundled by esbuild into one dependency-freedist/cli/estimate.mjs(node cannot run the sources directly undermoduleResolution: bundler).searchstreams a line per priced tuple to stderr and the ranked table to stdout;--jsonemits one row per line.explainscores one explicit sharding through the search's own scorer and prints the memory split, the operating batch, bound-by, and the vLLM/SGLang flags the roles spell as.sweepruns one worker thread per chip so a chip's warm reshard-plan caches stay put.scripts/search.tsis deleted, superseded bysearch --overlap 0,0.Correction 1: reserved state slots
memoryFootprintcharged one recurrent state per resident sequence, the physics floor. Real hybrid KV managers reserve several per request (SGLang: 3 with the radix cache off, 4 with extra_buffer_lazy, 5 with extra_buffer) plus one per speculative draft token. On Kimi K3 that pool, not the paged cache, caps concurrency, so the simulator admitted about 4x what an 8x B300 node measures.EvalOptions.statePool {slotsPerSeq, specSlots, stateDtypeBytes}threads into the three capacity gates.MemoryFootprintnow also reports the paged and state parts and the slot count. At the default the arithmetic is bit-identical to before. Five slots at a 0.9 static fraction gives 117 resident sequences against a measured 101 on that cell.Correction 2: overlap from the op graph
The naive backend hides two hand-set fractions of the memory and comms streams behind the widest one; nothing in the trace informs them, and they are the largest lever on every number the tool shows.
makeDagScheduleBackendkeeps the same per-op prices and runs each segment as a software-pipelined loop over its repeats: the period is the larger of the fullest stream and the longest dependency chain, and the first iteration also waits for its weights. Time always lands in [widest stream, serial sum];busyandbusyPerOpare the naive backend's op for op, so bound-by and the DAG view keep working.makeCostBackend({memoryOverlap, commsOverlap, scheduler})selects, defaulting to naive. The explorer gains an overlap source picker, and the step-time bar draws a scheduled trace's own visible split.Also
gb300-nvl72, an estimated entry whose header comment derives every number and says what would replace it.src/ui/machines.tsmoves tocore/hardware/machines.ts(plusparseMachine), and the worker'stoRowbecomesoptimizer/enrich.ts, so CLI numbers are the explorer's numbers rather than a second implementation of them.Verification
npm run typecheck,npm run format:check,npm run bench, and the full suite (127 tests, 19 files) pass. New suites:tests/state-slots.test.ts,tests/dagSchedule.test.ts,tests/cli.test.ts. CI also builds the bundle and smoke-runs it.Every number the tool emits is an estimate from a static roofline model. The two corrections move in the right direction against two measured points; they are not a calibration.
🤖 Generated with Claude Code