Repository navigation
[Fix] Keep the fast_divmod multiplier within 32 bits - #170
Merged
Merged
Conversation
The precomputed multiplier came from the Hacker's Delight search for the whole uint32 range, which needs 33 bits for some divisors. cuda_fastdiv_precompute_m truncated it to uint32, so fast_divmod(7, 7) returned 0 and 379 of the divisors 1-1024 gave wrong quotients. The dividend of fast_divmod is a non-negative int32, so use p = 31 + ceil(log2(b)) and m = ceil(2^p / b) as CUTLASS FastDivmod does. This is exact for dividends below 2^31 and m always fits in 32 bits. Signed-off-by: 0z5a <dezhen.lu@student.uni-tuebingen.de>
- State the dividend range as 0 <= a < 2^31 in the fast_divmod docstring. - Move the fast_divmod primitive import to the top of the test file. - Allocate test tensors on "cuda" directly under @requires.nvgpu_sm80. - Note why the host reference a * multiplier fits in int64. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
|
/ok to test e54034a |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
fast_divmodreturns wrong quotients for many divisors.fast_divmod(7, 7)gives 0. This PR changes how the multiplier is precomputed so that it is exact for every dividendfast_divmodaccepts.Why
cuda_fastdiv_precompute_msearched for the Hacker's Delight multiplier for the whole uint32 range. For some divisors that multiplier needs 33 bits, andreturn uint32(m)dropped the top bit. Forb = 7it computedm = 2^32 + 613566757,s = 3, and the kernel ran withm = 613566757.Of the divisors 1 to 1024, 379 are affected. For example,
b = 56is wrong ata = 56, where it returns 0.This reaches real kernels.
hopper_matmulmatmul_v4tov6andblackwell_matmulmatmul_v4tov6dividelinear_idxbynum_m_blocks * swizzle_size. Inhopper_matmul/matmul_v4(block_m = 128,block_n = 256,swizzle_size = 4),m_size = 1792andn_size = 4096give a divisor of 56, and 168 of the 224 tiles get a wronggroup_idxfrom the same multiplier.How
The dividend of
fast_divmodis a non-negative int32:cuda_fastdivtakesa: i32, and the docstring says "int32, must be >= 0". So the multiplier only has to be exact below 2^31, and then it fits in 32 bits:p = 31 + ceil(log2(b))m = ceil(2^p / b), which is below 2^32shift = p - 32This is the formula in
find_divisorin CUTLASSfast_math.h. The runtime (mul.hi.u32+shr.u32) and the power-of-2 path do not change.Dividends of 2^31 and above stay out of contract, and the docstrings now say
0 <= a < 2^31. They were never reliable: the power-of-2 path shifts anint32arithmetically. Every caller in the repo passes a non-negative int32 block index.Testing
Host tests ran on the Grace CPU of a GH200: GCC 13.3, CUDA 13.2, PyTorch 2.14.1+cu130, tilus
mainat f23018a. The host-side numbers below run the realcuda_fastdiv_precompute_m/s, built into acpu_kernelwith nvcc, and evaluatemul.hi+shrin Python.maina < 2^20, plus the top of the range)k*b - 1 < 2^31)b= 7, 56, 641, 1023, 2^31 - 1, allain[0, 2^31)matmul_v4shape above, tiles with a wronggroup_idxtests/instructions/test_fast_divmod.pyis new:maintest_precomputed_multiplier_is_exact(1065 divisors, boundary dividends)test_fast_divmod[0-7],[0-56],[2147483392-7]test_fast_divmod[0-3],[0-64](controls)GPU tests ran on GH200 (
sm_90, CUDA 13.2). Not run on B300.The rest of the CPU-runnable suite (
tests/lang,tests/ir,tests/drivers,tests/transformsand the top-level tests) gives the same result onmainand here: 192 passed, and the same 5 failed because they need a GPU.ruff checkandruff format --check(0.11.0 frompyproject.toml, 0.12.3 from pre-commit),mypy(1.15.0) and the copyright check pass on the changed files.