perf(kda): preserve SM90 workspace byte layout with bulk copies - #115
Conversation
|
Thanks for working on this optimization. Could you explicitly credit flash-flash-kda as the source of the raw workspace transport idea in the PR description and/or code comments? |
icavan
left a comment
There was a problem hiding this comment.
The SM90 intracard path's pre_scan appears to still load ws_kd and ws_kr through TensorMap/TMA (make_ws_qkd_atom). Since this change stores the physical K_INTER byte images and updates K2 to restore them via raw bulk G2S copies, how is the pre_scan path handled?
Could you please make sure this workspace-format change is also applied correctly to the intracard path—for example, by migrating the corresponding pre_scan loads to raw bulk G2S or otherwise preserving format compatibility—and validate it with tests/test_kda_sm90_intracard_cp.py? As written, it looks possible for pre_scan to reinterpret the raw byte image as the previous logical workspace layout.
Thanks for pointing this out. I’ll take a closer look at the intracard |
|
Hi, I have one dependency question before updating the package metadata. This PR's raw workspace path calls For context, the previous Tensor TMA store path did manually elect one issuing lane: if warp_idx == 0:
with cute.arch.elect_one():
cute.copy(tma_atom_ws_qd, ...)
...The optimized code keeps that manual We therefore cannot simply wrap the raw copies in Would you prefer that we:
I have not changed |
@fkuner #119 Please also remember to update the perf in README.md & BENCH_xxx.md after your optimizations. |
257a55a to
38093d2
Compare
Summary
K_INTERSMEM byte image for the SM90 KDAqd,kd, andkrworkspacescp.async.bulkS2G/G2S copiesinvandmqkon layout-aware Tensor TMApre_scanconsumerREADME.mdandBENCHMARK_H200.mdAcknowledgment
The raw workspace transport idea comes from Shikhar Mishra's Flash-Flash-KDA, which identified the same fragmented TensorMap workspace boundary and preserved the physical shared-memory byte image with non-tensor
cp.async.bulkcopies. This PR adapts that idea to cuLA's SM90 CuTeDSL implementation and itsCHUNK=16workspace ABI. The source is also credited next to the K1 raw workspace stores in code.Motivation
K1 and K2 use the same
K_INTERshared-memory layout forqd,kd, andkr. The previous path stored these tensors through TensorMap/TMA into a logical linear workspace and reconstructed the layout in K2. Flash-Flash-KDA identified this layout traversal as a source of fragmented TMA work for the same workspace boundary; cuLA's NCU results show the corresponding reduction in observable store/load-class executions, XBAR traffic, and kernel duration. NCU does not expose the internal TensorMap segment count directly.Because both kernels agree on the physical layout:
pre_scancopy the same image back with raw bulk G2S.The implementation deliberately leaves the other workspace tensors on Tensor TMA where layout-aware transport remains appropriate.
Figure 1. Raw bulk copies preserve three 4 KiB physical K_INTER byte images for qd/kd/kr; inv/mqk remain on layout-aware Tensor TMA.
Workspace transport
The optimization applies to
qd,kd, andkr, whose physicalK_INTERshared-memory layout is identical across their producers and consumers. Each cuLA tensor is a contiguous 4 KiB byte image (16 × 128 × sizeof(bf16)).The baseline uses layout-aware Tensor TMA to convert between the
K_INTERSMEM layout and a logical linear GMEM workspace. The optimized path preserves each tensor as an opaque byte image: K1 writes three contiguous payloads with raw bulk S2G copies, while K2 restores all three and intracardpre_scanrestoreskd/krwith raw bulk G2S copies.invandmqkare intentionally unchanged and continue to use layout-aware Tensor TMA. The diagram is conceptual and does not claim an exact internal TensorMap segment count; the observable NCU evidence is reported below.CuTeDSL compatibility
CuTeDSL 4.6.0 added the missing automatic
elect_oneinsidecute.copyfor async bulk-copy atoms; nesting a manual election around those calls is invalid in 4.6+. The raw workspace calls use a runtime version check incula/ops/kda/sm90/_common.py: CuTeDSL <4.6 gets an explicitelect_one, while 4.6+ relies on the generated election. The retained Tensor TMA stores keep their existing manual election. This preserves the declarednvidia-cutlass-dsl>=4.4.2compatibility range; validation used CuTeDSL 4.6.1.Performance
Benchmark provenance
origin/main5161546581cd6fecf2ad276dfa7a23a812208cf3; the KDA source baseline isd78f0075c69135fe191358fe8daf10e7383009d4(the later main commit only refreshed benchmark/docs files)4e67e4f55d241af600235898b55cde09bd90c165; current PR head:988693a31ecaf0e331d92ea5e56f355e11f8e470H=64,D=128,safe_gate=True, no initial state, 25 warmup iterations, 100 measured iterations, IQR meanPYTHONPATHunset to avoid accidentally using an older source checkoutAbsolute optimized result vs FLA
The refreshed 28-shape fixed/variable-length sweep reports 2.72x arithmetic-mean speedup (2.43x geometric mean), with a range of 1.56–7.56x. These are the values now recorded in
BENCHMARK_H200.mdand summarized inREADME.md.Workspace A/B against the latest main KDA baseline
The same 28 configurations were run with the raw workspace change disabled/enabled on the same H200 setup. The benchmark's default
use_intracard_cp=Noneselects the serial K1+K2 path, so this isolates the workspace transport from intracard-CP work.27/28 rows were faster; the single B=1/T=512 row was within small-kernel timing noise (0.990x). The fastest row improved by 1.2505x (20.04%).
Representative rows:
The baseline and optimized runs produced the same FLA-relative accuracy at printed precision (
rel_rmse=0.004568–0.004924,rel_max=0.007772–0.015000,mean_diff=0.000011–0.000013). The dedicated deterministic A/B checks also reported bitwise-identical output and final state.Intracard CP
Intracard CP is reported separately and is not included in the workspace A/B headline. On the optimized implementation,
use_intracard_cp="auto"versusFalseengages on 28/32 configurations and gives a 4.29x geometric-mean speedup, with a range of 1.93–7.83x. This measures CP planning,pre_scan, merge, and segmented K2 behavior in addition to the workspace transport.Comparison with Flash-Flash-KDA
Flash-Flash-KDA's deep dive reports isolated workspace-transport latency reductions of 23%, 34%, and 37% on H100 for fixed, uneven packed, and uniform packed inputs with
CHUNK=16. cuLA uses the sameCHUNK=16ABI. The cuLA H200 full non-intracard A/B above reduces total latency by 15.74% overall, with a best row reduction of 20.04%. This is comparable in direction and end-to-end scale, but is not claimed as an exact reproduction because the hardware and the measured scope differ.Nsight Compute evidence
NCU 2025.2.1,
--set full, B=1 / T=4096 / H=64:K1 accounts for about 88% of the combined NCU duration reduction, matching the hypothesis that workspace stores were the dominant opportunity.
NCU groups both
UTMASTGandUBLKCP.Gunder its TMA-store-class metric. The optimized K1 SASS adds threeUBLKCP.G.Sworkspace operations per CTA, but the aggregate dynamic count falls from 50 to 5 operations per CTA: three raw workspace copies plus the two retained Tensor TMA stores. Internal TensorMap layout-walk segments are not exposed as a standalone NCU counter, so the evidence is the observable instruction/request count, XBAR traffic, and kernel duration rather than an inferred segment count.Validation
pre-commit run --all-filespython -m py_compile cula/ops/kda/sm90/k1.py cula/ops/kda/sm90/k2.py cula/ops/kda/sm90/cp/pre_scan.py benchmarks/bench_kda_sm90_prefill.pypython -m pytest tests/test_kda_sm90_prefill_vs_fla.py tests/test_kda_sm90_intracard_cp.py -q(28 passed, 15 skipped)benchmarks/bench_kda_sm90_prefill.py --mode bothsweep on the H200/CUDA 12.9/FLA 0.5.0 environmentbenchmarks/bench_kda_sm90_cp.pyon the same optimized environment