Skip to content

Add an unrun native CUDA dequant kernel for the TurboQuant PoC - #7

Merged
lgoyal6 merged 1 commit into
mainfrom
turboquant-poc/native-cuda-dequant
Sep 6, 2026
Merged

lgoyal6 merged 1 commit into
mainfrom
turboquant-poc/native-cuda-dequant

Conversation

@lgoyal6

@lgoyal6 lgoyal6 commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

What this is

TurboQuantMSE.dequantize in turboquant_poc.py does four passes: promote the uint8 codes to int64 to index the codebook, materialise an fp32 gather result, run the GEMM, then scale the rows. On the decode path that runs for every layer on every token, and turboquant-poc/README.md already names the PyTorch dequantize path as the reason token rate sits below fp16.

Row scaling commutes with the rotation, because the rotation is a row-wise linear map:

(y_hat @ Pi) * norms[:, None]  ==  (y_hat * norms[:, None]) @ Pi

so the scale folds into the gather, leaving exactly one GEMM and no int64 index copy. tq_dequant_gather_scale does the fused half and deliberately leaves the GEMM to cuBLAS rather than reimplementing it. The codebook is at most 256 entries, so it is staged in shared memory once per block.

STATUS: UNRUN

The file says so in its own first paragraph, and this PR says it again so nobody has to open the file to find out.

This kernel has never been compiled or executed. The host it was written on has no GPU: nvidia-smi and nvcc are both absent. There are no performance numbers for it anywhere in this repository, and none may be quoted until it has been built and benchmarked on a CUDA device. bench_tq_dequant.py is that harness, and it refuses to run without CUDA rather than estimating.

What is verified is the algebra the fusion rests on. --check-math-only compares the fused result against the existing implementation on CPU and needs no GPU.

Known issue, reported rather than fixed

The kernel uses three symbols whose headers it does not include:

line symbol header it needs
117 at::cuda::getCurrentCUDAStream() <ATen/cuda/CUDAContext.h>
130 C10_CUDA_KERNEL_LAUNCH_CHECK() <c10/cuda/CUDAException.h>
115 std::min<long> <algorithm>

It includes only <torch/extension.h>, <cuda.h> and <cuda_runtime.h>. This is left unfixed on purpose: the compile failure cannot be reproduced on a host with no nvcc, and a fix nobody can run is a guess. Whoever takes this to a CUDA box should expect to add them.

Tests

No Python that the suite covers changed. .agent-work/ is excluded from discovery: worktrees under it hold duplicate copies of these same test files.

file result
test_token_merge.py 14/14
test_model_guard.py 21/21
attentionrag/test_core.py 10/10
experiments/test_data.py rc=0, 0 tests (fixture module)
total 45 passing, 0 failing

🤖 Generated with Claude Code

TurboQuantMSE.dequantize in turboquant_poc.py does three passes: it
promotes the uint8 codes to int64 to index the codebook, materialises an
fp32 gather result, runs the GEMM, and then scales the rows in a fourth
pass. On the decode path that runs for every layer on every token, and
turboquant-poc/README.md already names the PyTorch dequantize path as the
reason token rate sits below fp16.

Row scaling commutes with the rotation, because the rotation is a
row-wise linear map:

    (y_hat @ Pi) * norms[:, None]  ==  (y_hat * norms[:, None]) @ Pi

so the scale folds into the gather and leaves exactly one GEMM and no
int64 index copy. tq_dequant_gather_scale does the fused half and
deliberately leaves the GEMM to cuBLAS rather than reimplementing it. The
codebook is at most 256 entries, so it is staged in shared memory once
per block.

STATUS: UNRUN, and the file says so in its first paragraph. The host this
was written on has no GPU - nvidia-smi and nvcc are both absent - so
there are no performance numbers for this kernel anywhere in this repo,
and none may be quoted until it has been built and benchmarked on a CUDA
device. bench_tq_dequant.py is that harness, and it refuses to run
without CUDA rather than estimating.

What IS verified is the algebra the fusion rests on: --check-math-only
compares the fused result against the existing implementation on CPU.

Known issue, reported rather than fixed because it cannot be reproduced
on a host with no nvcc: the kernel uses three symbols whose headers it
does not include - at::cuda::getCurrentCUDAStream() needs
<ATen/cuda/CUDAContext.h>, C10_CUDA_KERNEL_LAUNCH_CHECK() needs
<c10/cuda/CUDAException.h>, and std::min<long> needs <algorithm>.
Whoever takes this to a CUDA box should expect to add them.
@lgoyal6
lgoyal6 merged commit c41110e into main Sep 6, 2026
1 check passed
@lgoyal6
lgoyal6 deleted the turboquant-poc/native-cuda-dequant branch September 6, 2026 23:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant