Repository navigation
Conversation
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
4b9ef6b to
ef9877d
Compare
for more information, see https://pre-commit.ci
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
[Medium impact] The PR appears safe to merge; no new actionable issue was found. SummaryAdds register-based BF16 MXFP8 kernels and splits the existing kernels into separate files.
Previous-thread context:
Diagram%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[MXFP8 quantization call] --> B[Check configuration and shape]
B --> C[Rowwise two-lane G2R]
B --> D[Bidimensional G2R]
B --> E[Rowwise one-lane G2R]
B --> F[Bidimensional G2S]
B --> G[General G2S fallback]
Reviews (18) · Last reviewed commit: "Merge branch 'main' into more_cutedsl_mx..." · Reviewed by Greptile |
113f73a to
cae94f5
Compare
0a9824e to
f67b1e5
Compare
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
ba1f62d to
5c3465a
Compare
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
3a80e08 to
dba8dbf
Compare
ff45b46 to
287505f
Compare
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
| is_writer_thread = tidx % THREADS_X_PER_MX_BLOCK == 0 | ||
| for row_idx in cutlass.range_constexpr(ELEMENTS_Y_PER_THREAD): | ||
| rX_row_i32 = cute.recast_tensor(rX[None, row_idx], Int32) | ||
| reciprocal = bf16_mx_scale_reciprocal(extract_mx_block_amax(rX_row_i32), MAX_EXPONENT) |
There was a problem hiding this comment.
for the case of WITH_ACT/WITH_DACT, the scale computed by this CuteDSL function is different from how thee CUDA kernel fused case compute it. CUDA version ignores NaN and the scale = e8m0(fmaxf(amax * max_norm_rcp, 0)), so it scale will be 0 when there is NaN. However this function in cuteDSL will return 0xFF for the scale here.
I know that the cast-only version in CUDA also uses the same scale calculation, which returns 0xFF. And numerically this should not matter, but since you have the byte-for-byte test between CuteDSL and CUDA, thought I might call it out for the fused activation case.
There was a problem hiding this comment.
I’d keep the new behavior and define all-NaN blocks to produce a NaN scale (0xFF), consistently with the cast-only path. The fused CUDA reduction currently loses the all-NaN condition by starting fmaxf from zero.
As we’re planning to transition to CuTeDSL kernels (and eventually retire the legacy CUDA implementations), we should probably prefer to standardize this behavior. And the remaining inconsistencies between backends can be fixed in a separate fix PR
There was a problem hiding this comment.
OK so... I'm just not gonna change anything?
There was a problem hiding this comment.
Yeah you do not need to change anything then, per Oleg. I'll fix the inconsistencies in the CUDA sidee in the next PR. Keeping this thread open and not resolved so I remember it though
…block scales - SiLU is x * sigmoid(x), as util/math.h computes it; x / (1 + exp(-x)) rounds differently, so FP32 SiLU differed from CUDA. - The general kernel carries one dbias sum down the column across its stages, as the CUDA kernels do, instead of adding 32-row partial sums. - With an activation fused, a block of only NaNs gets amax 0 and so scale 0, as in CUDA's generic kernel, in the register-resident, 2-lane rowwise and general kernels. Plain casts keep the NaN scale of CUDA's cast kernels. - FP32 dbias+dGeLU takes the register-resident kernel, whose dbias matches CUDA (the general kernel's still differs in the last bit for FP32). mxh2 parity against TE main (CUDA), tables off, 702 cases over BF16/FP16/FP32, all modes, layouts and fills including special values: 678 match (PR NVIDIA#3642 alone: 464). The rest are FP32 dbias with rowwise-only output, where CUDA adds row pairs (r, r + 32) before summing. Signed-off-by: Teddy Do <tdophung@nvidia.com>
for more information, see https://pre-commit.ci
Description
Add specialized MXFP8 CuTeDSL quantization kernels ported from #3459
And also some refactoring of the existing kernel -- so
quantize_mxfp8.pybecomesquantize_mxfp8_common.py: kernel config, signature, dispatching and registerationquantize_mxfp8_g2s_general.py: the same general MXFP8 kernel that handles all casesquantize_mxfp8_g2r_rowwise_1lane.py: the same old rowwise specialized kernelquantize_mxfp8_g2s_bidim.py: the same old bidim specialized kernelg2sandg2rmean the kernel uses SMEM / RMEM to quantizeNote: CuTeDSL cannot exactly mirror CUDA's implementation due to a bug in cutlass: NVIDIA/cutlass#3726
Type of change
Changes
Difference with the CUDA path:
Benchmark result (full sweep on the tip of this branch including things that aren't changed by this PR):
https://claude.ai/artifact/GsCNMy9S4YTxHnR7W3b1Vo?sk=DtZFlcQxJpBxCOlmq-W8_A
Or download it as a static HTML:
Quantization Benchmark .html
To examine which kernel is dispatched, expand "Data table" and you can see kernel names
Checklist: