Skip to content

Measure first-call and post-update costs of continuous rollout CUDA Graphs - #8853

Draft
nathon-lee wants to merge 13 commits into
deepspeedai:masterfrom
nathon-lee:bench/rollout-cuda-graph-first-call
Draft

nathon-lee wants to merge 13 commits into
deepspeedai:masterfrom
nathon-lee:bench/rollout-cuda-graph-first-call

Conversation

@nathon-lee

@nathon-lee nathon-lee commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Background

Follow-up to #8732 and its
review suggestions.
Training updates invalidate the continuous rollout graph, so steady-state latency alone does not capture the cost of alternating training and generation.

Implementation status

The initial benchmark records CUDA-synchronized latency and throughput for eager / graph rollouts around one real SGD update. Each measured call's tokens, attention masks, and response offsets are checked against native Hugging Face generate() using the same weights.

Existing GPU measurements

Recorded on an RTX A4500 (20 GiB), PyTorch 2.9.1+cu128 / CUDA 12.8, Transformers 5.20.1, FP16, using a randomly initialized tiny Llama. Steady-state values are medians of 10 calls; first-call values are single samples.

Phase Eager (ms) CUDA Graph (ms)
First call 240.182 61.933
Steady state 228.014 45.424
First call after SGD update 226.304 58.800
Steady state after update 234.919 45.281

Graph first-call overhead was 16.509 ms before SGD and 13.519 ms afterward; the training update took 55.849 ms. These are synthetic observations, not production-model performance claims. The overhead values are end-to-end differences, not isolated capture timings.

Reproduce on the benchmark checkout with the Issue 4 fix:

python -m benchmarks.rollout.bench_cuda_graph_first_call \
    --requests 8 --batch-size 4 --prompt-len 32 --max-new-tokens 32 \
    --iterations 10 --output rollout-first-call.json

CUDA / model libraries were initialized without warming up the rollout graph; each phase measured eager before graph. The original combined working tree reported 60 passed, 1 skipped and passing pre-commit checks. The skip required an optional pretrained model. This benchmark was not rerun during the separate Issue 4 validation.

Remaining work and acceptance criteria

  • Separate cache / static-buffer allocation, warmup, and capture timings from total rollout latency, without double-counting.
  • Report per-phase capture counts, allocated / reserved and peak GPU memory, latency, and generated-token throughput.
  • Measure repeated training / rollout cycles with real optimizer updates; preserve the four phases and generation-parity checks.
  • Keep synchronized timing, fixed inputs, reproducible commands, and complete model / attention / hardware / software / workload metadata. Clearly label synthetic versus pretrained-model results; none of the latter are available yet.

Scope and dependencies

Depends on #8732 and, on Transformers 5.20.1, Issue 4. Keep the runtime fix separate. Measure existing behavior without weakening parameter-version checks. Benchmark code and usage belong in benchmarks/rollout/bench_cuda_graph_first_call.py and benchmarks/README.md, not the Issue 4 branch.

Signed-off-by: nathon-lee <leejianwoo@gmail.com>
Cache continuous-rollout CUDA graph state across matching generate calls.
Rebuild the graph when the model parameters or static decode shape changes,
and reset static buffers and KV cache rows before reuse.

Use eager attention and a preallocated additive causal mask during capture
to avoid Transformers capture-time mask allocations. Relax cache-class
detection for models that support the cache interface without declaring the
private capability flag.

Add coverage for eager-attention capture, graph reuse, weight invalidation,
and current StaticCache update semantics.

Signed-off-by: nathon-lee <leejianwoo@gmail.com>
Signed-off-by: nathon-lee <leejianwoo@gmail.com>
Use the preallocated additive causal mask to make CUDA Graph capture safe
without overriding the model attention implementation. This preserves default
SDPA behavior and restores eager/graph token parity for pretrained GPT-2.

Update graph-capture coverage to verify the configured attention
implementation remains unchanged.

Signed-off-by: nathon-lee <leejianwoo@gmail.com>
Populate continuous rollout cache statistics after CUDA Graph decoding so callers do not receive stale eager-path metrics. Cover graph cache capacity, peak usage, decode steps, and trimming metrics.

Signed-off-by: nathon-lee <leejianwoo@gmail.com>
Validate fixed-slot CUDA Graph options before capture and cover unsupported decode alignment, cache trimming, and insufficient cache capacity.

Signed-off-by: nathon-lee <leejianwoo@gmail.com>
Add CUDA rollout coverage for pretrained Hugging Face models behind DEEPSPEED_PRETRAINED_ROLLOUT_MODEL so regular CI does not download weights.
Validate eager and CUDA Graph parity across prompts and verify graph reuse.

Signed-off-by: nathon-lee <leejianwoo@gmail.com>
Route dummy writes for non-decoding graph slots to a scratch cache position so refilled prompts retain their prefetched KV state.
Add CUDA coverage for a slot refill while another request continues decoding.

Signed-off-by: nathon-lee <leejianwoo@gmail.com>
Reject flash_attention_2 before continuous CUDA Graph capture because
the fixed replay path requires a four-dimensional additive attention mask.
Document the restriction and cover the configuration error.

Signed-off-by: nathon-lee <leejianwoo@gmail.com>
Reject models that explicitly lack cache-class support before the
continuous CUDA Graph path creates static cache state.
Add regression coverage for the graph-specific validation path.

Signed-off-by: nathon-lee <leejianwoo@gmail.com>
…raction

Keep static_cache_position in _ContinuousGraphState so it remains alive
for the lifetime of the captured graph.

Add is_current_stream_capturing() to the accelerator interface, with a
default False implementation and a CUDA override. Route the static cache
capture check through this interface instead of calling torch.cuda directly.

Add regression coverage for tensor lifetime, graph replay, capture state,
and eager cache bounds checks, and document the new accelerator method.

Signed-off-by: nathon-lee <leejianwoo@gmail.com>
…CUDA Graphs

Signed-off-by: nathon-lee <leejianwoo@gmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant