Repository navigation
perf(cake_gdn_kcp): with grad, lighter host path for the non-deterministic KCP package - #8212
Conversation
…aunch resolution The forward and backward bodies of the non-deterministic KCP package now run in one tvm_ffi.use_torch_stream() scope (cake_backend.launch_scope) instead of entering a context per launch; a launch outside every scope, or after a stream switch inside one, still enters its own. The scope is entered inside a CUDA graph capture when there is one, so it binds the capture stream. The record, grid, test flag and merge columns of each launch key are resolved once and kept with the context's tables (_Tables.launches); every launch still rebuilds its public values and appends its record. The launches, grids and streams are unchanged: host time only.
_pkg() and _det() ran a function-level import on every facade call. Cache the module objects with functools.cache: the first call still imports lazily, later calls reuse the module. Routing, exceptions and the lazy type resolution are unchanged. A CPU test checks that routed calls on either route run no import after first use.
|
@flashinfer-bot run tests/experimental/test_cake_gdn_train_kcp.py tests/experimental/test_cake_gdn_train_kcp_api.py tests/experimental/test_cake_gdn_train_kcp_build.py tests/experimental/test_cake_gdn_train_kcp_cp1.py tests/experimental/test_cake_gdn_train_kcp_dist.py tests/experimental/test_cake_gdn_det_train_kcp_build.py tests/experimental/test_cake_gdn_det_train_kcp_api.py |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Cached launch resolution flashinfer/experimental/cake_gdn_train_kcp/cake_kcp.py, tests/experimental/test_cake_gdn_train_kcp.py |
Both backends use a per-plan cache for resolved launch data. Tests compare cached resolutions and forward/backward results with uncached behavior. |
Scoped stream binding flashinfer/experimental/cake_gdn_train_kcp/cake_backend.py, flashinfer/experimental/cake_gdn_train_kcp/cake_kcp.py, flashinfer/experimental/cake_gdn_train_kcp/README.md, tests/experimental/test_cake_gdn_train_kcp.py, tests/experimental/test_cake_gdn_train_kcp_cp1.py |
Backends can provide a launch scope for forward and backward bodies. The kernel launcher reuses a matching stream binding and falls back to per-launch binding when no matching scope is active. Tests cover nested scopes, stream changes, and CUDA execution. |
Facade route loading
| Layer / File(s) | Summary |
|---|---|
Cached route imports flashinfer/cake_gdn_train_kcp.py, tests/experimental/test_cake_gdn_train_kcp_api.py |
The routed-package and deterministic-route loaders cache imported modules. A test verifies that subsequent calls perform no imports. |
Estimated code review effort: 3 (Moderate) | ~25 minutes
Change: Refactor
Sequence Diagram(s)
sequenceDiagram
participant EntryBody
participant KernelBackend
participant CakeBackend
participant TVMFFI
EntryBody->>KernelBackend: enter launch_scope
KernelBackend->>CakeBackend: delegate launch_scope
CakeBackend->>TVMFFI: bind current Torch stream
EntryBody->>CakeBackend: launch module
CakeBackend->>TVMFFI: call entry under matching scope
Possibly related issues
- Issue 7251: The issue covers the same package host implementation; this PR changes the KCP host launch path and caches launch data.
- Issue 4214: The issue concerns GDN cache lifecycle and cache identity; this PR adds a launch cache keyed by launch-selection inputs.
- Issue 8063: The issue requests a non-deterministic packed GDN implementation with gradients and KCP options; this PR changes the non-deterministic KCP training route.
Merge Risk: 
Minimal · up to 70452
-
No actionable merge-blocking risk was established. The change is mergeable after normal checks.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passed-
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 20 functions across 6 files.
-
Full details: Description check
-
Explanation
The description gives detailed technical scope, behavior, validation, and benchmark results. However, it omits the required template sections and experimental-track information, including the tracking issue, checklist declarations, and the required experimental-tests target block.
Resolution
Reformat the description using the repository template. Add the Description, Related Issues, Pull Request Checklist, Tests, Experimental Track, and Reviewer Notes sections as applicable. Because this PR changes code under flashinfer/experimental/, provide the experimental tracking issue and required declarations, and replace the experimental-tests placeholder with valid targets under tests/experimental/. Record the test outcomes or clearly state any pending validation.
-
Finishing Touches
-
Generate unit tests (beta)
-
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
yzh119
left a comment
There was a problem hiding this comment.
LGTM. Nit: _launch_key assumes resolve_launch reads nothing from the tensors except what's in the key. A comment saying so would help the next person who adds a grid input.
flashinfer-bot
left a comment
There was a problem hiding this comment.
CODEOWNERS gap attestation (not a code review).
A code owner of a changed path has approved this PR:
- @yzh119 -> flashinfer/cake_gdn_train_kcp.py
- @yzh119 -> flashinfer/experimental/cake_gdn_train_kcp/cake_backend.py
- @yzh119 -> flashinfer/experimental/cake_gdn_train_kcp/cake_kcp.py
- @yzh119 -> flashinfer/experimental/cake_gdn_train_kcp/README.md
The following files match only the catch-all rule; this approval covers that technical gap under the one-approval policy. GitHub still requires each owned path's own owner.
- tests/experimental/test_cake_gdn_train_kcp_api.py
- tests/experimental/test_cake_gdn_train_kcp_cp1.py
- tests/experimental/test_cake_gdn_train_kcp.py
Head: 7e5a4a3
resolve_launch derives the record, grid, test flag and merge cols_per_cta from the scalars in _launch_key alone; say so next to the key, so that an input added to resolve_launch is added to the key as well.
|
Thanks, @yzh119. Added the invariant to the |
|
@flashinfer-bot run tests/experimental/test_cake_gdn_train_kcp.py tests/experimental/test_cake_gdn_train_kcp_api.py tests/experimental/test_cake_gdn_train_kcp_build.py tests/experimental/test_cake_gdn_train_kcp_cp1.py tests/experimental/test_cake_gdn_train_kcp_dist.py tests/experimental/test_cake_gdn_det_train_kcp_build.py tests/experimental/test_cake_gdn_det_train_kcp_api.py |
…terministic KCP (#8219) This PR changes `flashinfer.experimental.cake_gdn_train_kcp`, the non-deterministic context-parallel variant of Cake's Gated DeltaNet (GDN) chunked training kernel with gradients. Callers reach it through `flashinfer.cake_gdn_train_kcp(deterministic=False)`. It follows #8212 and cuts more of the package's eager host work. The change is host-side only and has four parts: 1. Each plan now derives its launch state once and caches it in `_Tables.memo`. That state covers the normalized pool tables of `CallKcp.indexed` with their kernel addressing and device index tables, the walk and merge-chain device tables, the zero block's index table, the collectives' split lists and the pool sizes. Every device table still comes from the plan's content cache, so each launch receives the same tensors as before. 2. A call without `workspace=` now uses its context's ticket slots for the current stream. Before, it made a zeroed allocation per call. There is one zeroed set per context, device and stream. Under a CUDA stream capture, the call gets fresh slots. 3. Such a call no longer sizes the forward exchange's pools for a saved-context backward. It also no longer sizes the empty pools at P = 1. Backward peak memory can only go down. 4. `chunk_gdn_kcp` validates its keyword options once per keyword set. The context's prepared-tables lookup is built once per key, and per-launch pool slicing and record building are trimmed. The exchanges cannot be packed: in each step's GDN all_to_all pair the second exchange needs the first one's result, and the other 2 per-step collectives belong to the causal-conv package. Device programs, launch order, grids, streams, numerics, graph-replay semantics and the public API are unchanged. In every timed run (eager and graph replay, all ranks), outputs and every gradient are bitwise equal to the previous package. Launch records are also equal. Speedup is baseline latency / new latency, so values above 1 mean the new package is faster. There are three baselines, and all of them ran in the same process as the new package: - **Deterministic Cake KCP:** the deterministic Cake KCP package from main, called through its public entry. - **Strongest non-Cake, per row:** the faster of FLA 0.6.0 context-parallel KCP and a head-parallel all-to-all around the cuDNN frontend 1.32.1 FROST GDN engine. Both were qualified by comparison with the new package. FROST head-CP does not apply to P2 at CP4, because 4 ranks divide neither 2 nor 6 heads. FLA KCP is the only non-Cake arm there. FlashQLA has no sm_107a build. - **Previous non-deterministic:** the package of #8212, now on main. It cannot share the public entry with the new package in one process. It is loaded as a renamed copy and called through an equivalent stand-in entry, which skips the public entry's dispatch. A path-only control ran this PR's code on the stand-in entry and on the public entry. It measured 0.986-1.002 on forward+backward rows and 0.989-1.005 on checkpointed rows. "vs previous" ratios are therefore conservative by up to about 1 %. On the graph-replay rows, same-path code-only ratios (previous vs this PR's code, both on the stand-in entry) are 0.995-1.002. All arms ran on one exclusive R200 node (sm_107a, 212 SMs; CUDA 13.0 runtime, PyTorch 2.14.1+cu130; no power capping observed). S26, DET, P1 and P3 use CP2 (2 ranks). P2 uses CP4 (4 ranks). All rows use BF16 q/k/v, FP32 g/beta and head dim 128. The protocol is the same as in #8212. Each of 5 groups runs the arms in palindromic order 2 times. Each call is 12 timed iterations after 10 warm-up, with a 256 MiB L2 flush, sync and barrier before each iteration. Latency is the median CUDA-event time of the slowest rank. Speedup is the median of the per-group ratios [min, max]. Run 2 is a separate process with the arm order reversed. How to read the table: - Backward = forward+backward − forward. - "(medians)" marks a ratio of medians. - (H, HV) = (query/key heads, value heads). - S26 = (2, 6), 3 documents of 2049/3001/3142 tokens (8192). - DET = (2, 6), 65536 tokens in 6 documents. - P2 = (2, 6), 261987 tokens (3 documents), CP4. - P1 = (16, 48), 241817 tokens. - P3 = (16, 48), 259174 tokens. - Layout C is contiguous; layout D is zigzag per document. Four ratio cells are classed UNSTABLE, all in the vs-deterministic column. Three are S26 run 1 cells: eager forward, eager forward+backward and graph-replay checkpointed (deterministic arm drift 2.22 %). The fourth is DET layout D run 2 eager forward. They are shown as measured. Table: R200 (sm_107a, 212 SMs), CUDA 13.0 runtime, PyTorch 2.14.1+cu130, CP2 (P2: CP4); latencies in ms (median CUDA-event time of the slowest rank); speedup = median of the per-group ratios [min, max]. | GPU / architecture | workload (pack, (H, HV), S tokens, CP, layout); timing mode; run | operation | deterministic Cake (ms) | strongest non-Cake (ms, implementation) | previous non-deterministic Cake (ms) | new non-deterministic Cake (ms) | speedup vs deterministic Cake | speedup vs non-Cake SOTA | speedup vs previous non-deterministic Cake | |---|---|---|---|---|---|---|---|---|---| | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; eager; run 1 | forward | 0.805 | 3.235 (FLA KCP) | 0.724 | 0.546 | 1.474 [1.467, 1.479] | 5.935 [5.909, 5.939] | 1.324 [1.323, 1.343] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; eager; run 1 | backward (= forward+backward − forward) | 1.303 | 3.703 (FLA KCP) | 1.179 | 0.896 | 1.454 [1.430, 1.481] | 4.131 [4.131, 4.131] (medians) | 1.319 [1.301, 1.326] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; eager; run 1 | forward+backward | 2.108 | 6.938 (FLA KCP) | 1.903 | 1.442 | 1.461 [1.446, 1.479] | 4.811 [4.811, 4.811] unpaired | 1.321 [1.312, 1.332] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; eager; run 1 | checkpointed 2×forward+backward | 3.114 | 10.088 (FLA KCP) | 2.865 | 2.192 | 1.419 [1.412, 1.433] | 4.596 [4.568, 4.648] | 1.303 [1.300, 1.319] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; graph replay; run 1 | forward | 0.544 | n/a (no graph-replay arm) | 0.526 | 0.527 | 1.032 [1.029, 1.035] | n/a | 0.997 [0.995, 0.998] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; graph replay; run 1 | backward (= forward+backward − forward) | 0.854 | n/a (no graph-replay arm) | 0.837 | 0.837 | 1.019 [1.018, 1.024] | n/a | 1.000 [0.998, 1.004] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; graph replay; run 1 | forward+backward | 1.398 | n/a (no graph-replay arm) | 1.363 | 1.364 | 1.025 [1.024, 1.026] | n/a | 0.999 [0.998, 1.000] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; graph replay; run 1 | checkpointed 2×forward+backward | 1.936 | n/a (no graph-replay arm) | 1.895 | 1.899 | 1.020 [1.017, 1.022] | n/a | 0.998 [0.997, 0.999] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; eager; run 2 (reversed arm order) | forward | 0.792 | 3.235 (FLA KCP) | 0.718 | 0.545 | 1.453 [1.446, 1.456] | 5.941 [5.941, 5.941] unpaired | 1.318 [1.316, 1.320] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; eager; run 2 (reversed arm order) | backward (= forward+backward − forward) | 1.318 | 3.703 (FLA KCP) | 1.184 | 0.887 | 1.485 [1.471, 1.494] | 4.173 [4.173, 4.173] (medians) | 1.339 [1.323, 1.355] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; eager; run 2 (reversed arm order) | forward+backward | 2.110 | 6.938 (FLA KCP) | 1.902 | 1.432 | 1.474 [1.462, 1.479] | 4.853 [4.807, 4.857] | 1.331 [1.321, 1.341] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; eager; run 2 (reversed arm order) | checkpointed 2×forward+backward | 3.146 | 10.088 (FLA KCP) | 2.891 | 2.219 | 1.423 [1.405, 1.427] | 4.546 [4.546, 4.546] unpaired | 1.307 [1.295, 1.311] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; graph replay; run 2 (reversed arm order) | forward | 0.541 | n/a (no graph-replay arm) | 0.526 | 0.526 | 1.029 [1.026, 1.029] | n/a | 0.999 [0.998, 0.999] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; graph replay; run 2 (reversed arm order) | backward (= forward+backward − forward) | 0.852 | n/a (no graph-replay arm) | 0.835 | 0.835 | 1.021 [1.019, 1.022] | n/a | 1.000 [0.999, 1.003] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; graph replay; run 2 (reversed arm order) | forward+backward | 1.393 | n/a (no graph-replay arm) | 1.361 | 1.361 | 1.023 [1.022, 1.025] | n/a | 1.000 [0.999, 1.002] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, C; graph replay; run 2 (reversed arm order) | checkpointed 2×forward+backward | 1.931 | n/a (no graph-replay arm) | 1.893 | 1.893 | 1.020 [1.018, 1.021] | n/a | 1.000 [0.999, 1.002] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; eager; run 1 | forward | 0.889 | 3.235 (FLA KCP) | 0.628 | 0.625 | 1.421 [1.420, 1.427] | 5.179 [5.179, 5.179] unpaired | 1.007 [1.005, 1.008] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; eager; run 1 | backward (= forward+backward − forward) | 1.380 | 3.703 (FLA KCP) | 0.871 | 0.753 | 1.834 [1.814, 1.843] | 4.916 [4.916, 4.916] (medians) | 1.155 [1.152, 1.160] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; eager; run 1 | forward+backward | 2.269 | 6.938 (FLA KCP) | 1.499 | 1.378 | 1.646 [1.639, 1.652] | 5.035 [5.035, 5.035] unpaired | 1.087 [1.087, 1.090] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; eager; run 1 | checkpointed 2×forward+backward | 3.382 | 10.088 (FLA KCP) | 2.365 | 2.038 | 1.662 [1.650, 1.667] | 4.949 [4.949, 4.949] unpaired | 1.164 [1.157, 1.170] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; graph replay; run 1 | forward | 0.600 | n/a (no graph-replay arm) | 0.596 | 0.596 | 1.006 [1.005, 1.007] | n/a | 0.998 [0.996, 1.000] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; graph replay; run 1 | backward (= forward+backward − forward) | 0.810 | n/a (no graph-replay arm) | 0.808 | 0.810 | 1.001 [1.000, 1.004] | n/a | 1.000 [0.995, 1.001] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; graph replay; run 1 | forward+backward | 1.411 | n/a (no graph-replay arm) | 1.404 | 1.406 | 1.003 [1.002, 1.004] | n/a | 0.999 [0.997, 0.999] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; graph replay; run 1 | checkpointed 2×forward+backward | 2.039 | n/a (no graph-replay arm) | 2.031 | 2.032 | 1.004 [1.003, 1.004] | n/a | 0.999 [0.999, 1.000] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; eager; run 2 (reversed arm order) | forward | 0.885 | 3.235 (FLA KCP) | 0.625 | 0.621 | 1.428 [1.418, 1.458] UNSTABLE | 5.207 [5.207, 5.207] unpaired | 1.006 [1.005, 1.008] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; eager; run 2 (reversed arm order) | backward (= forward+backward − forward) | 1.377 | 3.703 (FLA KCP) | 0.873 | 0.755 | 1.821 [1.806, 1.830] | 4.904 [4.904, 4.904] (medians) | 1.155 [1.151, 1.159] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; eager; run 2 (reversed arm order) | forward+backward | 2.263 | 6.938 (FLA KCP) | 1.498 | 1.376 | 1.643 [1.640, 1.649] | 5.041 [5.041, 5.041] unpaired | 1.089 [1.085, 1.089] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; eager; run 2 (reversed arm order) | checkpointed 2×forward+backward | 3.371 | 10.088 (FLA KCP) | 2.366 | 2.034 | 1.656 [1.652, 1.671] | 4.960 [4.960, 4.960] unpaired | 1.165 [1.161, 1.172] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; graph replay; run 2 (reversed arm order) | forward | 0.599 | n/a (no graph-replay arm) | 0.594 | 0.593 | 1.010 [1.009, 1.014] | n/a | 1.002 [1.000, 1.005] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; graph replay; run 2 (reversed arm order) | backward (= forward+backward − forward) | 0.809 | n/a (no graph-replay arm) | 0.809 | 0.808 | 1.003 [0.998, 1.004] | n/a | 1.003 [0.998, 1.005] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; graph replay; run 2 (reversed arm order) | forward+backward | 1.408 | n/a (no graph-replay arm) | 1.403 | 1.400 | 1.006 [1.004, 1.007] | n/a | 1.002 [1.000, 1.003] | | R200 sm_107a (212 SMs) | DET, (2, 6), 65536, CP2, D; graph replay; run 2 (reversed arm order) | checkpointed 2×forward+backward | 2.040 | n/a (no graph-replay arm) | 2.026 | 2.026 | 1.007 [1.006, 1.008] | n/a | 1.000 [0.999, 1.001] | | R200 sm_107a (212 SMs) | P1, (16, 48), 241817, CP2, C; eager; run 1 | forward | 4.866 | 22.030 (FROST head-CP) | 4.805 | 4.793 | 1.015 [1.015, 1.015] | 4.596 [4.596, 4.596] unpaired | 1.003 [1.002, 1.003] | | R200 sm_107a (212 SMs) | P1, (16, 48), 241817, CP2, C; eager; run 1 | backward (= forward+backward − forward) | 8.539 | 32.014 (FROST head-CP) | 8.543 | 8.546 | 0.999 [0.999, 1.000] | 3.746 [3.746, 3.746] (medians) | 1.000 [0.999, 1.000] | | R200 sm_107a (212 SMs) | P1, (16, 48), 241817, CP2, C; eager; run 1 | forward+backward | 13.404 | 54.044 (FROST head-CP) | 13.348 | 13.340 | 1.005 [1.005, 1.005] | 4.051 [4.051, 4.051] unpaired | 1.001 [1.000, 1.001] | | R200 sm_107a (212 SMs) | P1, (16, 48), 241817, CP2, C; eager; run 1 | checkpointed 2×forward+backward | 15.063 | 70.615 (FROST head-CP) | 14.939 | 14.930 | 1.009 [1.009, 1.009] | 4.730 [4.730, 4.730] unpaired | 1.001 [1.000, 1.001] | | R200 sm_107a (212 SMs) | P1, (16, 48), 241817, CP2, C; eager; run 2 (reversed arm order) | forward | 4.858 | 22.030 (FROST head-CP) | 4.791 | 4.781 | 1.016 [1.016, 1.017] | 4.608 [4.607, 4.610] | 1.002 [1.002, 1.003] | | R200 sm_107a (212 SMs) | P1, (16, 48), 241817, CP2, C; eager; run 2 (reversed arm order) | backward (= forward+backward − forward) | 8.536 | 32.014 (FROST head-CP) | 8.534 | 8.539 | 1.000 [0.999, 1.000] | 3.749 [3.749, 3.749] (medians) | 0.999 [0.999, 1.000] | | R200 sm_107a (212 SMs) | P1, (16, 48), 241817, CP2, C; eager; run 2 (reversed arm order) | forward+backward | 13.395 | 54.044 (FROST head-CP) | 13.324 | 13.319 | 1.006 [1.005, 1.006] | 4.057 [4.056, 4.059] | 1.000 [1.000, 1.001] | | R200 sm_107a (212 SMs) | P1, (16, 48), 241817, CP2, C; eager; run 2 (reversed arm order) | checkpointed 2×forward+backward | 15.054 | 70.615 (FROST head-CP) | 14.920 | 14.908 | 1.010 [1.009, 1.010] | 4.737 [4.735, 4.738] | 1.001 [1.000, 1.001] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; eager; run 1 | forward | 0.914 | 18.713 (FLA KCP) | 0.902 | 0.895 | 1.020 [1.020, 1.022] | 20.902 [20.902, 20.902] unpaired | 1.007 [1.007, 1.009] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; eager; run 1 | backward (= forward+backward − forward) | 1.535 | 16.908 (FLA KCP) | 1.405 | 1.380 | 1.112 [1.107, 1.124] | 12.254 [12.254, 12.254] (medians) | 1.016 [1.014, 1.023] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; eager; run 1 | forward+backward | 2.448 | 35.621 (FLA KCP) | 2.307 | 2.275 | 1.076 [1.073, 1.084] | 15.659 [15.644, 15.729] | 1.012 [1.011, 1.017] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; eager; run 1 | checkpointed 2×forward+backward | 3.413 | 54.507 (FLA KCP) | 3.179 | 2.816 | 1.212 [1.210, 1.213] | 19.346 [19.342, 19.377] | 1.129 [1.125, 1.134] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; graph replay; run 1 | forward | 0.892 | n/a (no graph-replay arm) | 0.879 | 0.882 | 1.012 [1.009, 1.014] | n/a | 0.997 [0.995, 0.999] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; graph replay; run 1 | backward (= forward+backward − forward) | 1.374 | n/a (no graph-replay arm) | 1.374 | 1.375 | 1.000 [0.999, 1.001] | n/a | 1.000 [0.999, 1.001] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; graph replay; run 1 | forward+backward | 2.266 | n/a (no graph-replay arm) | 2.254 | 2.256 | 1.005 [1.004, 1.005] | n/a | 0.999 [0.999, 0.999] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; graph replay; run 1 | checkpointed 2×forward+backward | 3.172 | n/a (no graph-replay arm) | 3.144 | 3.148 | 1.008 [1.007, 1.008] | n/a | 0.999 [0.998, 0.999] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; eager; run 2 (reversed arm order) | forward | 0.914 | 18.713 (FLA KCP) | 0.902 | 0.896 | 1.020 [1.019, 1.021] | 21.078 [20.856, 21.094] | 1.006 [1.006, 1.007] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; eager; run 2 (reversed arm order) | backward (= forward+backward − forward) | 1.529 | 16.908 (FLA KCP) | 1.400 | 1.378 | 1.109 [1.100, 1.116] | 12.268 [12.268, 12.268] (medians) | 1.014 [1.013, 1.022] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; eager; run 2 (reversed arm order) | forward+backward | 2.443 | 35.621 (FLA KCP) | 2.302 | 2.274 | 1.073 [1.068, 1.078] | 15.663 [15.663, 15.663] unpaired | 1.011 [1.011, 1.016] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; eager; run 2 (reversed arm order) | checkpointed 2×forward+backward | 3.417 | 54.507 (FLA KCP) | 3.183 | 2.816 | 1.213 [1.210, 1.220] | 19.357 [19.357, 19.357] unpaired | 1.130 [1.128, 1.134] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; graph replay; run 2 (reversed arm order) | forward | 0.894 | n/a (no graph-replay arm) | 0.880 | 0.881 | 1.014 [1.011, 1.018] | n/a | 1.000 [0.996, 1.001] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; graph replay; run 2 (reversed arm order) | backward (= forward+backward − forward) | 1.373 | n/a (no graph-replay arm) | 1.371 | 1.374 | 1.000 [0.998, 1.002] | n/a | 0.997 [0.997, 1.001] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; graph replay; run 2 (reversed arm order) | forward+backward | 2.267 | n/a (no graph-replay arm) | 2.251 | 2.255 | 1.005 [1.005, 1.005] | n/a | 0.999 [0.998, 0.999] | | R200 sm_107a (212 SMs) | P2, (2, 6), 261987, CP4, C; graph replay; run 2 (reversed arm order) | checkpointed 2×forward+backward | 3.174 | n/a (no graph-replay arm) | 3.143 | 3.146 | 1.009 [1.009, 1.009] | n/a | 0.999 [0.999, 1.000] | | R200 sm_107a (212 SMs) | P3, (16, 48), 259174, CP2, C; eager; run 1 | forward | 5.028 | 7.908 (FLA KCP) | 4.957 | 4.948 | 1.016 [1.016, 1.017] | 1.598 [1.597, 1.599] | 1.002 [1.001, 1.003] | | R200 sm_107a (212 SMs) | P3, (16, 48), 259174, CP2, C; eager; run 1 | backward (= forward+backward − forward) | 9.084 | 51.429 (FROST head-CP forward+backward − FLA KCP forward) | 9.081 | 9.081 | 1.000 [1.000, 1.001] | 5.664 [5.664, 5.664] (medians) | 1.000 [1.000, 1.001] | | R200 sm_107a (212 SMs) | P3, (16, 48), 259174, CP2, C; eager; run 1 | forward+backward | 14.112 | 59.337 (FROST head-CP) | 14.039 | 14.029 | 1.006 [1.006, 1.006] | 4.230 [4.230, 4.230] unpaired | 1.001 [1.000, 1.001] | | R200 sm_107a (212 SMs) | P3, (16, 48), 259174, CP2, C; eager; run 1 | checkpointed 2×forward+backward | 15.812 | 67.882 (FLA KCP) | 15.670 | 15.658 | 1.010 [1.009, 1.010] | 4.335 [4.335, 4.335] unpaired | 1.001 [1.000, 1.001] | | R200 sm_107a (212 SMs) | P3, (16, 48), 259174, CP2, C; eager; run 2 (reversed arm order) | forward | 5.027 | 7.908 (FLA KCP) | 4.951 | 4.945 | 1.017 [1.016, 1.017] | 1.599 [1.599, 1.599] unpaired | 1.001 [1.000, 1.003] | | R200 sm_107a (212 SMs) | P3, (16, 48), 259174, CP2, C; eager; run 2 (reversed arm order) | backward (= forward+backward − forward) | 9.086 | 51.429 (FROST head-CP forward+backward − FLA KCP forward) | 9.081 | 9.079 | 1.000 [1.000, 1.002] | 5.664 [5.664, 5.664] (medians) | 1.000 [0.999, 1.001] | | R200 sm_107a (212 SMs) | P3, (16, 48), 259174, CP2, C; eager; run 2 (reversed arm order) | forward+backward | 14.113 | 59.337 (FROST head-CP) | 14.032 | 14.024 | 1.006 [1.006, 1.007] | 4.231 [4.230, 4.232] | 1.000 [1.000, 1.001] | | R200 sm_107a (212 SMs) | P3, (16, 48), 259174, CP2, C; eager; run 2 (reversed arm order) | checkpointed 2×forward+backward | 15.826 | 67.882 (FLA KCP) | 15.666 | 15.660 | 1.011 [1.010, 1.011] | 4.335 [4.332, 4.336] | 1.000 [1.000, 1.001] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; eager; run 1 | forward | 0.519 | 0.838 (FLA KCP) | 0.463 | 0.406 | 1.277 [1.271, 1.303] UNSTABLE | 2.066 [2.052, 2.072] | 1.139 [1.136, 1.149] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; eager; run 1 | backward (= forward+backward − forward) | 0.778 | 0.725 (FLA KCP) | 0.688 | 0.613 | 1.268 [1.262, 1.281] | 1.182 [1.182, 1.182] (medians) | 1.122 [1.118, 1.127] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; eager; run 1 | forward+backward | 1.296 | 1.563 (FLA KCP) | 1.151 | 1.020 | 1.270 [1.268, 1.290] UNSTABLE | 1.533 [1.530, 1.541] | 1.130 [1.126, 1.133] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; eager; run 1 | checkpointed 2×forward+backward | 2.186 | 2.547 (FLA KCP) | 1.991 | 1.809 | 1.207 [1.197, 1.217] | 1.403 [1.396, 1.412] | 1.096 [1.093, 1.107] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; graph replay; run 1 | forward | 0.306 | n/a (no graph-replay arm) | 0.298 | 0.299 | 1.025 [1.018, 1.026] | n/a | 0.998 [0.992, 1.000] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; graph replay; run 1 | backward (= forward+backward − forward) | 0.326 | n/a (no graph-replay arm) | 0.325 | 0.325 | 1.002 [0.999, 1.012] | n/a | 0.998 [0.994, 1.005] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; graph replay; run 1 | forward+backward | 0.633 | n/a (no graph-replay arm) | 0.623 | 0.624 | 1.013 [1.012, 1.015] | n/a | 0.998 [0.997, 1.000] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; graph replay; run 1 | checkpointed 2×forward+backward | 1.014 | n/a (no graph-replay arm) | 1.002 | 1.010 | 1.003 [0.952, 1.012] UNSTABLE | n/a | 0.993 [0.967, 0.995] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; eager; run 2 (reversed arm order) | forward | 0.518 | 0.838 (FLA KCP) | 0.462 | 0.407 | 1.272 [1.268, 1.282] | 2.061 [2.061, 2.061] unpaired | 1.137 [1.129, 1.140] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; eager; run 2 (reversed arm order) | backward (= forward+backward − forward) | 0.752 | 0.725 (FLA KCP) | 0.680 | 0.607 | 1.236 [1.228, 1.256] | 1.195 [1.195, 1.195] (medians) | 1.114 [1.110, 1.130] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; eager; run 2 (reversed arm order) | forward+backward | 1.270 | 1.563 (FLA KCP) | 1.142 | 1.014 | 1.250 [1.247, 1.262] | 1.543 [1.543, 1.543] unpaired | 1.123 [1.121, 1.133] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; eager; run 2 (reversed arm order) | checkpointed 2×forward+backward | 2.130 | 2.547 (FLA KCP) | 1.960 | 1.776 | 1.198 [1.194, 1.210] | 1.434 [1.434, 1.434] unpaired | 1.105 [1.101, 1.113] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; graph replay; run 2 (reversed arm order) | forward | 0.305 | n/a (no graph-replay arm) | 0.298 | 0.299 | 1.019 [1.016, 1.022] | n/a | 0.994 [0.991, 0.997] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; graph replay; run 2 (reversed arm order) | backward (= forward+backward − forward) | 0.328 | n/a (no graph-replay arm) | 0.325 | 0.327 | 1.002 [1.002, 1.004] | n/a | 0.995 [0.993, 0.999] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; graph replay; run 2 (reversed arm order) | forward+backward | 0.633 | n/a (no graph-replay arm) | 0.623 | 0.626 | 1.010 [1.009, 1.012] | n/a | 0.995 [0.995, 0.996] | | R200 sm_107a (212 SMs) | S26, (2, 6), 8192, CP2, C; graph replay; run 2 (reversed arm order) | checkpointed 2×forward+backward | 0.995 | n/a (no graph-replay arm) | 0.984 | 0.997 | 0.998 [0.992, 1.006] | n/a | 0.986 [0.982, 0.995] | Reading: - **Eager vs previous non-deterministic:** forward+backward is 1.123-1.130 on S26, 1.321-1.331 on DET C, 1.087-1.089 on DET D and 1.011-1.012 on P2 (CP4). Checkpointed steps are 1.096-1.105 (S26), 1.303-1.307 (DET C), 1.164-1.165 (DET D) and 1.129-1.130 (P2). - **Eager vs deterministic Cake:** forward+backward is 1.250-1.270 on S26, where the run 1 value of 1.270 is classed UNSTABLE. It is 1.461-1.474 on DET C, 1.643-1.646 on DET D and 1.073-1.076 on P2. Checkpointed steps are 1.198-1.207 (S26), 1.419-1.423 (DET C), 1.656-1.662 (DET D) and 1.212-1.213 (P2). - **Graph replay:** vs the previous package, the DET C, DET D and P2 graph cells are between 0.997 and 1.003. S26 graph cells are lower: 0.994-0.998 on forward, 0.995-0.998 on backward and forward+backward, and 0.986-0.993 on checkpointed, the smallest cell. These ratios include the entry-path difference. With both arms on the stand-in entry, the same-path code-only ratios on the graph-replay rows are 0.995-1.002. Vs deterministic Cake, graph cells are between 0.998 and 1.032. - **(16, 48) rows:** P1 and P3 are GPU-bound and at parity with the previous package, between 0.999 and 1.003 in every cell. Vs deterministic Cake they are between 0.999 and 1.017. - **Non-Cake:** the new package is faster than the strongest non-Cake implementation in every eager cell. The smallest ratio is 1.182-1.195, on S26 backward. On forward+backward it is 1.533-1.543 (S26), 4.811-4.853 (DET C), 5.035-5.041 (DET D), 15.659-15.663 (P2, vs FLA KCP only), 4.051-4.057 (P1) and 4.230-4.231 (P3). There is no non-Cake graph-replay arm. B200 (sm_100a) and B300/GB300 (sm_103a) rows are pending; the change is host-side only on every architecture. The kernel's other Cake variants, all on main, are the deterministic single-GPU `flashinfer.experimental.cake_gdn_det_train`, the non-deterministic single-GPU `flashinfer.experimental.cake.cake_gdn_train` (#8157) and the deterministic context-parallel `flashinfer.experimental.cake_gdn_det_train_kcp`; this PR tunes the non-deterministic context-parallel package from #8172, previously tuned in #8212, the two context-parallel variants share the entry `flashinfer.cake_gdn_train_kcp(deterministic=...)`, and the family ships on sm_100a, sm_103a and sm_107a. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> <!-- coderabbit-ai-generated:v1 --> ## Summary by CodeRabbit * **Improvements** * Repeated launch plans avoid redundant preparation. * Per-call workspaces skip empty or unused buffers in applicable forward and backward operations, reducing workspace requirements. * Calls on separate CUDA streams use separate ticket state. During CUDA graph capture, calls use fresh ticket state rather than sharing cached state. * Supported keyword options are validated, and repeated option sets can reuse cached validation results. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Yingyi Huang <averyh@nvidia.com>
This PR changes
flashinfer.experimental.cake_gdn_train_kcp, the non-deterministic context-parallel variant of Cake's Gated DeltaNet (GDN) chunked training kernel with gradients. Callers reach it throughflashinfer.cake_gdn_train_kcp(deterministic=False). The change is host-side only and has three parts:flashinfer.cake_gdn_train_kcpcaches the two package modules it routes to. Before, it re-imported the module on every call. This also removes that per-call import from thedeterministic=Trueroute, whose behavior is unchanged.Device programs, launch order, grids, streams and workspace are unchanged, and so are the checkpoint and graph-replay semantics. In every timed run (eager and graph replay, both ranks), outputs and every gradient are bitwise equal to main's non-deterministic package. Launch records (programs and launch count per phase) are also equal.
Speedup is baseline latency / new latency, so values above 1 mean the new package is faster. There are three baselines, and all of them ran in the same process as the new package:
All arms ran on one exclusive R200 node (sm_107a, 212 SMs; CUDA 13.0 runtime, PyTorch 2.14.1+cu130; no power capping observed). The setup was CP2 (2 ranks, GPUs 0-1) with BF16 q/k/v, FP32 g/beta and head dim 128.
Protocol: 5 groups, each running the arms in palindromic order 2 times. Each call is 12 timed iterations after 10 warm-up, with a 256 MiB L2 flush, device sync and barrier before every iteration. Latency is the median CUDA-event time of the slowest rank, and speedup is the median of the per-group ratios [min, max]. Two runs ran in separate processes, and run 2 reverses the arm order. Eager uses default options. Graph replay uses a caller-owned workspace with
graph="replay".How to read the table:
Five ratio cells are classed UNSTABLE because their group-to-group spread is above the 1 % tolerance, all on S26 eager forward+backward (two in run 1, three in run 2). They are shown as measured.
Table: R200 (sm_107a, 212 SMs), CUDA 13.0 runtime, PyTorch 2.14.1+cu130, CP2; latencies in ms (median CUDA-event time of the slowest rank); speedup = median of the per-group ratios [min, max].
Reading:
B200 (sm_100a) and B300/GB300 (sm_103a) rows are pending and will be added when they are ready; the change is host-side only on every architecture.
The kernel's other Cake variants, all on main, are the deterministic single-GPU
flashinfer.experimental.cake_gdn_det_train, the non-deterministic single-GPUflashinfer.experimental.cake.cake_gdn_train(#8157) and the deterministic context-parallelflashinfer.experimental.cake_gdn_det_train_kcp; this PR tunes the non-deterministic context-parallel package from #8172, the two context-parallel variants share the entryflashinfer.cake_gdn_train_kcp(deterministic=...), and the family ships on sm_100a, sm_103a and sm_107a.Summary by CodeRabbit