Skip to content

The LTX-2.5 denoise loop captures no CUDA graph, and cannot until it runs on the device at all #1164

Description

@localai-bot

Our diffusion path captures no CUDA graphs at all: grep for capture across
src/vllm/model_executor/models/ltx2*.cpp returns nothing. SGLang measured large
end-to-end wins from graphing exactly this shape. This issue records the candidate and
why it cannot be scoped yet.

Why the candidate looked strong

A denoise loop is the ideal capture target: fixed shapes, tens of identical iterations,
one host dispatch sequence repeated. SGLang enabled BCG on this shape after our pin and
measured:

  • LTX-2 two-stage, H200, e2e 10.75 s to 6.90 s (1.56x)d4be483efb
  • SANA 1024px e2e -26%, bit-exact — 6c7498113f
  • SANA denoise 0.73 s to 0.457 s from auto-capturing the default warmup
    resolution — 56ef810cad
  • Z-Image single-GPU BCG made bit-exact vs eager — f5f0c3ee7a

Discount the magnitude hard: their win is mostly PyTorch host tax per denoise step,
which our C++ loop does not pay. The shape is still right.

Why it is blocked

The premise a denoise-loop graph needs is a denoise loop that runs on the device.
Ours does not, and three open issues already measured that:

A CUDA graph collapses host launch dispatch. There is close to no device dispatch in
this render to collapse, and the dominant cost is a serial host phase that a graph
cannot touch. Capturing here now would measure nothing.

What would unblock it

In order:

  1. An LTX-2.5 render emits ONE log line in 2.5 hours, so no phase of it can be measured without re-deriving the timing from a memory sampler #1010 — a phase-boundary log, so a phase can be named rather than inferred from a
    duration.
  2. After #1041 the LTX-2.5 render is dominated by a ~1731 s single-threaded phase that is CONSTANT in resolution, not by the decode #1087 — identify and fix the resolution-constant serial phase.
  3. An LTX-2.5 render with --device cuda stages 35.5 GiB onto the GPU and then never uses it: GPU utilization is 0 in 321 of 347 samples, and every non-zero one is inside the staging window #1024 and LTX-2.5 video VAE decode runs on the HOST because it has no device arm — every oracle runs it GPU-resident #1007 — get the denoise loop and the VAE decode actually device-resident.
  4. Only then: measure GPU-busy against wall on the denoise loop. If the loop is
    device-resident and host-dispatch-bound, capture it. If it is GPU-bound, close this
    as not-a-lever the way SGLang's Breakable CUDA Graph is unrecorded, and ENG-CUDAGRAPH carries no verdict on prefill capture #1161 closed prefill capture.

Step 4 is the decision point, and it is a measurement, not an implementation.

Gate, when it runs

Bit-exact pixels against the eager arm, verified on pixels rather than on an exit code,
over more than one replay. Related: #1149, where a completed render read as a failure
because of an exit code.

Owner

Owned by ENG-CUDAGRAPH-DIFFUSION, listed under ## Owed in
.agents/specs/sglang-breakable-cuda-graph.md. Analysis issue: #1161. Blocked by
#1010, #1087, #1024, #1007.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [Claude Code]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions