Repository navigation
exl3 cuda: the grouped experts kernel loads a tile ahead - #1505
Conversation
|
@ashhart could you please rerun the |
|
Thanks @ajensenwaud for splitting the load-ahead out and for the GLM-5.3-Flash A/B. We merged 49f3d38 onto main a1e6d34 (clean). fmt and lean are clean, and Two asks:
Then on our GB10 pair we'll record nvcc 13.2's limits for the three kernels and run the contract. We'll also repeat GLM-5.3-Flash at TP=2 against main (tokens drafted and plain, solo and four streams, three speed rounds) and run the Qwen3.5-MoE EXL3 pack on one GB10, comparing its tokens with main's. |
49f3d38 to
2f6a6e5
Compare
|
Thanks @ashhart, both done in
|
|
Thanks @ajensenwaud, both are done in 2f6a6e5:
Next on our side:
|
ae3e384 to
7b5d949
Compare
|
Thanks @ajensenwaud for rebasing. Our gate passed on it, and it was in tonight's landing batch. Then two of tonight's landings collided with it, both our doing:
You don't need to do anything yet. Once #1388 is on main, we'll rebase your two commits onto it ourselves. We'll keep both moves, and keep your load-ahead exactly as you wrote it. Then we'll re-run the kernel contract on a GB10, since the merge touches the same kernel. That puts it just after 1.2.0, which we're cutting this morning, rather than in it. If you'd rather do the rebase yourself, say so here and we'll wait for your push. |
warp_tiles issues the next k tile's lane words before decoding the current one (exllamav3's experts kernel at pf = 1). The decode, the mma chain and the warp sums are unchanged: same SASS arithmetic, same bits. On GB10, MiMo-V2.6-Flash's routed experts go from 110 to 97 us a layer step; GLM-5.3-Flash decodes the same tokens. Records: nvcc 13.0's measured on all five SMs (registers 145-168) and marked later_pending; nvcc 13.3's measured receipt in pending_133.zig; 13.2 stays pending (no 13.2 compiler here), and its stale grouped_1 override goes.
…n's loop under the contract warp_tiles takes its load as a template argument: PLAIN is main's loop, AHEAD the tile ahead. tf_exl3_grouped_* build AHEAD where __CUDA_ARCH__ >= 1200 and PLAIN below, so sm_80, sm_86 and sm_89 compile main's code (their SASS is main's, instruction for instruction, under nvcc 13.0 and 13.3) and keep main's records under every compiler. exl3_grouped.cuh holds the projection; contract_controls.cu builds main's loop for each codebook (tf_ctl_exl3_grouped_old_*) and two planted faults: the next load reads tile i + 2, or the last tile decodes the words before it. contract_exl3_grouped.zig registers the three kernels as replacements of main's loop: bit-equal at 1, 2 and 3 k tiles a warp, at GLM-5.3-Flash's and MiMo-V2.6-Flash's expert widths on one and two ranks and the Qwen3.5 EXL3 pack's, and at the tile edges, with each expert at its own width (lane words 2 and 3). Gate 4 holds the float64 reference's gamma bound on its stress rows (fp16 overflows, bf16 misses 240x; host-tested at the runner's seeds). Records: sm_80 to sm_89 are main's again (13.0, 13.2's 128 and 13.3's, measured equal); sm_120 and sm_121 carry the load-ahead's measured registers, 149/157/145 under 13.0 and 158/158/148 under 13.3; 13.2 stays pending there.
7b5d949 to
a39cdd2
Compare
|
Thank you @ajensenwaud. This is merged into main with your commits under your own name, so you're listed as a TensorFold contributor. It ships in the next release, credited to you in the changelog and the release notes. |
…o contract_controls.cu compiles again #1528's rebase onto #1505 placed MOSS-Image's control block between the pocket control's if block and its closing brace and lost that brace, so nvcc refuses the file (namespace definition not allowed) and every CUDA kernel-contract run fails to build. CI builds no CUDA kernels, so only the GB10 contract showed it.
|
Thank you. |
|
Thanks @ajensenwaud! The EXL3 grouped experts kernel that loads the next tile while it decodes, on sm_120 and sm_121, is in 1.2.1: https://github.com/ashhart/TensorFold/releases/tag/v1.2.1 |
warp_tiles, the body oftf_exl3_grouped_0/1/2, loads the next k tile's lane words while it decodes the current one, as exllamav3's experts kernel does at pf = 1. The decode, the mma chain and the warp sums are unchanged. Split out of #728 as asked there.The load-ahead builds on sm_120 and up only (
__CUDA_ARCH__ >= 1200). sm_80/86/89 compile main's loop: their SASS for the three kernels is byte-identical to main's under nvcc 13.0 and 13.3, and their records are main's. Only GB10 was measured, so only sm_12x changes.Two commits:
0e4b754eexl3 cuda: the grouped experts kernel loads a tile ahead.7b5d949bexl3 cuda: the grouped load-ahead on sm_120 up only, bit-equal to main's loop under the contract. The grouped projection moves fromexl3_experts.cutoexl3_grouped.cuh, with the tile loading as a template argument (main's loop, the load-ahead, or a planted fault).Contract
tf_ctl_exl3_grouped_old_0/1/2incontract_controls.cu, with its records.tf_exl3_grouped_0/1/2are registered as its replacement (contract_exl3_grouped.zig,contract_exl3_grouped_ref.zig).3 kernels: 3 pass gates 1-4, 0 fail, 0 known findings; 2 controls: 2 red as planted, 0 missed; 19 shapes bit-equal to the kernel it replaces. Gate 5 on the device passes for all six launches. The filter was a local change to the runner, so this is not a full-contract SUMMARY.Same bits, served
tensorfold-nativefrom mainb30d5b9d(A) and A plus the load-ahead (B), the same flags (--context 32768 --parallel 4, DFlash2, temperature 0, thinking off): 30/30 identical by token SHA, drafted and"draft": false, solo and 4 streams, including every 512-token speed run across arms and reps. drafted == plain and 4 streams == solo hold within each arm. (Run before the sm_120 gate; the sm_121 code is the same.)tf-mimo m1's teacher-forced logits over 1,905 steps are byte-equal with and without the load-ahead.Speed (GB10)
"draft": falsetf_exl3_grouped_2, µs a launch (nsys, CUDA graph nodes)GLM figures are medians of 3 reps, 512 tokens; GLM's prefill runs the prompt kernels, which this does not touch.
Records
Registers a thread (sm_80 / 86 / 89 / 120 / 121; 32,832 shared bytes a block on all):
sm_80/86/89 are main's values under 13.0, 13.2 and 13.3. sm_12x's 13.2 entries stay pending (no 13.2 compiler here). On sm_12x shared memory already bounds a block count at three an SM, so the extra registers cost no occupancy. A host test checks every SM under every compiler and goes red on a planted wrong value.
Host:
test-kernel-contract,test-cuda-host,test-kernel-symbols-host,compile-cuda-testsandnativepass;zig fmt --checkandgit diff --checkare clean; lean finds 426 problems, as main.