Repository navigation
fix(aisimulate): pass trace workloads straight to the AIC generator - #17523
Conversation
AISimulate's generator bridge now lowers a trace workload without request lengths and rejects placeholder ones (ai-dynamo/aisimulate#626), so the AIC renderer again passes the workload, and the manifest AIC returns, through unchanged. The renderer tests check that a trace DGD equals the synthetic one without TensorRT-LLM's KV-transfer buffer size. This needs an AISimulate nightly containing that change. The pin bump lands in this PR before it leaves draft. Signed-off-by: hongkuanz <hongkuanz@nvidia.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
✅ Dynamo PR CI passed — run 40917773565 (attempt 1) on
|
…hrough Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
Nightly 87 (0.13.0.dev202610290000000087, Rust 0.13.0-dev.202610290000000087) is built from AISimulate 03eadda3 and contains ai-dynamo/aisimulate#626, which the pass-through AIC renderer relies on. Update every pin and the three Cargo.lock files; only the aisimulate-core version and checksum change. Signed-off-by: hongkuanz <hongkuanz@nvidia.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AISimulate nightly 87 (ai-dynamo/aisimulate#616) shares each prefill rank's sending link and each decode rank's receiving link max-min fairly among concurrent offline P/D transfers. The page still said concurrent requests do not contend for a shared link. Signed-off-by: hongkuanz <hongkuanz@nvidia.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
/ok to test 99429c6 |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Trace workload rendering and validation components/src/dynamo/aisimulate/output/dgd/renderers/aic/renderer.py, components/src/dynamo/aisimulate/tests/dgd/test_renderers.py |
The renderer passes the original workload to the generator and no longer removes the transfer-buffer-size argument from generated manifests. Tests check workload pass-through and compare manifests with a test-local argument filter. |
AISimulate version pins
| Layer / File(s) | Summary |
|---|---|
Dependency and documented version updates Cargo.toml, lib/bindings/python/Cargo.toml, pyproject.toml, benchmarks/pyproject.toml, container/deps/requirements.aisimulate.txt, docs/fern/pages/reference/components/planner-configuration.mdx |
AISimulate dependency pins and planner documentation now reference the October 29 build. Existing Python version constraints and optional feature settings remain unchanged. |
Offline transfer contention documentation
| Layer / File(s) | Summary |
|---|---|
Shared-link transfer model docs/fern/pages/cli/operations/simulation-with-dynosim/simulation-model.md |
The documentation describes line-rate transfer pricing and max-min sharing when concurrent transfers use the same prefill sending link or decode receiving link. |
Priority:
Estimated code review effort: 2 (Simple) | ~10 minutes
Merge Risk: 
Minimal · up to 99429
-
Trace workloads now pass directly to the generator; no verified functional issue blocks merging.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passed-
Full details: Description check
-
Explanation
The description follows the repository template closely. It has Overview, Key Changes, Validation, and Issues and Ongoing Work sections, plus the checklist. It explains the revert and the pin bump from nightly 86 to 87, names the affected files, and gives detailed validation results. It also lists known gaps: GPU deployment and full CI are unverified. The 'Closes
#XXXX' line is absent, but the template marks that item as advisory today, and the description states there is no tracked issue. The pull request checklist item is unchecked, and the template's required item is '/pr-checklist' skill use. Those are minor gaps and do not affect the overall completeness.
-
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 4 functions across 2 files. (7 skipped: 7 unsupported.)
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.
jthomson04
left a comment
There was a problem hiding this comment.
LGTM. The renderer matches the pre-#17474 version exactly, and every AISimulate pin is consistent at nightly 87. A few optional nits inline.
The description still says "It stays a draft for now", but the PR is marked ready for review.
- Scope KV transfer link sharing to offline prediction and note that live Mocker workers apply a fixed delay per transfer. - Drop the fake-bridge pass-through test; the real-bridge trace test already covers it in the dynamo-runtime pre-merge CPU lane. - Drop a docstring that repeated its function name. Signed-off-by: hongkuanz <hongkuanz@nvidia.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
/ok to test 88bca4d |
dmitry-tokarev-nv
left a comment
There was a problem hiding this comment.
No P0, P1, P2 or P3 findings at 88bca4d08f5b6a3b4186783b9a40c6c6458ce073.
This review read all 12 changed files at that head, and the commit 88bca4d08f in full. The changes that the three review threads of 2026-10-29 asked for are in this head.
Open items: none.
What this review measured, with controls.
-
Pins. All 9 pin locations name nightly 87, and no file names nightly 86. The same search finds the 9 nightly 86 pins on
main. The sha256 of theaisimulate-core0.13.0-dev.202610290000000087 crate iseb823782e806dd74cba719906a6b828b86f415aad54c6d5016c29ff278e89319. It matches the crates.io index and all threeCargo.lockfiles. In each lock file, only theaisimulate-coreversion and checksum change.cargo tree --lockedpasses on the three manifests at this head, atmain, and at a merge of this head withmainat261a106a3d. As a control, a pin set back to nightly 86 fails that check. -
Nightly 86 against nightly 87. The two wheels have the same
Requires-Distlines, entry points and file list. The 26 changed files are all underaisimulate/: the generator and_runtime.abi3.so. The two crates have the same dependencies and features, and every changed Rust item ispub(crate). So the statement "No API or dependency change" in the description holds. -
Trace rendering,
components/src/dynamo/aisimulate/tests/dgd:Tree Nightly Result this head 87 66 passed this head 86 3 failed with SweeperCandidateError: the matching workload must provide isl and osl (or set SlaConfig.isl/osl overrides)main86 69 passed main87 3 failed with SweeperCandidateError: a trace workload has no fixed request length; remove workload.isl, workload.oslThe 3 failures are the three cases of
test_installed_aic_renders_trace_workloads_like_synthetic_ones. So each half fails alone, as the description says. -
Test strength. Two deliberate breaks of the renderer at this head ran with nightly 87. The renderer from
mainfails the same 3 cases. An edit of the manifest for trace workloads only fails the TensorRT-LLM case. So the real-bridge test still covers what the removed fake-bridge test covered. -
TensorRT-LLM transfer buffer. The disaggregated TensorRT-LLM trace DGD is byte-identical at
mainwith nightly 86 and at this head with nightly 87. Both keep--trtllm.cache_transceiver_config.backend DEFAULTon prefill and decode. Neither has--trtllm.cache_transceiver_config.max_tokens_in_buffer. The synthetic DGD sets that size to6528. The aggregated and disaggregated trace DGDs for TensorRT-LLM, vLLM and SGLang are also identical between the two setups. -
simulation-model.md. A probe on the two crates replayed two concurrent 128 ms transfers at 1 GB/s. With nightly 86, each transfer took 128 ms in every layout. With nightly 87, two transfers into one decode rank took 256 ms each. Two transfers from one prefill rank also took 256 ms each. Transfers on separate ranks took 128 ms. The live Mocker sleepsdelay_msfor eachStartTransferinlib/llm/src/mocker/handoff.rs. The new text matches both. -
Rust on macOS.
cargo test --locked -p dynamo-mocker --all-targetspasses 290 of 290 at this head with nightly 87, and atmainwith nightly 86. -
CI at this head.
dynamo-runtime / test / parallel cuda13.0, amd64ran the three trace cases and passed them.test_installed_aisimulate_matches_the_declared_releasealso passed there, so that image has nightly 87.rust-tests (.)ran on a merge of this head with9f88a47f25and compiled nightly 87. It passed 3946dynamo-llmand 294dynamo-mockerunit tests.
dmitry-tokarev-nv
left a comment
There was a problem hiding this comment.
Approving at 88bca4d08f5b6a3b4186783b9a40c6c6458ce073.
The revert of the AIC renderer and the nightly 87 pin must land together, and together they work. At this head with nightly 87, the AISimulate DGD tests pass. Each half fails alone: this head with nightly 86 and main with nightly 87 both fail the three trace cases. The TensorRT-LLM trace DGD is byte-identical to the one from main with nightly 86, and it has no transfer buffer size. All 9 pins name nightly 87, and the crate checksum matches all three Cargo.lock files. The new link-sharing text in simulation-model.md matches the nightly 87 replay.
In CI at this head, the three trace cases pass, and rust-tests (.) passes the dynamo-llm and dynamo-mocker tests with nightly 87.
Open items: none.
…erator The vllm-trace ClusterEnv scenario forced dgdr_run.generator: direct, so it could pass while an ordinary trace Request failed to render its Candidate through the default AIC generator. The AIC renderer forwards the trace workload since #17474 and #17523, so drop the override and keep the scenario on the default path. The pinned AISimulate still rejects a candidate without an explicit block size (#17581), so the scenario takes the same TODO(#17581) block-size workaround as the static vllm scenario. The Candidate golden is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
Overview
This is a follow-up to #17474, in response to its review. With ai-dynamo/aisimulate#626, AISimulate's generator bridge lowers a trace workload without request lengths and rejects placeholder ones. The AIC DGD renderer therefore goes back to passing the workload, and the manifest AIC returns, through unchanged.
Note
This PR now pins AISimulate nightly 87 (
0.13.0.dev202610290000000087, Rust0.13.0-dev.202610290000000087). Nightly 87 is built from AISimulate03eadda3and contains ai-dynamo/aisimulate#626.The revert and the pin bump have to land together, in this PR:
mainpins nightly 86 (feat(planner): load local AISimulate execution profiles #17228), which was built before fix: lower trace workloads in the Sweeper generator bridge aisimulate#626. The revert on that pin breaks trace rendering again.mainsends. Any other PR that moves the pin past 86 failstest_installed_aic_renders_trace_workloads_like_synthetic_ones[trtllm|vllm|sglang]onmain's renderer, and needs this change.Key Changes
components/src/dynamo/aisimulate/output/dgd/renderers/aic/renderer.py: restore the renderer from before fix(aisimulate): render trace workloads through the AIC generator #17474, which passes the workload straight through. This drops the placeholder lengths and the scrub of--trtllm.cache_transceiver_config.max_tokens_in_buffer, and keeps the check that AIC returnedk8s_deploy.yaml.components/src/dynamo/aisimulate/tests/dgd/test_renderers.py:test_installed_aic_renders_trace_workloads_like_synthetic_onesnow expects the trace DGD to equal the synthetic one without the TensorRT-LLM transfer-buffer size. The test computes that expected DGD itself; the renderer no longer edits anything.pyproject.tomlbenchmarks/pyproject.tomlcontainer/deps/requirements.aisimulate.txtCargo.tomllib/bindings/python/Cargo.tomlCargo.lock,lib/bindings/python/Cargo.lock,lib/bindings/kvbm/Cargo.lock: only theaisimulate-coreversion and checksum change, throughcargo update -p aisimulate-core --precise. The checksum matches the crates.io index.docs/fern/pages/reference/components/planner-configuration.mdx.docs/fern/pages/cli/operations/simulation-with-dynosim/simulation-model.md: nightly 87 also contains feat: share P/D KV transfer links and offload bandwidth max-min fairly aisimulate#616. Offline P/D transfers now share each prefill rank's sending link and each decode rank's receiving link max-min fairly. The page said concurrent requests do not contend for a shared link; it now describes link sharing in offline prediction and notes that live Mocker workers still wait a fixed delay per transfer.mainatebad592bf0to pick up the nightly 86 pin before bumping it.Validation
These runs used the published nightly 87. A fresh virtual environment held the PyPI wheel and Dynamo bindings rebuilt against the crates.io crate (
maturin develop --release --features kv-indexer,slot-tracker,select-service,mm-routing,ais-forward-pass).-n 16over:components/src/dynamo/{aisimulate,planner,replay,profiler,router,mocker}/testslib/bindings/python/tests/test_ais_capacity.pylib/bindings/python/tests/replaytests/dependenciestest_profiler_protocol.py::test_materialize_dgd_inaccessible_model_path[True|False]. They assert oncaplogand do not call AISimulate. Both pass alone, and the file passes 103 of 103 when run by itself.test_aisimulate_consistency.py.components/src/dynamo/aisimulate/testspasses 102 of 102.cargo test --locked -p dynamo-mocker --all-targets: 294 passed.pre-merge.yml(offline_replay_benchonmooncake_trace_tiny.jsonl) completed.cargo clippy --locked --no-deps -p dynamo-mocker --all-targets -- -D warningspassed.lib/bindings/python,cargo test --locked --features ais-forward-pass: 85 passed.cargo test --locked -p dynamo-llm --lib mocker: 48 passed, includinglive_and_offline_handoff_surfaces_share_one_conformance_reportandno_bootstrap_prefill_delays_terminal_finish_once.17625dc8and03eadda3against Dynamo's callers.from_sweeper_candidatehas no Dynamo caller other than this renderer, and the profiler's generator paths always pass request lengths. perf: allocation-free grid-table queries aisimulate#627, fix: fix max_local_prefill_length not being printed out in disagg router log #628, fix: add DYNAMO_HOME env var to vLLM docker image #629 and build: Define UCX env var to use NVLink when available #631 are internal and bit-for-bit equivalent. fix: the SGLang MLA module collector recognises the ModelOpt mixed recipe aisimulate#614 changes only the collector, which is not shipped in the wheel.kv_transfer_bandwidthis set and transfers overlap on one rank, or when a ReplaySpec gives decode a lower bandwidth than prefill. Shared G2/G3 offload (cluster_shared) now redistributes unused pool bandwidth max-min fairly. The default (no bandwidth) is unchanged, and no Dynamo test asserts the affected timings. Results from planner-gym matches oroffline_replay_benchruns that set a transfer bandwidth can shift.main's placeholder-and-scrub renderer in 32 of 32 cases: TensorRT-LLM rc20/rc23, vLLM 0.20.1 and SGLang 0.5.9, each × agg/disagg × block size 32/64 ×context_lengthNone/10000. That check used nightly 82 with the fix: lower trace workloads in the Sweeper generator bridge aisimulate#626 generator overlaid; nightly 87'sgenerator/matches that source.docs_lint.py: passed on the changed files.Issues and Ongoing Work
Pull Request Checklist
/pr-checklistskill.🤖 Generated with Claude Code