Repository navigation
CUDA: fix slow q4_0/q5_0 V dequantization on Blackwell with CUDA 12.8 - #30077
ilyas-mallah wants to merge 3 commits into
Conversation
PerformanceTable generated with
I'm not seeing the reported speedup with > $ nvcc --version [±b4e5089ea ●(✹)]
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2026 NVIDIA Corporation
Built on Tue_Jun_09_02:43:40_PM_PDT_2026
Cuda compilation tools, release 13.3, V13.3.73
Build cuda_13.3.r13.3/compiler.38244171_0 |
|
Thanks for testing! The slowdown only happens with CUDA 12.8, which is what the default cuda Docker images use, so no difference with 13.3 is expected. 12.8 compiles that byte-pointer read for Blackwell through local memory, newer versions don't. You're right about the q5_0 regression on the 3090. I pushed a change so the shifts are only used on Blackwell and every other architecture keeps the original code. I checked that the generated code for the older architectures is now identical to master. |
|
@CISC can we just update the docker image to CUDA 12.9? I would like to avoid having to work around compiler bugs like this in the backend code. |
The Ubuntu CUDA 12.8 release builds have the same problem on Blackwell, so they'd need the bump too. Anyone building from source with 12.8 would also still hit it. |
Overview
The vector FA kernel with q4_0 or q5_0 V cache gets a 128 to 336 byte stack frame on CUDA 12.8 for Blackwell (sm_120a, sm_100a, sm_101a). Older architectures and CUDA 12.9 and 13.0 are not affected.
This PR changes
dequantize_V_q4_0anddequantize_V_q5_0so they read the dequantized word with shifts, instead of through an int8_t pointer to it, which nvcc 12.8 kept in local memory. The result is that the stack frame for those kernels is removed.On an RTX 5090 built with CUDA 12.8.1 (the version the
cudaDocker images use), the FA op with a q4_0 cache becomes 2.1x as fast and decode gets 1.7x faster at 16k context and 2.1x at 32k. q8_0 is unchanged. Built with CUDA 13.0, master already runs at this speed.This is only done on Blackwell (
__CUDA_ARCH__ >= 1000); other architectures, HIP and MUSA keep the pointer read.Additional information
Performance (RTX 5090, CUDA 12.8.1, llama-bench -fa 1 -ctk/-ctv q8_0,q4_0 -p 0 -n 128 -d 0,4096,16384,32768)
Table generated with
scripts/compare-llama-bench.py. V type equals K type.FA op alone (head size 128, 8 K/V heads, GQA 4, q4_0): 88.1 to 41.2 us at 16k K/V rows, 164.8 to 77.1 us at 32k.
Stack frame per nvcc version (-Xptxas -v, D=128, one column)
With this PR, q4_0 and q5_0 on sm_120a with nvcc 12.8 drop to the frames all types have (the two-column and D=64 softcap kernels). The stack is already in the PTX from nvcc 12.8, so it comes from the front end, not ptxas.
test-backend-ops -o FLASH_ATTN_EXT -p type_K=qpasses on the RTX 5090 (1728/1728).Requirements