Перейти к основному содержимому

For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://docs.nvidia.com/dynamo/llms.txt. For full content including API reference and SDK examples, see https://docs.nvidia.com/dynamo/llms-full.txt.

Запуски DynoSim

A DynoSim run оценивает одну рабочую нагрузку на одной смоделированной конфигурации Dynamo. Текущая CLI-команда — python -m dynamo.replay, которая выводит сводную таблицу в стиле AIPerf, записывает полный JSON-отчёт на диск и напрямую поддерживает offline|online, round_robin|kv_router, arrival_speedup_ratio, закрытую конкуррентность и входные данные для синтетических нагрузок.

Команда пока сохраняет существующее имя replay. В документации термин "DynoSim run" обозначает продуктовую сущность: одна рабочая нагрузка, одна смоделированная конфигурация, один отчёт.

В отличие от обычного использования dynamo.mocker, в offline-режиме не запускаются workers, не регистрируются endpoints и не требуются NATS, etcd или frontend. Online-режим, наоборот, проходит по живому runtime-пути mock-worker.

Используйте запуски DynoSim, когда нужно:

  • сравнить поведение scheduler по сохранённому trace
  • сравнить тайминги и поведение cache между конфигурациями mocker
  • проверить логику симуляции в CI без поднятия распределённого стека

Обзор Harness

Harness запуска DynoSim подключает load driver (файл trace или генератор синтетической нагрузки) к одной или нескольким симуляциям engine mocker и передаёт тайминги запросов и токенов в trace collector.

flowchart LR
LD[Load Driver] --> H[DynoSim Harness]

H --> SES[Single Engine Simulation]
H --> MES[Multi Engine Simulation]

SES --> H
MES --> H

H --> TC[Trace Collector]

Load driver — это либо Mooncake-style JSONL trace (timestamps, ISL/OSL, hash_ids), либо синтетический генератор, параметризованный isl/osl/concurrency. Single-engine simulation (SES) — быстрый путь для num_workers == 1 с движком vLLM; multi-engine simulation (MES) покрывает агрегированные multi-worker запуски, disaggregated prefill/decode запуски и KV-router запуски. Trace collector формирует сводную таблицу в стиле AIPerf, JSON-отчёт и поля таймингов на уровне каждого запроса, которые используются в последующем анализе.

Каждая симуляция собирается из разного набора компонентов. SES напрямую управляет core движка (scheduler + моделирование forward-pass). MES объединяет несколько core движка с KV transfer/ offloading, KV routing и симуляцией planner поверх них:

flowchart TD
subgraph SEC[Single Engine Core]
subgraph SCH[Scheduler Modeling]
F[Fwd Pass Modeling]
end
end

KV[KV Transfer + Offloading Simulation]
KR[KV Router Simulation]
P[Planner Simulation]

SES[Single Engine Simulation]
MES[Multi Engine Simulation]

SES --> SEC

MES --> SEC
MES --> KV
MES --> KR
MES --> P

См. lib/mocker/src/replay/offline/README.md для подробностей о внутренних механизмах offline-harness (logical clock, event queue, worker model) и Live Simulation with Mocker для деталей engine core (scheduler, KV block manager).

Быстрый старт

Запустите offline-проверку DynoSim через отдельную CLI-команду:

python -m dynamo.replay /path/to/mooncake_trace.jsonl \
--num-workers 4 \
--replay-mode offline \
--router-mode round_robin \
--trace-block-size 512 \
--extra-engine-args '{"block_size":64}' \
--report-json /tmp/dynosim-report.json

Запустите синтетическую проверку DynoSim через ту же CLI-команду, когда нужны фиксированные формы запросов без файла trace:

python -m dynamo.replay \
--input-tokens 5000 \
--output-tokens 500 \
--request-count 1000 \
--arrival-interval-ms 1.0 \
--num-workers 1 \
--replay-mode offline \
--replay-concurrency 100 \
--extra-engine-args '{"block_size":512}' \
--report-json /tmp/dynosim-report.json

Запустите синтетическую нагрузку, когда нужна структура shared-prefix или multi-turn без файла trace:

python -m dynamo.replay \
--input-tokens 5000 \
--output-tokens 500 \
--request-count 200 \
--turns-per-session 3 \
--shared-prefix-ratio 0.5 \
--num-prefix-groups 8 \
--inter-turn-delay-ms 250 \
--replay-mode offline \
--replay-concurrency 32 \
--extra-engine-args '{"block_size":512}' \
--report-json /tmp/dynosim-report.json

python -m dynamo.replay выводит сводную таблицу в стиле AIPerf в stdout и записывает полный JSON-отчёт на диск.

Формат входных данных

Файл trace должен быть Mooncake-style JSONL. Каждая строка должна содержать:

  • timestamp or created_time
  • input_length or input_tokens
  • output_length or output_tokens
  • hash_ids

Пример:

{"timestamp": 0, "input_length": 6755, "output_length": 500, "hash_ids": [0, 1, 2, 3]}
{"timestamp": 0, "input_length": 4096, "output_length": 128, "hash_ids": [9, 10, 11, 12]}

Строки без session_id — это независимые запросы с timestamp. Используйте такой формат для wall-clock request traces, включая agent-converted traces, где параллельные вызовы LLM должны оставаться параллельными.

Запуски DynoSim также поддерживают multi-turn sessions. Используйте один и тот же session_id для всех turns в session. Multi-turn sessions работают в closed-loop: turn n+1 ждёт, пока завершится turn n, а затем дополнительно учитывает либо явный delay / delay_ms, либо delta timestamp, выведенную из последовательных строк в одной session.

Пример:

{"session_id":"session-a","timestamp":1000,"input_length":2048,"output_length":128,"hash_ids":[1,2,3,4]}
{"session_id":"session-a","delay_ms":50,"input_length":2560,"output_length":128,"hash_ids":[1,2,3,4,5]}
{"session_id":"session-b","timestamp":1010,"input_length":1024,"output_length":64,"hash_ids":[9,10]}
{"session_id":"session-b","timestamp":1060,"input_length":1536,"output_length":64,"hash_ids":[9,10,11]}

Вторая строка session-a ждёт завершения первого turn плюс 50 ms. Вторая строка session-b тоже ждёт завершения первого turn плюс выведенную delta timestamp 50 ms.

Agentic Mooncake

--trace-format agentic_mooncake симулирует dependencies на уровне запросов в дополнение к полям Mooncake request. Каждая строка должна содержать обычные поля Mooncake плюс стабильный request_id. Поля зависимостей необязательны.

{
"request_id": "root-2",
"session_id": "run-42:root",
"timestamp": 1000.0,
"input_length": 4096,
"output_length": 256,
"hash_ids": [0, 1, 2, 3],
"wait_for": ["child-1"],
"branches": ["child-1"],
"prefix_reset": false,
"delay": 10.0,
"tool_wait_ms": 2500.0
}

Строки без wait_for используют timestamp как время старта. Строки с зависимостями ждут завершения каждого указанного запроса, затем дополнительно ждут delay + tool_wait_ms перед dispatch. branches фиксирует дочерние запросы, порождённые этой строкой, а prefix_reset отмечает первую строку в trajectory.

Используйте agent_trace_to_mooncake --agentic, чтобы получить этот формат из Dynamo agent traces:

cargo run -p dynamo-bench --bin agent_trace_to_mooncake -- \
--agentic \
--input-path /tmp/dynamo-agent-trace.jsonl \
--output-file /tmp/dynamo-agent-trace.agentic-mooncake.jsonl

Запустите так:

python -m dynamo.replay /tmp/dynamo-agent-trace.agentic-mooncake.jsonl \
--trace-format agentic_mooncake \
--trace-block-size 128 \
--replay-mode offline \
--router-mode kv_router \
--num-workers 4 \
--extra-engine-args '{"block_size":128}' \
--report-json /tmp/agentic-dynosim-report.json

В DynoSim используются два разных понятия block-size для файлов trace:

  • --trace-block-size: how many tokens each hash_id in the dataset represents
  • engine block_size: the block size used by the simulated engine and router when they re-chunk the synthesized tokens into sequence hashes

Public Mooncake/toolagent traces используют 512 tokens на один hash_id, поэтому запуски DynoSim обычно должны использовать --trace-block-size 512. При этом engine block_size может быть и меньше, например live-настройка benchmark для vLLM использует block_size=64. Для engine_type=sglang DynoSim по-прежнему использует canonical block_size внутри; sglang.page_size принимается как compatibility alias и нормализуется в block_size перед стартом симуляции.

Поверхности DynoSim

python -m dynamo.replay

Отдельная CLI DynoSim поддерживает:

  • either a positional trace_file, or all of --input-tokens, --output-tokens, and --request-count
  • --replay-mode offline|online
  • --router-mode round_robin|kv_router
  • --num-workers
  • --num-prefill-workers
  • --num-decode-workers
  • --replay-concurrency
  • --arrival-interval-ms
  • --arrival-speedup-ratio
  • --trace-format mooncake|mooncake-delta|agentic_mooncake|applied_compute_agentic
  • --trace-block-size
  • --turns-per-session
  • --shared-prefix-ratio
  • --num-prefix-groups
  • --inter-turn-delay-ms
  • --extra-engine-args (JSON string)
  • --prefill-engine-args (JSON string)
  • --decode-engine-args (JSON string)
  • --router-config (JSON string)
  • --aic-backend
  • --aic-system
  • --aic-backend-version
  • --aic-tp-size
  • --aic-model-path
  • --aic-moe-tp-size
  • --aic-moe-ep-size
  • --aic-attention-dp-size
  • --report-json

Значения по умолчанию:

  • --replay-mode offline
  • --router-mode round_robin

Пример:

python -m dynamo.replay /path/to/mooncake_trace.jsonl \
--replay-mode online \
--router-mode kv_router \
--num-workers 4 \
--arrival-speedup-ratio 10 \
--trace-block-size 512 \
--extra-engine-args '{"block_size":64}' \
--router-config '{"router_queue_policy":"fcfs","router_temperature":0.0}' \
--report-json /tmp/dynosim-report.json

Симуляция SGLang использует ту же CLI-поверхность. Минимальный файл extra-engine-args может использовать либо block_size напрямую, либо compatibility alias sglang.page_size:

{
"engine_type": "sglang",
"num_gpu_blocks": 512,
"sglang": {
"page_size": 2
}
}

И --extra-engine-args, и --router-config принимают частичные JSON-объекты. Настройки движка такие как block_size, engine_type, dp_size, speedup_ratio и decode_speedup_ratio должны находиться в --extra-engine-args, а не в виде верхнеуровневых флагов DynoSim CLI. --trace-block-size отдельный и используется только для запусков с trace-файлом. Неуказанные поля получают те же значения по умолчанию, что и MockEngineArgs::default() и KvRouterConfig::default().

У DynoSim есть две независимые AIC-поверхности:

  • engine timing AIC via --extra-engine-args / staged engine JSON
  • router-side prompt-load AIC via top-level --aic-* flags together with router_prefill_load_model: "aic" in --router-config

Обе поверхности принимают поля MoE parallelism. Для Kimi-style TP-only MoE конфигураций синхронизируйте их, задав aic_moe_tp_size таким же, как aic_tp_size, а также aic_moe_ep_size=1 и aic_attention_dp_size=1.

Offline disaggregated simulation использует staged engine args вместо --extra-engine-args:

  • --prefill-engine-args для конфигурации prefill worker
  • --decode-engine-args для конфигурации decode worker
  • --num-prefill-workers и --num-decode-workers для размеров pool

Для offline disaggregated simulation staged JSON должен явно задавать worker_type:

  • --prefill-engine-args должен использовать worker_type: "prefill"
  • --decode-engine-args должен использовать worker_type: "decode"

Staged-конфигурации также должны использовать одинаковый engine block_size. --trace-block-size по-прежнему остаётся отдельным параметром ввода для trace-файла.

Синтетические нагрузки

Синтетический режим обходит загрузку trace и генерирует запросы в памяти с фиксированными длинами input/output и необязательным synthetic arrival spacing:

python -m dynamo.replay \
--input-tokens 5000 \
--output-tokens 500 \
--request-count 200 \
--arrival-interval-ms 0.5 \
--replay-mode offline \
--replay-concurrency 50 \
--extra-engine-args '{"block_size":512}'

Это полезно для parameter sweeps, где Mooncake-style prefix structure не нужна.

Когда --turns-per-session > 1, --request-count интерпретируется как число sessions, а не общее число emitted turns. Итоговое количество завершённых запросов становится:

  • request_count * turns_per_session

Параметры synthetic workload:

  • --turns-per-session: число turns в каждой synthetic session
  • --shared-prefix-ratio: доля prompt blocks, shared внутри prefix group
  • --num-prefix-groups: число shared-prefix groups; 0 отключает grouping
  • --inter-turn-delay-ms: постоянная задержка, применяемая после каждого завершённого turn перед тем, как следующий turn в той же session станет eligible

Режимы

Запуски с фиксированным расписанием

Режим trace по умолчанию сохраняет timestamps из trace и симулирует arrivals согласно этим timestamp:

python -m dynamo.replay /path/to/mooncake_trace.jsonl \
--replay-mode offline \
--num-workers 4 \
--trace-block-size 512 \
--extra-engine-args '{"block_size":64}'

Это правильный режим, когда нужна детерминированная симуляция исходного шаблона arrival запросов. Для wall-clock request traces не указывайте session_id, чтобы каждая строка планировалась независимо по timestamp. Строки с общим session_id симулируются как closed-loop session, где каждый следующий turn ждёт завершения предыдущего.

Закрытая конкуррентность

Используйте --replay-concurrency, чтобы игнорировать timing arrival первого turn и удерживать фиксированное число запросов in flight:

python -m dynamo.replay /path/to/mooncake_trace.jsonl \
--replay-mode offline \
--num-workers 4 \
--replay-concurrency 16

Этот режим полезен, когда нужно сравнить поведение scheduler при фиксированной предлагаемой concurrency, а не по исходному расписанию trace.

Для multi-turn sessions режим concurrency по-прежнему соблюдает порядок session и задержки между turns:

  • timestamps первого turn игнорируются
  • turn n+1 не становится eligible, пока не завершится turn n
  • delay / delay_ms / synthetic --inter-turn-delay-ms по-прежнему применяются после завершения
  • TTFT измеряется от фактического dispatch под cap, а не от проигнорированного trace timestamp

Online-режим

Online-режим запускает mock workers и прогоняет trace через live runtime path. Это полезно, когда нужно включить live request dispatch, live обработку output и ту же async KV-event propagation model, которая используется текущей router integration.

python -m dynamo.replay /path/to/mooncake_trace.jsonl \
--replay-mode online \
--router-mode kv_router \
--num-workers 4 \
--arrival-speedup-ratio 10 \
--trace-block-size 512 \
--extra-engine-args '{"block_size":64}'

Ускорение прибытия

Используйте --arrival-speedup-ratio, чтобы сжать или растянуть процесс arrival trace без изменения mocker compute model. Более большие значения делают arrivals раньше относительно исходного trace.

python -m dynamo.replay /path/to/mooncake_trace.jsonl \
--replay-mode offline \
--num-workers 4 \
--arrival-speedup-ratio 5 \
--trace-block-size 512 \
--extra-engine-args '{"block_size":64}'

Режимы Router

DynoSim сейчас поддерживает:

  • round_robin
  • kv_router

kv_router использует общий local scheduler и in-process KV indexer. Настройка router policy передаётся через --router-config, а не через отдельный верхнеуровневый CLI-флаг. В offline-режиме:

  • kv_router поддерживается только при num_workers > 1
  • router queueing включён и использует simulation time, а не wall-clock time
  • KV visibility немного задерживается относительно событий жизненного цикла запроса
  • queue admission управляется рёбрами жизненного цикла router (add_request, mark_prefill_completed и free)
  • transient in-pass prefill occupancy по-прежнему аппроксимируется на уровне router, а не моделируется точно
  • when router_prefill_load_model is "aic", DynoSim predicts one expected prefill duration per admitted request and decays only the oldest active prefill request on each worker

Чтобы вручную сравнить queue policies, оставьте тот же trace и engine args, а меняйте только router_queue_policy внутри --router-config:

python -m dynamo.replay /path/to/mooncake_trace.jsonl \
--replay-mode offline \
--router-mode kv_router \
--num-workers 4 \
--trace-block-size 512 \
--extra-engine-args '{"block_size":64}' \
--router-config '{"router_queue_policy":"fcfs"}'

python -m dynamo.replay /path/to/mooncake_trace.jsonl \
--replay-mode offline \
--router-mode kv_router \
--num-workers 4 \
--trace-block-size 512 \
--extra-engine-args '{"block_size":64}' \
--router-config '{"router_queue_policy":"lcfs"}'

lcfs намеренно является более слабой сравнительной policy при saturation; используйте его для экспериментов, а не как ожидаемый production default.

Чтобы включить router-side AIC prefill-load modeling во время симуляции:

python -m dynamo.replay /path/to/mooncake_trace.jsonl \
--replay-mode offline \
--router-mode kv_router \
--num-workers 4 \
--trace-block-size 512 \
--extra-engine-args '{"block_size":64}' \
--router-config '{"router_track_prefill_tokens":true,"router_prefill_load_model":"aic"}' \
--aic-backend vllm \
--aic-system h200_sxm \
--aic-model-path nvidia/Llama-3.1-8B-Instruct-FP8 \
--aic-tp-size 1

Для offline disaggregated simulation поддерживаются те же верхнеуровневые флаги --aic-*, но оценщик применяется только к router на prefill-stage.

Для MoE-моделей, которым требуется AIC MoE parallelism, добавьте соответствующие верхнеуровневые router AIC-флаги, например:

--aic-tp-size 2 \
--aic-moe-tp-size 2 \
--aic-moe-ep-size 1 \
--aic-attention-dp-size 1

Вывод

Отчёт содержит:

  • request counts
  • input and output token totals
  • virtual duration and wall-clock runtime
  • request and token throughput
  • prefix cache reuse ratio
  • TTFT, TTST, TPOT, ITL, and end-to-end latency summaries
  • output-token-throughput-per-user summaries

Отдельная CLI DynoSim возвращает ту же схему отчёта, что и Python APIs dynamo.replay.run_trace_replay(...) and dynamo.replay.run_synthetic_trace_replay(...).

Если --report-json не указан, python -m dynamo.replay записывает в текущий рабочий каталог файл dynamo_replay_report_*.json с timestamp в имени.

Ограничения

Общие ограничения:

  • extra_engine_args.engine_type должен быть vllm или sglang
  • aggregated simulation требует существующий путь для aggregated args
  • disaggregated simulation требует и prefill_engine_args, и decode_engine_args
  • disaggregated simulation требует router_mode=kv_router
  • dp_size должен быть 1
  • disaggregated simulation требует совпадающий block_size в prefill_engine_args и decode_engine_args

Дополнительные ограничения для offline:

  • offline kv_router требует num_workers > 1
  • single-worker offline mode по-прежнему остаётся отдельным fast path для vllm, но теперь поддерживает и flat request runs, и workload-driven multi-turn runs
  • sglang по-прежнему проходит через общий multi-worker runtime даже при num_workers=1
  • offline disaggregated simulation — это отдельный двухстадийный runtime с пулами workers для prefill и decode

Дополнительные ограничения для online:

  • current live simulation path также ограничен aggregated workers

Если нарушить эти ограничения, DynoSim немедленно завершится с validation error.

Практические замечания

  • python -m dynamo.replay требует ровно одного из вариантов: либо trace file, либо все три флага --input-tokens, --output-tokens и --request-count
  • --replay-concurrency работает и с trace-file, и с synthetic workloads
  • регуляторы скорости compute у mocker, такие как speedup_ratio, по-прежнему влияют на simulated timing, если переданы через engine-args JSON для выбранного режима
  • --arrival-speedup-ratio влияет на trace timestamps, а не на worker compute speed
  • --trace-block-size влияет только на то, как hash_ids из trace разворачиваются в tokens
  • --arrival-interval-ms применяется только к synthetic workloads
  • --turns-per-session, --shared-prefix-ratio, --num-prefix-groups и --inter-turn-delay-ms применяются только к synthetic workloads
  • --extra-engine-args, --prefill-engine-args, --decode-engine-args и --router-config в standalone DynoSim CLI являются JSON-строками
  • верхнеуровневые флаги --aic-* используются только для router-side prompt-load modeling; engine timing AIC по-прежнему должен находиться в engine-args JSON
  • offline mode не требует setup для planner runtime, регистрации router или внешнего event transport
  • workloads на основе trace-файлов могут использовать разные значения --trace-block-size и engine block_size
  • Mooncake/toolagent traces обычно используют --trace-block-size 512, тогда как engine block_size часто остаётся 64

Когда использовать это вместо AIPerf

Используйте offline DynoSim, когда:

  • нужна быстрая симуляция только scheduler
  • нужен детерминированный CI coverage поведения симуляции
  • не требуется HTTP serving, поведение frontend или сетевые эффекты

Используйте Dynamo Benchmarking, когда:

  • нужен end-to-end benchmarking против live endpoint
  • требуется поведение frontend, transport или cluster-level
  • нужны AIPerf dashboards и metrics, ориентированные на endpoint