Skip to content

feat(replay): replay DGDR trace Runs with common random numbers - #17733

Open
tedzhouhk wants to merge 1 commit into
hzhou/dgdr-trace-pvcfrom
hzhou/live-retune-1-crn
Open

tedzhouhk wants to merge 1 commit into
hzhou/dgdr-trace-pvcfrom
hzhou/live-retune-1-crn

Conversation

@tedzhouhk

@tedzhouhk tedzhouhk commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Note

Stacked PR, live retune (split from #17562). Merge order: #17483 → #17733 (this PR) → #17734 → #17735 → #17736 → #17562

This PR targets hzhou/dgdr-trace-pvc, the branch of #17483 (the PR below it), so its diff shows only this layer. #17562 was split into these layers for review. Together they carry #17562's original diff exactly, plus a 40-line replay check in #17734 that rejects executor: dgdr in offline replay.

Overview

Live planner retune (#17562) compares Candidates that different DGDR Runs of one window scored. That comparison only works if a Candidate's score depends on its own configuration and nothing else. This PR makes DynamoReplayRunner replay every trace workload with common random numbers (CRN): ordinal request ids and the canonical router seed. DynamoReplayRunner is the dynamo replay runner that AISimulate's Sweeper loads (entry point in pyproject.toml), and it is what a DGDR trace Run executes.

run_trace_replay already has the internal _deterministic option for this; offline replay retune uses it for its baseline and candidates. This PR only passes it from the Sweeper runner. The synthetic-workload path is unchanged.

This layer changes no file that #17483 touches. It sits on #17483 for merge order, because DGDR trace Runs (spec.workload.trace) come from #17483.

Key Changes

  • components/src/dynamo/replay/simulation.py: passes _deterministic=True to both run_trace_replay calls of DynamoReplayRunner (agg and disagg). run_synthetic_trace_replay has no such parameter and does not receive it.
  • components/src/dynamo/replay/tests/test_simulation_crn.py (new): replaces the replay entry points with fakes that bind their kwargs to the real signatures. It checks that the flag is set for agg and disagg with dynamo and mooncake trace workloads, and that synthetic replays never receive it.

Behavior note: this applies to every trace replay through the Sweeper's dynamo runner, including every DGDR trace Run, not only the Planner's. A Run's scores no longer depend on the other candidates or on the Run's parallelism.

Validation

Ran on this layer (e9ab6afc24) and compared with the same suites at the stack base 6e8087d359 (#17483's head, with main c6b055d4c7 merged in):

Check Result
replay/tests/test_simulation_crn.py 6 passed
Planner and replay suites (components/src/dynamo/planner/tests, components/src/dynamo/replay/tests, no xdist) 59 failed, 2137 passed, 2 skipped. At the base: 59 failed, 2131 passed, 2 skipped. The two sets of failing tests are identical; the 6 extra passes are the new tests.
pre-commit run --files on the 2 changed files All hooks pass, no files changed
CI mypy (the dynamo-pipeline.yml command, MYPYPATH=components/src:lib/bindings/python/src mypy --explicit-package-bases) on dynamo/planner and dynamo/replay 9 errors, the same 9 as at the base: missing yaml/pandas/nvtx stubs, plus existing arg-type errors in common/http/url_validator.py and planner/simulation/provider.py. None is new.

The 59 failures come from this host. Its prebuilt bindings lack conversation_affinity (#16854) and the ais-forward-pass feature, and it has no etcd binary. CI builds the bindings from source.

The development-cluster run in #17562 used a planner image with this change for its Run Jobs, on #17562's pre-split branch. Both windows of that run reached a decision (kept, applied). The executor allows a decision only when the CRN probe's score matches the grid evaluation of the same point within a relative error of 1e-9. This layer was not run on a cluster by itself.

Issues and Ongoing Work

Pull Request Checklist
  • I used Dynamo's /pr-checklist skill.

🤖 Generated with Claude Code

DynamoReplayRunner now replays every candidate of a trace sweep with
_deterministic=True: ordinal request ids and the canonical router seed.
Candidates of one trace then differ only by their configuration, so a
candidate's score does not depend on the other candidates, the Run or the
parallelism. Live planner retune compares candidates that different DGDR
Runs of one window scored on that basis. The synthetic-workload path is
unchanged.

First layer of the live retune stack split from #17562.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
@tedzhouhk
tedzhouhk requested a review from a team as a code owner October 30, 2026 23:42
@github-actions github-actions Bot added the feat label Oct 30, 2026
tedzhouhk added a commit that referenced this pull request Oct 30, 2026
Stacks this PR on #17736. The library layers of live retune now come from
#17733 (CRN replay), #17734 (configuration and premises), #17735 (window
cut and reconciler) and #17736 (DGDR executor), so this PR's diff against
#17736 is the supervisor, state, actuator, metrics, the Planner wiring,
Helm RBAC, docs and the end-to-end tests. #17734 also adds a replay check
that rejects executor 'dgdr'.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

✅ Dynamo PR CI passed — run 41146042861 (attempt 1) on e9ab6afc24

Gate checks: ✅ backend-status-check · ✅ deploy-status-check · ✅ dynamo-status-check

Posted automatically by Devin for run 41146042861. Updated on every full-CI run of this PR.

@jthomson04 jthomson04 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at e9ab6af. The change is fine: the canonical seed is the same for every candidate and window, no user seed is overridden, and the offline-only guard can't trip. Two nits inline.

{"trace_paths": ["a.jsonl", "b.jsonl"], "trace_format": "mooncake"},
],
)
def test_trace_replays_are_deterministic(monkeypatch, mode, workload):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

140 lines of tests for a 9-line change. test_simulation.py::test_trace_runner_preserves_current_replay_arguments already captures these kwargs; add assert seen["_deterministic"] is True and one disagg row there and drop this file. The synthetic test checks a function this PR doesn't touch.

# embedded value instead of imposing the synthetic-workload default.
if trace_format not in {"weka", "dynamo"} and trace_block_size is None:
trace_block_size = self.trace_block_size
# Common random numbers: every candidate of a trace sweep replays the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cut this to the invariant: trace replays use ordinal ids and the canonical router seed. Naming the live-retune consumer here will go stale. replay/api.py:100 still says _deterministic is internal to retune sweeps, which this PR makes untrue.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants