Fix PyExecutor FPM iteration timing - #14922
Conversation
Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
acab472 to
163eb86
Compare
📝 WalkthroughWalkthroughThis PR extends iteration statistics collection to capture GPU forward timing via CUDA events and snapshot per-iteration scheduler state before request mutation. The metric propagates through ADP fanout and direct serialization paths across all executor modes (pipeline-parallelism, non-PP, overlap), with corresponding test updates validating the new timing field and iter_states-driven stat override behavior. ChangesGPU Forward Timing Metrics in Iteration Statistics
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
/bot run |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
tests/unittest/pyexecutor/test_iter_stats_populate.py (1)
550-576: Coverage assessment: sufficient for this PR’s iter-state/timing regressions.
tests/unittest/pyexecutor/test_iter_stats_populate.pynow covers both snapshot-sourced counters (num_ctx_tokens,num_gen_kv_tokens) and ADP fanout timing-field propagation. For this PR objective, coverage is sufficient.
Follow-up outside this PR (optional): add one negative-path test where timing fields are absent end-to-end in fanout output.Also applies to: 693-720
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unittest/pyexecutor/test_iter_stats_populate.py` around lines 550 - 576, Add a negative-path unit test in tests/unittest/pyexecutor/test_iter_stats_populate.py that verifies ADP fanout timing fields are absent when not present in the inputs: use _invoke_update_iter_stats with a _StubScheduledBatch (e.g., gen_reqs or context_reqs as appropriate) and provide iter_states that omit timing fields, then inspect the returned stats.inflight_batching_stats (or the fanout output) and assert the timing fields are not present or are None/zero as expected; place the test alongside test_num_ctx_tokens_... and test_num_gen_kv_tokens_... and name it to reflect the "timing fields absent" negative path.tests/unittest/executor/test_stats_serializer.py (1)
216-240: Coverage assessment: sufficient for serializer tuple-shape evolution.
tests/unittest/executor/test_stats_serializer.pynow explicitly validates the 8-tuple contract (hostStepTimeMS, omittedprevDeviceStepTimeMSonNone,schedulerMode,gpuForwardTimeMS). For this PR scope, coverage in this file is sufficient.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unittest/executor/test_stats_serializer.py` around lines 216 - 240, The test `test_serializer_8_tuple_emits_new_timing_and_scheduler_mode` already covers the new 8-tuple serializer contract for BaseWorker._stats_serializer by asserting hostStepTimeMS == 12.5, that prevDeviceStepTimeMS is omitted when None, schedulerMode == "overlap", and gpuForwardTimeMS == 4.25; no code changes are required—keep the existing test as-is and ensure BaseWorker._stats_serializer continues to produce the documented 8-tuple JSON output.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tensorrt_llm/_torch/pyexecutor/py_executor.py`:
- Around line 3022-3033: In the branch where self.enable_iter_perf_stats is true
but sample_state is None, ensure any timing events borrowed from
_iter_timing_event_pool are returned to the pool instead of being leaked;
specifically, when skipping the call to _process_iter_stats (and after a
_forward_step() that may have returned None), release/return
gpu_forward_start_event, gpu_forward_end_event and any entries in
gpu_forward_events_from_iter_pool back into _iter_timing_event_pool (or call the
pool's release method) so borrowed CUDA events are not leaked.
---
Nitpick comments:
In `@tests/unittest/executor/test_stats_serializer.py`:
- Around line 216-240: The test
`test_serializer_8_tuple_emits_new_timing_and_scheduler_mode` already covers the
new 8-tuple serializer contract for BaseWorker._stats_serializer by asserting
hostStepTimeMS == 12.5, that prevDeviceStepTimeMS is omitted when None,
schedulerMode == "overlap", and gpuForwardTimeMS == 4.25; no code changes are
required—keep the existing test as-is and ensure BaseWorker._stats_serializer
continues to produce the documented 8-tuple JSON output.
In `@tests/unittest/pyexecutor/test_iter_stats_populate.py`:
- Around line 550-576: Add a negative-path unit test in
tests/unittest/pyexecutor/test_iter_stats_populate.py that verifies ADP fanout
timing fields are absent when not present in the inputs: use
_invoke_update_iter_stats with a _StubScheduledBatch (e.g., gen_reqs or
context_reqs as appropriate) and provide iter_states that omit timing fields,
then inspect the returned stats.inflight_batching_stats (or the fanout output)
and assert the timing fields are not present or are None/zero as expected; place
the test alongside test_num_ctx_tokens_... and test_num_gen_kv_tokens_... and
name it to reflect the "timing fields absent" negative path.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: cf2d0457-0914-4c9e-a8dc-71c25195f112
📒 Files selected for processing (5)
tensorrt_llm/_torch/pyexecutor/adp_iter_stats.pytensorrt_llm/_torch/pyexecutor/py_executor.pytensorrt_llm/executor/base_worker.pytests/unittest/executor/test_stats_serializer.pytests/unittest/pyexecutor/test_iter_stats_populate.py
Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
Hi @tedzhouhk, thanks for the contribution! In the future, it'd still be better to run new tests locally first, as it'll take TRTLLM's CI quite a while to get to the new tests which might delay time-sensitive MRs. For tensorrt_llm.bindings, it'll need to compile the TRTLLM source following https://nvidia.github.io/TensorRT-LLM/installation/build-from-source.html#build-from-source. |
Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
|
/bot run |
1 similar comment
|
/bot run |
|
PR_Github #52450 [ run ] triggered by Bot. Commit: |
|
PR_Github #52450 [ run ] completed with state
|
Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
e5f9d41 to
00ec987
Compare
|
/bot run |
|
PR_Github #52453 [ run ] triggered by Bot. Commit: |
|
PR_Github #52453 [ run ] completed with state
|
|
/bot run |
|
PR_Github #52819 [ run ] triggered by Bot. Commit: |
|
PR_Github #52819 [ run ] completed with state
|
|
/bot run |
|
PR_Github #53126 [ run ] triggered by Bot. Commit: |
|
PR_Github #53126 [ run ] completed with state |
Summary
gpuForwardTimeMSfor PyExecutor iteration stats using CUDA events around the batch_forward_step.inflightBatchingStatsstays matched to the exported iteration.PerfMetricsManagerprovides pooled events, this code reuses those instead.iter_statessnapshots are actually passed into_update_iter_stats.Validation
python -m py_compile tensorrt_llm/_torch/pyexecutor/py_executor.py tests/unittest/pyexecutor/test_iter_stats_populate.py tensorrt_llm/_torch/pyexecutor/adp_iter_stats.py tensorrt_llm/executor/base_worker.py29 passed in 0.11sQwen/Qwen3-0.6B, FPM enabled:aiperfconcurrency=50, ISL=5000, OSL=500, requests=200gpuForwardTimeMSwall-time p50=40.8 ms, p95=71.7 ms, max=159.2 msTRT-LLM pytest was not runnable in my local checkout because the source tree lacks generated
tensorrt_llm.bindingsand the available TRT-LLM venv does not includepytest; the modified files were syntax-checked instead.Summary by CodeRabbit
New Features
Bug Fixes
Tests