Skip to content

[FlyDSL] split-K hgemm: make semaphore/signal workspace CUDA-graph-capture safe - #4715

Draft
xiaohuguo2023 wants to merge 1 commit into
mainfrom
xiaohuguo/flydsl-splitk-cudagraph-capture-fix
Draft

[FlyDSL] split-K hgemm: make semaphore/signal workspace CUDA-graph-capture safe#4715
xiaohuguo2023 wants to merge 1 commit into
mainfrom
xiaohuguo/flydsl-splitk-cudagraph-capture-fix

Conversation

@xiaohuguo2023

Copy link
Copy Markdown
Member

Summary

The FlyDSL split-K GEMM path uses a per-(device, stream) semaphore/signal
workspace from _get_split_k_tensors, memoized with functools.lru_cache and
zero-initialized once, eagerly. The split-K reduction kernel treats these as
atomic counters: each workgroup decrements as it retires and the "last workgroup"
performs the cross-split reduction, which requires the counters to start at their
zeroed state on every launch.

Under CUDA-graph capture + replay this invariant breaks. The one-time
torch.zeros(...) ran before capture, so it is not recorded as a node in the
graph
. On replay the workspace is never re-zeroed, the counters never return to
their initial state, the last-workgroup handshake never re-arms, and the kernel
hangs. This is the same failure mode fixed for the a16w16 ASM GEMM path in
#4494 — this PR applies the same remedy to the FlyDSL split-K path.

Any split-K FlyDSL GEMM captured in a full CUDA graph is affected. In practice it
shows up on skinny decode shapes that select split_k 4–8 (e.g. N=1024/384, K=7168 at small M) inside a FULL decode cudagraph.

Fix

Mirror #4494:

  • Keep the eager fast path unchanged — the memoized allocator is renamed to
    _get_split_k_tensors_cached (still lru_cached on (device, stream)).
  • In _get_split_k_tensors, when torch.cuda.is_current_stream_capturing() is
    true, allocate a fresh, zeroed workspace for that launch so the zero-fill is
    recorded as a graph node and re-establishes the initial counter state on every
    replay. Distinct captured launches therefore never alias one another's counters.
  • Keep captured workspaces alive for the process lifetime
    (_captured_split_k_keepalive) so the graph-recorded zero-fill always has valid
    backing storage.

Call sites are unchanged — _get_split_k_tensors(device, stream) keeps its name
and signature.

@github-actions

Copy link
Copy Markdown
Contributor

🏷️ CI Guide

Runs automatically on every PR:

  • ✅ Pre-checks (submodule verification, code formatting)
  • ✅ Aiter op tests (gfx942 + gfx950)
  • ✅ Triton tests on MI35X (only when aiter/ops/triton/** or related paths are changed)

Extended tests (opt-in via labels):

Label Tests
ci:gfx1250-ffm-triton Run the five-shard gfx1250 FFM Triton test suite
ci:triton-300x Run an additional Triton test job on MI300X in PRs; main branch always runs both MI35X and MI300X
ci:sglang SGLang integration tests: DeepSeek-R1-MXFP4 accuracy, Qwen 3.5 accuracy
ci:atom ATOM benchmark: DeepSeek-R1-0528, GPT-OSS-120B
ci:atom_full ATOM accuracy suite for PR and main models from ATOM models_accuracy.json
ci:vllm vLLM benchmark: GPT-OSS-120B, DeepSeek-R1-0528, Kimi-K2.5
ci:all All standard extended tests (excludes ci:atom_full)

Only add ci:atom_full for FlyDSL or Triton upgrades.
Add labels via the sidebar or gh pr edit 4715 --add-label <label>

@xiaohuguo2023
xiaohuguo2023 force-pushed the xiaohuguo/flydsl-splitk-cudagraph-capture-fix branch from b00cd17 to a40438c Compare August 21, 2026 11:14
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