Skip to content

CUDA: thread-local stream override infrastructure for graph capture (stage 0, no functional change)#566

Open
riccardo-galbani wants to merge 1 commit into
antirez:mainfrom
riccardo-galbani:cuda-graphs-stage0
Open

CUDA: thread-local stream override infrastructure for graph capture (stage 0, no functional change)#566
riccardo-galbani wants to merge 1 commit into
antirez:mainfrom
riccardo-galbani:cuda-graphs-stage0

Conversation

@riccardo-galbani

Copy link
Copy Markdown

What

Infrastructure-only groundwork for CUDA graph capture in the decode path
(stage 0 of the plan discussed in #534):

  • Thread-local ds4_current_stream() accessor, gated behind DS4_CUDA_GRAPHS=1
  • 175 launch sites redirected through the accessor: 156 kernel launches,
    3 cudaMemsetAsync, 9 cublasSetStream insertions, 7 profiling
    cudaEventRecord (DS4_CUDA_MOE_PROFILE)
  • ds4_capture_set_stream() setter for later stages (currently unused)
  • Two NOTE markers for known stage-2 work items (sync memset at the routed
    MoE counts clear; profiling/capture mutual exclusion)
  • No ABI changes: all ds4_gpu_* shim signatures untouched

Why no functional change is guaranteed

No stream is ever created in this commit: g_ds4_capture_stream is
initialized to stream 0 and ds4_capture_set_stream() has no callers, so
ds4_current_stream() returns the legacy stream even with the flag on.
Flag-ON behavior is a no-op by construction, not just empirically.

Verification

Bit-identical logits (--dump-logits diff empty) and identical greedy
40-token output, reference (main @ 80ebbc3) vs this branch, flag OFF and ON:

  • RTX 4070 Laptop (sm_89), expert-streaming mode
  • DGX Spark GB10 (sm_121), fully resident weights (~80.8 GiB device cache),
    with and without MTP (draft=2)

Build: make cuda CUDA_ARCH=sm_89 and make cuda-spark CUDA_ARCH=sm_121, clean.

What this enables

Later stages (per-cluster capture/replay, following the approach validated
in Entrpi's decode-perf-tuning fork, +5.2–5.6% gen on GB10) can introduce
a real capture stream without touching launch sites again. Each stage will
come as a separate PR.

Add ds4_current_stream()/ds4_capture_set_stream() (internal linkage, no
ABI change) gated by DS4_CUDA_GRAPHS, and route all default-stream
operations in the decode/prefill paths through ds4_current_stream():
156 kernel launches, 3 cudaMemsetAsync, 9 cuBLAS gemm call sites
(cublasSetStream), 7 MoE-profiling cudaEventRecord.

With the flag unset, ds4_current_stream() returns the default stream:
behavior is provably identical. No capture is performed yet; this is
Stage 0 of the plan discussed in issue antirez#534.

Two NOTE markers document Stage 2 blockers (sync memset in routed_moe,
host-timed MoE profiling incompatible with capture).
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