Skip to content

[Profiler] Export torch profiler trace off the worker's main thread - #51816

Open
elvircrn wants to merge 2 commits into
vllm-project:mainfrom
elvircrn:profiler-async-stop-offload
Open

elvircrn wants to merge 2 commits into
vllm-project:mainfrom
elvircrn:profiler-async-stop-offload

Conversation

@elvircrn

@elvircrn elvircrn commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Export trace on a background thread instead of inline in on_trace_ready, since Kineto has already stopped collecting by then. Verified against a real opt-125m server: stop_profile() 22.6s -> 3.5s, no correctness regressions.

(Earlier revision also made Executor.profile() dispatch non-blocking via collective_rpc(non_block=True). Dropped it — the returned Future only resolves if something else calls .result() on it, which nothing does for this call, so it hung under real multiprocessing. Worker-side fix alone already solves the reported slowdown.)

Repro

from vllm import LLM, SamplingParams
import time

llm = LLM(
    model="facebook/opt-125m",
    enforce_eager=True,
    gpu_memory_utilization=0.2,
    profiler_config={"profiler": "torch", "torch_profiler_dir": "/tmp/trace"},
)
llm.start_profile()
llm.generate(["The quick brown fox"], SamplingParams(max_tokens=32))

t0 = time.perf_counter()
llm.stop_profile()
print(f"stop_profile(): {time.perf_counter() - t0:.1f}s")

Measured on CPU, opt-125m, gzip'd trace:

  • main: stop_profile() = 22.6s
  • this PR: stop_profile() = 3.5s

Test plan

  • New CPU-only tests in tests/v1/worker/test_gpu_profiler.py
  • Verified against real facebook/opt-125m on CPU: start_profile -> generate -> stop_profile -> generate, no hang, real trace produced

Export trace on a background thread and dispatch the worker RPC with non_block=True, so stop_profile no longer stalls the step loop.
Signed-off-by: Elvir Crncevic <elvircrn@gmail.com>
@elvircrn
elvircrn requested a review from njhill as a code owner August 11, 2026 12:19

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@elvircrn
elvircrn marked this pull request as draft August 11, 2026 12:19
Executor.profile()/EngineCore.profile()'s non_block=True path returns a
Future that only resolves if something else calls .result() on
MultiprocExecutor's shared FutureWrapper queue -- nothing does that for a
one-off utility call, so it hangs forever in real multi-process runs.
Verified this hang against a live opt-125m server; reverting it here.

The worker-side fix (backgrounding trace export in wrapper.py) already
covers the original problem: verified against the same real model,
stop_profile() dropped from 22.6s to 3.5s with no hang.
Signed-off-by: Elvir Crncevic <elvircrn@gmail.com>
@elvircrn elvircrn changed the title [Profiler] Make /stop_profile non-blocking [Profiler] Export torch profiler trace off the worker's main thread Aug 11, 2026
@elvircrn
elvircrn marked this pull request as ready for review August 11, 2026 14:24
@mergify

mergify Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @elvircrn.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

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.

1 participant