Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/codeowners/areas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ shared:
owners: [replay, mocker, maintainers]
- glob: .claude/skills/aisimulate-replay-performance
owners: [replay, mocker, maintainers]
- glob: python/aisimulate/tools/simulation_perf_gate/
owners: [replay, forward-pass-engine, infra, maintainers]
- glob: pages/
owners: [forward-pass-engine, infra, maintainers]
- glob: tests/fpm_accuracy/
Expand Down
406 changes: 406 additions & 0 deletions .github/workflows/simulation-performance.yml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@
/python/aisimulate/src/aisimulate/cli_args.py @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/aisimulate-sweeper-codeowners @ai-dynamo/access-aisimulate-maintain
/.agents/skills/aisimulate-replay-performance/ @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/aisimulate-mocker-codeowners @ai-dynamo/access-aisimulate-maintain
/python/aisimulate/src/aisimulate/resources.py @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/aisimulate-sweeper-codeowners @ai-dynamo/access-aisimulate-maintain
/python/aisimulate/tools/simulation_perf_gate/ @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/aisimulate-forward-pass-engine-codeowners @ai-dynamo/aisimulate-infra-codeowners @ai-dynamo/access-aisimulate-maintain
/python/aisimulate/src/aisimulate/supervision.py @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/aisimulate-sweeper-codeowners @ai-dynamo/access-aisimulate-maintain
/python/aisimulate/.github/workflows/codeowners.yml @ai-dynamo/aisimulate-infra-codeowners @ai-dynamo/access-aisimulate-maintain
/python/aisimulate/src/aisimulate/resource_worker.py @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/aisimulate-sweeper-codeowners @ai-dynamo/access-aisimulate-maintain
Expand Down
17 changes: 17 additions & 0 deletions THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -1081,3 +1081,20 @@ Licensed under Apache-2.0;
the license is included at the repository root as `LICENSE` and in the Python
distribution. Upstream license:
https://github.com/vllm-project/vllm/blob/a474da28131f61684849b31e29af0eebaaedc383/LICENSE

## SemiAnalysis AgentX simulation-performance fixture

`python/aisimulate/tools/simulation_perf_gate/fixtures/agentx.jsonl` is derived
from `traces.jsonl` in the SemiAnalysis dataset
https://huggingface.co/datasets/semianalysisai/cc-traces-weka-062126-256k/tree/8fecd2fc56694469f758f0afbbb6335ad3043740
at revision `8fecd2fc56694469f758f0afbbb6335ad3043740`.
The original dataset card is preserved as `fixtures/DATASET_CARD.md`.

Upstream authors: SemiAnalysis. The upstream card supplies no separate
copyright or NOTICE statement. License: Apache License 2.0, declared in the
pinned dataset card and reproduced in `fixtures/LICENSE`.

Modified by NVIDIA: selected the complete play
`002001296e8a8c38ad9d7cc436d691afc602` and normalized JSON whitespace, without
changing request values, dependencies, hashes, or timestamps. See the adjacent
fixture README for the source, counts, and content checksum.
30 changes: 22 additions & 8 deletions crates/core/src/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ use crate::engine::{
use crate::perfmodel::engine::{Engine as PerfEngine, RuntimeConfig};
use crate::replay::{
POWER_DATA_COVERAGE_THRESHOLD, ReplayArtifactKvEventVisibility, ReplayArtifacts,
ReplayEngineConfig, ReplayEngineFactory, ReplayOperationPowerDiagnostics,
ReplayPhasePowerDiagnostics, ReplayPowerDiagnostics, ReplayRoleConfig, ReplayRuntimeInput,
ReplaySpec, ReplayTopology, Replayer, TracePowerStats,
ReplayCaptureOptions, ReplayDeterminism, ReplayEngineConfig, ReplayEngineFactory,
ReplayOperationPowerDiagnostics, ReplayPhasePowerDiagnostics, ReplayPowerDiagnostics,
ReplayRoleConfig, ReplayRuntimeInput, ReplaySpec, ReplayTopology, Replayer, TracePowerStats,
loadgen::{
AgenticSnapshotOptions, ArrivalSpec, DelaySpec, DynamoRequestTrace, LengthSpec,
SyntheticTraceSpec, Trace, ValidatedAgenticGraph, WekaImportOptions,
Expand All @@ -43,6 +43,8 @@ enum ExecutionPayload {
traffic: Option<Box<RuntimeTraffic>>,
#[serde(default)]
capture_performance_diagnostics: bool,
#[serde(default)]
determinism: ReplayDeterminism,
Comment thread
jthomson04 marked this conversation as resolved.
Resolved
},
Legacy(ReplaySpec),
}
Expand Down Expand Up @@ -1663,11 +1665,16 @@ fn run_with_input(
factory: ReplayEngineFactory,
input: Option<ReplayRuntimeInput>,
capture_artifacts: bool,
determinism: ReplayDeterminism,
) -> crate::replay::ReplayResult<(crate::replay::ReplayReport, Option<ReplayArtifacts>)> {
let replayer = match input {
Some(input) => Replayer::new(spec, factory)?.with_runtime_input(input),
None => Replayer::new(spec, factory)?,
};
}
.with_capture_options(ReplayCaptureOptions {
determinism,
..ReplayCaptureOptions::default()
});
if capture_artifacts {
let (report, artifacts) =
replayer.run_with_artifacts(ReplayArtifactKvEventVisibility::Native)?;
Expand Down Expand Up @@ -2142,14 +2149,20 @@ fn replay_fpm_coverage(
}

fn execute_json(payload: &str, capture_artifacts: bool) -> Result<String> {
let (mut spec, mut traffic, capture_performance_diagnostics) =
let (mut spec, mut traffic, capture_performance_diagnostics, determinism) =
match serde_json::from_str(payload).context("invalid AISimulate execution ReplaySpec")? {
ExecutionPayload::Configured {
spec,
traffic,
capture_performance_diagnostics,
} => (spec, traffic.map(|t| *t), capture_performance_diagnostics),
ExecutionPayload::Legacy(spec) => (spec, None, false),
determinism,
} => (
spec,
traffic.map(|t| *t),
capture_performance_diagnostics,
determinism,
),
ExecutionPayload::Legacy(spec) => (spec, None, false, ReplayDeterminism::default()),
};
let agentic_input = traffic.as_ref().and_then(|traffic| {
traffic
Expand Down Expand Up @@ -2238,7 +2251,7 @@ fn execute_json(payload: &str, capture_artifacts: bool) -> Result<String> {
ReplayEngineFactory::new,
ReplayEngineFactory::with_timing_model,
);
run_with_input(spec, factory, input, capture_artifacts)
run_with_input(spec, factory, input, capture_artifacts, determinism)
.map(|(report, artifacts)| (report, artifacts, resolved_basis))
}
ReplayTopology::Disaggregated { .. } => {
Expand Down Expand Up @@ -2364,6 +2377,7 @@ fn execute_json(payload: &str, capture_artifacts: bool) -> Result<String> {
),
input,
capture_artifacts,
determinism,
)
.map(|(report, artifacts)| (report, artifacts, resolved_basis))
}
Expand Down
17 changes: 17 additions & 0 deletions python/aisimulate/THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -1081,3 +1081,20 @@ Licensed under Apache-2.0;
the license is included at the repository root as `LICENSE` and in the Python
distribution. Upstream license:
https://github.com/vllm-project/vllm/blob/a474da28131f61684849b31e29af0eebaaedc383/LICENSE

## SemiAnalysis AgentX simulation-performance fixture

`python/aisimulate/tools/simulation_perf_gate/fixtures/agentx.jsonl` is derived
from `traces.jsonl` in the SemiAnalysis dataset
https://huggingface.co/datasets/semianalysisai/cc-traces-weka-062126-256k/tree/8fecd2fc56694469f758f0afbbb6335ad3043740
at revision `8fecd2fc56694469f758f0afbbb6335ad3043740`.
The original dataset card is preserved as `fixtures/DATASET_CARD.md`.

Upstream authors: SemiAnalysis. The upstream card supplies no separate
copyright or NOTICE statement. License: Apache License 2.0, declared in the
pinned dataset card and reproduced in `fixtures/LICENSE`.

Modified by NVIDIA: selected the complete play
`002001296e8a8c38ad9d7cc436d691afc602` and normalized JSON whitespace, without
changing request values, dependencies, hashes, or timestamps. See the adjacent
fixture README for the source, counts, and content checksum.
15 changes: 14 additions & 1 deletion python/aisimulate/src/aisimulate/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from collections.abc import Mapping
from dataclasses import dataclass, field, replace
from numbers import Real
from typing import Any, Protocol, runtime_checkable
from typing import Any, Literal, Protocol, runtime_checkable

import numpy as np

Expand Down Expand Up @@ -373,6 +373,7 @@ class EngineReplayRunnerFactory:
"""

trace_block_size: int = 512
determinism: Literal["random", "canonical_v1"] = field(default="random", kw_only=True)
Comment thread
jthomson04 marked this conversation as resolved.
Resolved
runtime: EngineReplayRuntime | None = field(default=None, repr=False, compare=False)
afd_companion_model: AFDCompanionPerformanceModel | None = field(
default=None,
Expand Down Expand Up @@ -414,6 +415,7 @@ def create(self, worker_id: int) -> EngineReplayRunner:
worker_id=worker_id,
capabilities=self.capabilities(),
trace_block_size=self.trace_block_size,
determinism=self.determinism,
runtime=self.runtime,
afd_companion_model=self.afd_companion_model,
)
Expand All @@ -426,6 +428,7 @@ class EngineReplayRunner:
worker_id: int
capabilities: RunnerCapabilities
trace_block_size: int = 512
determinism: Literal["random", "canonical_v1"] = field(default="random", kw_only=True)
runtime: EngineReplayRuntime | None = None
afd_companion_model: AFDCompanionPerformanceModel | None = None

Expand Down Expand Up @@ -460,6 +463,12 @@ def run(
output_requirements: ReplayOutputRequirements | None = None,
) -> ReplayReport:
output_requirements = output_requirements or ReplayOutputRequirements()
if self.determinism not in {"random", "canonical_v1"}:
raise ValueError(f"unsupported replay determinism: {self.determinism!r}")
if self.determinism != "random" and (
spec.backend_deployment.deployment_mode in {"afd", "afd+pd"} or spec.backend_deployment.encoder is not None
):
raise InvalidRunnerError("canonical determinism requires native text replay")
if output_requirements.capture_telemetry:
raise InvalidRunnerError("EngineReplayRunner's JSON runtime does not yet expose replay telemetry")
if spec.workload.get("source_type") is not None and "length_sampler" in spec.workload:
Expand Down Expand Up @@ -540,6 +549,10 @@ def run(
if "spec" not in execution_spec:
execution_spec = {"spec": execution_spec}
execution_spec["capture_performance_diagnostics"] = True
if self.determinism != "random":
if "spec" not in execution_spec:
execution_spec = {"spec": execution_spec}
execution_spec["determinism"] = self.determinism
execution_spec_json = json.dumps(
execution_spec,
allow_nan=False,
Expand Down
Loading
Loading