Skip to content

[Fix] Use int64 seq_lens across all CUDA graph runners and backends - #27840

Merged
ch-wan merged 2 commits into
mainfrom
cheng/seq-lens-int64
Jun 11, 2026
Merged

ch-wan merged 2 commits into
mainfrom
cheng/seq-lens-int64

Conversation

@ch-wan

@ch-wan ch-wan commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Motivation

PR #27407 routed the eager forward path (forward_decode / forward_extend / forward_idle) through the CUDA-graph input-buffer registry. That registry mirrors seq_lens / seq_lens_cpu as int32 (the long-standing cuda-graph buffer convention), but the canonical ForwardBatch.seq_lens is int64, and the intel_amx CPU decode kernel strictly requires int64 req_lens. On CPU the registry therefore handed the kernel a downcast tensor and crashed:

RuntimeError: decode: expect req_lens to be int64, got Int

This is the Xeon CI failure. #27549 worked around it with a device == "cuda" gate on the three eager call sites, which fixed the symptom on CPU but left the int32 downcast in place (a silent dtype change on the CUDA eager path vs. main) and kept non-CUDA devices off the unified eager path.

This PR fixes the root cause: seq_lens / seq_lens_cpu are int64 uniformly across all runners, so every backend receives the canonical dtype. GPU backends already convert to int32 internally where their kernels need it (verified by auditing every attention backend), so the int32 buffer dtype was incidental, not a kernel requirement.

Modifications

  • int64 buffer allocations for seq_lens / seq_lens_cpu:
    • DecodeInputBuffers.create (runner_utils/buffers.py)
    • _allocate_decode_buffers (runner/decode_cuda_graph_runner.py)
    • build_decode_registry slots (cuda_graph_buffer_registry.py)
    • speculative-decode runners: eagle_draft_cuda_graph_runner, eagle_draft_extend_cuda_graph_runner, frozen_kv_mtp_cuda_graph_runner, and the eagle_info placeholders.
  • flashinfer_mla: the cuda-graph replay path passed kv_len_arr_cpu (= seq_lens_cpu[:bs]) straight into wrapper.plan() while the capture path converts to int32 — added the matching .to(torch.int32).
  • Removed the device == "cuda" gate on the three _eager_fb_view call sites in model_runner.py (back to if not self.server_args.enable_pdmux:). With seq_lens int64 everywhere the eager path runs through the registry on all devices.

Backends that assert int32 (cutlass_mla, DSV4 sparse-prefill, trtllm_mla, tokenspeed) are always fed a converted int32 at the call site, never the raw buffer, so they are unaffected.

Accuracy Tests

CPU unit tests pass: test/registered/unit/model_executor/test_cuda_graph_buffer_registry.py (39 passed). GPU validation of the flashinfer / flashinfer_mla (DeepSeek-MLA) / trtllm / eagle / dflash paths should run in CI.

Speed Tests and Profiling

N/A — seq_lens / seq_lens_cpu are small bs-sized buffers; int64 doubles only those few bytes, and backends already materialize int32 derived tensors where their kernels need them.

🤖 Generated with Claude Code


CI States

Latest PR Test (Base): 🚫 Run #27313253351
Latest PR Test (Extra): ❌ Run #27313253134

The eager forward path routes through the CUDA-graph input-buffer registry,
which mirrored `seq_lens` / `seq_lens_cpu` as int32 (the cuda-graph buffer
convention). The canonical `ForwardBatch.seq_lens` is int64, and the
`intel_amx` CPU decode kernel requires int64 `req_lens`, so on CPU the
registry downcast crashed with `decode: expect req_lens to be int64, got Int`
(the Xeon CI failure #27549 worked around with a `device == "cuda"` gate
without addressing the root cause).

Make `seq_lens` / `seq_lens_cpu` int64 uniformly so every backend receives the
canonical dtype (GPU backends convert to int32 internally where needed):

- int64 buffer allocations: `DecodeInputBuffers.create`,
  `_allocate_decode_buffers`, `build_decode_registry` slots, and the
  speculative-decode runners (eagle draft / draft-extend / frozen-kv-mtp,
  eagle_info placeholders).
- `flashinfer_mla` replay: downcast `kv_len_arr_cpu` to int32 before
  `wrapper.plan` (the capture path already converts).
- Remove the `device == "cuda"` gate on the three `_eager_fb_view` call sites
  in `model_runner.py`; the eager path now runs through the registry on all
  devices.

CPU unit tests (test_cuda_graph_buffer_registry.py) pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@ch-wan

ch-wan commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator Author

/tag-and-rerun-ci

@kpham-sgl kpham-sgl left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Needed this change to fuse some memcpys / eager ops in metadata preparation path :D

With seq_lens now int64 in the cuda-graph decode buffers, the DSV4 decode
metadata builder derived swa_topk_lengths / raw_positions / page indices from
an int64 seq_lens_casual, and the sparse-decode kernel rejects non-int32
topk_length (`RuntimeError: topk_length must have dtype torch::kInt32`).

Normalize seq_lens_casual to int32 at the single make_core_attn_metadata choke
point (covers both the direct-pass decode callers and the expand_* paths),
restoring the prior int32 invariant. Same fix for the HIP radix backend.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ch-wan
ch-wan force-pushed the cheng/seq-lens-int64 branch from 59bbfd8 to 77e1914 Compare June 10, 2026 23:33
@ch-wan
ch-wan merged commit f4f30d7 into main Jun 11, 2026
146 of 166 checks passed
@ch-wan
ch-wan deleted the cheng/seq-lens-int64 branch June 11, 2026 02:55
@ZailiWang ZailiWang mentioned this pull request Jun 27, 2026
5 tasks
Chronostasys pushed a commit to MindLab-Research/sglang that referenced this pull request Aug 24, 2026
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.

2 participants