Repository navigation
perf(cake_dense_projection_gemm): run the deterministic program at the sm_107a token counts its new plans win - #8363
Conversation
…e sm_107a token counts its new plans win The deterministic package's sm_107a rules for single token counts (flashinfer-ai#8303: 16231 and 16384 tokens) make several FP32 weight-gradient rows faster there than this package's split program. Re-measured on 208-SM and 212-SM parts against those plans at 16172, 16231 and 16384 tokens (op cells and whole backward / checkpointed step), this routes the losing token counts to the deterministic program: - K1_SPLIT_RULE_EXCLUDED_TOKENS also takes sm_107a rows: an entry holds from its SM count up at or above the row's SM-count floor (as before) and on exactly its SM count below it (the parts of K1_SPLIT_RULES_BY_SM); k1_plan applies the entries to both branches. - 208 SMs: 4096 -> 48, 4096 -> 64, 4096 -> 512, 5120 -> 48 at 16231 and 16384; 4096 -> 1024, 5120 -> 64 at 16231; 5120 -> 1024 at 16384. - 212 SMs: 4096 -> 512, 5120 -> 512 at 16231 and 16384; 4096 -> 1024, 5120 -> 48, 5120 -> 64 at 16231; 4096 -> 4096 runs the deterministic program (verdict None). - 216 SMs (not measured on 216-SM parts yet): 4096 -> 48, 4096 -> 512 at 16231 and 16384; 4096 -> 1024, 5120 -> 48, 5120 -> 64 at 16231. Every other token count, SM count and row keeps its verdict. Depends on flashinfer-ai#8303: before it merges these token counts run the earlier deterministic plans.
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 1 minute. View limit details
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. |
|
@flashinfer-bot run tests/experimental/test_cake_dense_projection_gemm.py tests/experimental/test_cake_dense_projection_det_gemm_names.py tests/experimental/test_cake_dense_projection_det_gemm.py |
…1024 FP32 at 16384 tokens on 208 SMs A second measurement of 5120 -> 1024 FP32 on a 208-SM part (16172, 16231 and 16384 tokens, four more runs on another part), taken together with the first, keeps this package's program within the rule at 16384 tokens: backward pass 0.8923 / 0.8886 and checkpointed step 0.9847 / 0.9655 of the deterministic program (ratio of the medians over the runs, graph replays / eager launches). The 208-SM entry for that row is removed. 4096 -> 1024 FP32 at 16231 tokens on 212 SMs, measured a second time as well, keeps its entry: over both measurements its checkpointed step is 1.0213 of the deterministic program in graph replays.
|
@flashinfer-bot run tests/experimental/test_cake_dense_projection_gemm.py tests/experimental/test_cake_dense_projection_det_gemm_names.py tests/experimental/test_cake_dense_projection_det_gemm.py |
|
@flashinfer-bot run tests/experimental/test_cake_dense_projection_gemm.py tests/experimental/test_cake_dense_projection_det_gemm_names.py tests/experimental/test_cake_dense_projection_det_gemm.py |
…192-wide 4096 -> 1024 FP32 and six more deterministic token counts (#8438) ## Summary The Cake dense projection GEMM family covers BF16-input dense and batched projection GEMMs, with BF16 or FP32 weight-gradient output, and an FP32 router GEMM. In `flashinfer.experimental.dense_projection_gemm`, the keyword-only `deterministic` flag selects the variant: `deterministic=True` (the default) calls `flashinfer.experimental.dense_projection_det_gemm`, and `deterministic=False` runs the split-K / stream-K programs (#8190, #8238). The family ships on `sm_100a` (GB200), `sm_103a` (GB300) and `sm_107a` (R200). This PR changes only the planner of `deterministic=False`. The change applies to the projection weight gradient (K1) on `sm_107a` parts with 216 or more SMs. There are no kernel changes. #8363 shipped the 216-SM entries of the deterministic token counts without a 216-SM measurement. These entries are now measured on two 216-SM parts at 16172, 16231 and 16384 tokens. This PR uses the rule of #8363. A point keeps the split-K program only if all three conditions hold: - (a) At the op level, the split-K program was faster than the deterministic program in every run. This requires a one-sided paired sign test p < 0.05 and a median time ratio below 0.99, in eager launches and in CUDA graph replays. - (b) Next to a kernel holding 8, 16 or 32 SMs on another stream, it was no more than 3 % slower than the deterministic program, in both launch orders. - (c) It left the backward pass and the checkpointed step at most 1.3 % slower than the deterministic program. This is the ratio of the medians over the runs, eager and graph. Otherwise, the point runs the deterministic program. Changes: - `4096 -> 1024` FP32 on exactly 216 SMs, 16172 to 16384 tokens: the 192-wide row-major program at one split (176 CTAs, as on 212 SMs since #8275) replaces 256-wide tiles at one split (128 CTAs). 16231 tokens keep the deterministic program. - The deterministic program at 6 more points, from 216 SMs up: FP32 `4096 -> 32` at 16231 tokens; `4096 -> 64` at 16231 and 16384; `5120 -> 48` and `5120 -> 64` at 16384; BF16 `5120 -> 1024` at 16231. - The 7 existing 216-SM points are confirmed. Other points, SM counts and architectures are unchanged. **Accuracy:** At `4096 -> 1024` FP32 (16172 and 16384 tokens), the output of the 192-wide program is bitwise equal to the output of the previous plan (256-wide tiles, one split) on the same inputs. The 6 new deterministic points return the output of the deterministic program. **Speedups** (ratio = baseline us / new us; above 1 means this PR is faster): - `4096 -> 1024` FP32 at 16172 / 16384 tokens, graph mode: - previous/new: wgrad 1.160 / 1.164, bwd 1.106 / 1.122, 2fwd+bwd 1.064 / 1.070. - det/new: wgrad 1.680 / 1.418, bwd 1.420 / 1.270, 2fwd+bwd 1.185 / 1.071. - SOTA/new: wgrad 0.919 / 0.923, bwd 0.892 / 0.893, 2fwd+bwd 0.972 / 0.960. - Eager mode previous/new: wgrad 1.177 / 1.179, bwd 1.106 / 1.108, 2fwd+bwd 1.052 / 1.016. - The 6 new deterministic points against the previous plan (previous/new; below 1 means the deterministic program is slower): - Graph: wgrad 0.980 to 1.010 (geomean 0.996), bwd 0.988 to 1.009 (geomean 0.995), 2fwd+bwd 0.999 to 1.007 (geomean 1.003). - Eager: wgrad 0.973 to 1.007 (geomean 0.990), bwd 0.991 to 1.015 (geomean 0.999), 2fwd+bwd 0.994 to 1.001 (geomean 0.998). - The lowest value is `4096 -> 32` at 16231 tokens, eager wgrad 0.973. There, the deterministic program is 2.7 % slower at the op. - At the five FP32 points, the split-K program missed part (a) or (b) of the rule in at least one of the 8 run-and-mode cells. It missed 1 of 8 at `4096 -> 32` and 5 to 8 of 8 at the other four. - At BF16 `5120 -> 1024`, 16231 tokens, the split-K program passed (a) and (b) in all 8 cells. The deterministic program is 2.0 % slower at the op there (wgrad previous/new 0.980). However, the eager backward pass with the split-K program was 1.5 % slower than with the deterministic program (ratio of the medians over the runs; eager bwd previous/new 1.015). This is above the 1.3 % limit of (c), so that point runs the deterministic program. Definitions: - **Rows:** 48 = 8 points x 3 ops x 2 modes, graph rows first; all on 216 SMs. - **Ops:** wgrad = weight gradient `[d_out, d_in]` (output dtype as in the `out` column) from BF16 activations `[T, d_in]` and BF16 output gradients `[T, d_out]`. bwd = input gradient (BF16) + wgrad. 2fwd+bwd = checkpointed step (2 x forward + bwd). - **Modes:** g = CUDA graph replay, e = eager. - **Latency:** Median us over 4 runs per row. The runs use two 216-SM GPUs. Each GPU has one long-lived process over all rows and a fresh process per row, with one arm order per GPU. In a run, all arms of a row are interleaved in paired groups: 15 groups of 20 steps for wgrad, 9 groups for bwd and 2fwd+bwd. L2 is cold before every iteration. The time is the CUPTI GPU time of the operation (first kernel begin to last kernel end, all launches). - **Baselines:** - det Cake = `deterministic=True` at FlashInfer main eabf03f (the deterministic package with the #8303 plans; the measured deterministic package is the same tree). - previous Cake = `deterministic=False` at FlashInfer main eabf03f, without this PR. It uses the same kernel programs as this PR. Its forward and input gradient are the deterministic programs. - new = `deterministic=False` with this PR. At the 6 new deterministic points, it runs the deterministic program, so new us is the det Cake measurement. The `deterministic=False` call that dispatches to it was not timed separately. - SOTA = cuBLAS / cuBLASLt, the vendor GEMM library for `sm_107a` and the strongest non-Cake GEMM available there. For wgrad, it is the fastest correct launch among `torch.mm` and the cuBLASLt heuristic's top-8 algorithms. For bwd and 2fwd+bwd, it is the fastest correct library launch per op. - Ratio = baseline us / new us, computed from the medians in the table; above 1.000 = this PR is faster. - **Setup:** R200 (`sm_107a`), 216 SMs, driver 615.71.10; CUDA 13.4 (nvcc 13.4.92), PyTorch 2.14.1+cu130, cuBLAS 13.8.0.4. - **Noise:** - Per-run paired previous/new: `4096 -> 1024` wgrad 1.156 to 1.196, bwd 1.086 to 1.124, 2fwd+bwd 1.044 to 1.061; the 6 deterministic points wgrad 0.934 to 1.018, bwd 0.966 to 1.004, 2fwd+bwd 0.985 to 1.029. - The two GPUs differ in speed by a few percent. Thus, a median over 4 runs (2 per GPU) can differ from the per-run paired ratios. At BF16 `5120 -> 1024`, every per-run paired bwd previous/new is 0.981 to 0.995, while the ratio of the medians is 1.015 in eager mode. - Some samples show the software power-cap throttle flag. All arms of a row run interleaved in one process, so the ratios hold, but absolute times can be a few percent high. *Table: one row per point, op and mode; R200 (`sm_107a`), 216 SMs, CUDA 13.4; latencies in us (median over 4 runs); ratios = baseline us / new us.* | GPU | SMs | `d_in -> d_out` | out | T | op | mode | det Cake us | SOTA us | previous Cake us | new us | det/new | SOTA/new | previous/new | |---|---|---|---|---|---|---|---|---|---|---|---|---|---| |R200|216|4096 -> 1024|FP32|16172|wgrad|g|90.10|49.30|62.20|53.62|1.680|0.919|1.160| |R200|216|4096 -> 1024|FP32|16172|bwd|g|144.93|91.06|112.83|102.06|1.420|0.892|1.106| |R200|216|4096 -> 1024|FP32|16172|2fwd+bwd|g|237.76|194.87|213.32|200.56|1.185|0.972|1.064| |R200|216|4096 -> 1024|FP32|16384|wgrad|g|76.52|49.82|62.82|53.98|1.418|0.923|1.164| |R200|216|4096 -> 1024|FP32|16384|bwd|g|128.83|90.58|113.85|101.47|1.270|0.893|1.122| |R200|216|4096 -> 1024|FP32|16384|2fwd+bwd|g|217.54|194.93|217.28|203.04|1.071|0.960|1.070| |R200|216|4096 -> 32|FP32|16231|wgrad|g|20.49|20.56|20.20|20.49|1.000|1.003|0.986| |R200|216|4096 -> 32|FP32|16231|bwd|g|38.01|35.91|37.54|38.01|1.000|0.945|0.988| |R200|216|4096 -> 32|FP32|16231|2fwd+bwd|g|75.78|73.70|75.74|75.78|1.000|0.973|0.999| |R200|216|4096 -> 64|FP32|16231|wgrad|g|20.58|22.63|20.79|20.58|1.000|1.100|1.010| |R200|216|4096 -> 64|FP32|16231|bwd|g|38.34|38.01|38.21|38.34|1.000|0.991|0.997| |R200|216|4096 -> 64|FP32|16231|2fwd+bwd|g|75.30|75.64|75.82|75.30|1.000|1.005|1.007| |R200|216|4096 -> 64|FP32|16384|wgrad|g|20.94|22.73|20.83|20.94|1.000|1.085|0.995| |R200|216|4096 -> 64|FP32|16384|bwd|g|38.64|38.34|38.42|38.64|1.000|0.992|0.994| |R200|216|4096 -> 64|FP32|16384|2fwd+bwd|g|76.14|75.92|76.34|76.14|1.000|0.997|1.003| |R200|216|5120 -> 48|FP32|16384|wgrad|g|23.24|24.74|23.41|23.24|1.000|1.065|1.007| |R200|216|5120 -> 48|FP32|16384|bwd|g|44.85|43.47|44.55|44.85|1.000|0.969|0.993| |R200|216|5120 -> 48|FP32|16384|2fwd+bwd|g|90.12|88.88|90.29|90.12|1.000|0.986|1.002| |R200|216|5120 -> 64|FP32|16384|wgrad|g|23.28|25.22|23.19|23.28|1.000|1.083|0.996| |R200|216|5120 -> 64|FP32|16384|bwd|g|43.95|43.82|43.57|43.95|1.000|0.997|0.991| |R200|216|5120 -> 64|FP32|16384|2fwd+bwd|g|89.14|88.88|89.50|89.14|1.000|0.997|1.004| |R200|216|5120 -> 1024|BF16|16231|wgrad|g|64.54|50.46|63.28|64.54|1.000|0.782|0.980| |R200|216|5120 -> 1024|BF16|16231|bwd|g|133.20|115.45|134.46|133.20|1.000|0.867|1.009| |R200|216|5120 -> 1024|BF16|16231|2fwd+bwd|g|257.66|236.33|258.33|257.66|1.000|0.917|1.003| |R200|216|4096 -> 1024|FP32|16172|wgrad|e|89.33|49.39|62.30|52.95|1.687|0.933|1.177| |R200|216|4096 -> 1024|FP32|16172|bwd|e|145.58|91.82|113.44|102.60|1.419|0.895|1.106| |R200|216|4096 -> 1024|FP32|16172|2fwd+bwd|e|239.96|195.78|215.59|204.90|1.171|0.955|1.052| |R200|216|4096 -> 1024|FP32|16384|wgrad|e|76.44|49.93|62.94|53.39|1.432|0.935|1.179| |R200|216|4096 -> 1024|FP32|16384|bwd|e|129.36|91.78|114.95|103.77|1.247|0.884|1.108| |R200|216|4096 -> 1024|FP32|16384|2fwd+bwd|e|219.94|196.50|209.68|206.32|1.066|0.952|1.016| |R200|216|4096 -> 32|FP32|16231|wgrad|e|20.73|20.92|20.17|20.73|1.000|1.009|0.973| |R200|216|4096 -> 32|FP32|16231|bwd|e|38.46|36.70|38.13|38.46|1.000|0.954|0.991| |R200|216|4096 -> 32|FP32|16231|2fwd+bwd|e|78.14|75.71|77.73|78.14|1.000|0.969|0.995| |R200|216|4096 -> 64|FP32|16231|wgrad|e|20.86|23.15|20.80|20.86|1.000|1.110|0.997| |R200|216|4096 -> 64|FP32|16231|bwd|e|38.94|39.08|38.90|38.94|1.000|1.004|0.999| |R200|216|4096 -> 64|FP32|16231|2fwd+bwd|e|78.22|77.99|78.26|78.22|1.000|0.997|1.001| |R200|216|4096 -> 64|FP32|16384|wgrad|e|21.20|23.25|20.89|21.20|1.000|1.097|0.985| |R200|216|4096 -> 64|FP32|16384|bwd|e|39.37|39.28|39.06|39.37|1.000|0.998|0.992| |R200|216|4096 -> 64|FP32|16384|2fwd+bwd|e|78.97|78.28|78.64|78.97|1.000|0.991|0.996| |R200|216|5120 -> 48|FP32|16384|wgrad|e|23.46|25.15|23.63|23.46|1.000|1.072|1.007| |R200|216|5120 -> 48|FP32|16384|bwd|e|45.25|44.25|45.30|45.25|1.000|0.978|1.001| |R200|216|5120 -> 48|FP32|16384|2fwd+bwd|e|93.17|91.17|93.30|93.17|1.000|0.979|1.001| |R200|216|5120 -> 64|FP32|16384|wgrad|e|23.42|25.70|23.30|23.42|1.000|1.097|0.995| |R200|216|5120 -> 64|FP32|16384|bwd|e|44.64|44.46|44.41|44.64|1.000|0.996|0.995| |R200|216|5120 -> 64|FP32|16384|2fwd+bwd|e|92.55|91.19|92.42|92.55|1.000|0.985|0.999| |R200|216|5120 -> 1024|BF16|16231|wgrad|e|64.57|50.54|63.30|64.57|1.000|0.783|0.980| |R200|216|5120 -> 1024|BF16|16231|bwd|e|133.64|115.54|135.58|133.64|1.000|0.865|1.015| |R200|216|5120 -> 1024|BF16|16231|2fwd+bwd|e|260.66|236.04|259.15|260.66|1.000|0.906|0.994| Other Cake variants of this family (the deterministic package, the batched MLA head rows, the FP32 router GEMM, BF16 and FP32 weight-gradient outputs) and the `sm_100a` / `sm_103a` planners are unchanged; 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 * **Performance** * Dense projection GEMM now uses refined execution plans for selected GPU configurations and input sizes, including 216-SM devices. * The updated plans cover specific FP32 and BF16 workloads and token counts, with exclusions where a tuned plan does not apply. * Execution selection remains deterministic for the supported configurations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Yingyi Huang <averyh@nvidia.com>
Summary
The Cake dense projection GEMM family covers BF16-input dense and batched projection GEMMs, with BF16 or FP32 weight-gradient output. It also covers an FP32 router GEMM (256 experts, BF16x3 emulation). In
flashinfer.experimental.dense_projection_gemm, a keyword-onlydeterministicflag selects the variant.deterministic=True(the default) callsflashinfer.experimental.dense_projection_det_gemm.deterministic=Falseruns the split-K / stream-K programs (#8190, #8238). The family ships onsm_100a(GB200),sm_103a(GB300) andsm_107a(R200).This PR changes only the planner. It affects only
deterministic=False, the projection weight gradient (K1), FP32 output rows, andsm_107aparts with 208 SMs, 212 SMs, or 216 or more SMs. #8303 gives the deterministic package newsm_107aplans for single token counts (16231 and 16384 tokens). At some of these points, the deterministic program is now as fast as or faster than the split-K program. This PR runs the deterministic program at those points.The split-K program keeps a point only if both conditions hold in eager and graph mode:
Otherwise, the point runs the deterministic program. The measured token counts are 16172, 16231 and 16384. 20 measured points change (208 SMs: 10, 212 SMs: 10). The other 46 measured points keep their split-K plans. Other token counts, other SM counts,
sm_100a,sm_103aand all kernels are unchanged.Changed points (
d_in -> d_out, FP32 output):4096 -> 48,4096 -> 64,4096 -> 512,5120 -> 48at 16231 and 16384 tokens;4096 -> 1024,5120 -> 64at 16231.4096 -> 512,5120 -> 512at 16231 and 16384;4096 -> 1024,5120 -> 48,5120 -> 64at 16231;4096 -> 4096at every token count from 16172 to 16384 (measured at 16172, 16231 and 16384).4096 -> 48,4096 -> 512at 16231 and 16384;4096 -> 1024,5120 -> 48,5120 -> 64at 16231.This PR depends on #8303 and must merge after it. Before #8303, these points run the earlier deterministic plans, which are slower. The "det Cake (main)" column of the table shows them.
The entries for 216 or more SMs were not measured on such parts. They are not in the table.
Speedups (graph mode, geomean over the 20 rows of each op, range in parentheses; ratio = baseline us / new us, above 1 means this PR is faster):
In eager mode, the previous/new geomeans are 1.024 (wgrad), 1.023 (bwd) and 1.018 (2fwd+bwd). The largest graph gains (previous/new) are at 212-SM
4096 -> 4096: wgrad 1.136 to 1.148, bwd 1.097 to 1.103. 208-SM4096 -> 1024at 16231 gives wgrad 1.139 and 2fwd+bwd 1.104.4096 -> 512gives wgrad 1.094 and 1.100 at 208 SMs, and 1.053 and 1.059 at 212 SMs.In graph mode, this PR is slower than the previous version in 9 of 20 wgrad rows, 11 of 20 bwd rows and 5 of 20 2fwd+bwd rows. The lowest are 212-SM
5120 -> 512at 16231 and 16384 (wgrad 0.951 and 0.955). There, the split-K program was faster on most GPUs, but not on all of them. At 16231, the deterministic program was as fast or faster on one of the eight GPUs. At 16384, it was as fast or faster on one GPU, and on a second GPU the split-K program was less than 1 % faster. 212-SM4096 -> 1024at 16231 gives wgrad 0.970 and bwd 0.976, but 2fwd+bwd 1.021, because the checkpointed step of the split-K program is slower. This point was measured twice; the rule uses the runs of both measurements together. 208-SM and 212-SM5120 -> 48,5120 -> 64at 16231 (and 208-SM5120 -> 48at 16384) give wgrad 0.976 to 0.986. At these points, the split-K program was not faster in every run, or its checkpointed step was more than 1.3 % slower. The rule therefore selects the deterministic program.In graph mode, the library baseline is faster than the new plan (SOTA/new below 1) in 6 of 20 wgrad rows, 13 of 20 bwd rows and 17 of 20 2fwd+bwd rows.
[d_out, d_in](FP32 output) from BF16 activations[T, d_in]and BF16 output gradients[T, d_out]; bwd = input gradient (BF16) + wgrad; 2fwd+bwd = checkpointed step (2 x forward + bwd). Modes: g = CUDA graph replay, e = eager.4096 -> 1024at 16231 tokens: 24 runs on 16 GPUs, from two measurements). In a run, all arms of a row are interleaved in paired groups: 15 groups of 20 steps for wgrad, 9 groups for bwd and 2fwd+bwd. L2 is cold before every iteration. The time is the CUPTI GPU time of the operation (first kernel begin to last kernel end, all launches).deterministic=Truewith fix(cake_dense_projection_det_gemm): take the cluster rendezvous before the 2-CTA tensor-memory allocation, and add sm_107a row rules #8303. previous Cake =deterministic=Falsewith fix(cake_dense_projection_det_gemm): take the cluster rendezvous before the 2-CTA tensor-memory allocation, and add sm_107a row rules #8303 and without this PR (its forward and input gradient are the fix(cake_dense_projection_det_gemm): take the cluster rendezvous before the 2-CTA tensor-memory allocation, and add sm_107a row rules #8303 deterministic programs). new =deterministic=Falsewith this PR: it runs the deterministic program at every row of the table, so new us is the det Cake (fix(cake_dense_projection_det_gemm): take the cluster rendezvous before the 2-CTA tensor-memory allocation, and add sm_107a row rules #8303) measurement (thedeterministic=Falsecall that dispatches to it was not timed separately). SOTA = cuBLAS / cuBLASLt, the vendor GEMM library forsm_107a: for wgrad the fastest correct launch amongtorch.mmand the cuBLASLt heuristic's top-8 algorithms; for bwd and 2fwd+bwd the fastest correct library launch per op. Ratio = baseline us / new us; above 1.000 = this PR is faster.sm_107a), 212 SMs (driver 620.62) and 208 SMs (driver 615.71.10); CUDA 13.4 (nvcc 13.4.92), PyTorch 2.14.1+cu130, cuBLAS 13.8.0.4.4096 -> 1024at 16231 tokens, the per-run paired 2fwd+bwd previous/new is 0.983 to 1.041 (graph) and 0.986 to 1.043 (eager). An identical-plan control in the same runs, det Cake (fix(cake_dense_projection_det_gemm): take the cluster rendezvous before the 2-CTA tensor-memory allocation, and add sm_107a row rules #8303) against det Cake (main) on the same row at 16172 and 16384 tokens (both use the same wgrad plan there), gives a per-run 2fwd+bwd ratio of 0.955 to 1.016 (graph) and 0.950 to 1.022 (eager).Table: one row per point, op and mode; R200 (
sm_107a), CUDA 13.4; latencies in us; ratios = baseline us / new us.d_in -> d_out