CUDA: use radix TOP_K when CUB DeviceTopK is unavailable - #28366
CUDA: use radix TOP_K when CUB DeviceTopK is unavailable#28366Rhonstin wants to merge 2 commits into
Conversation
CUDA builds with CCCL < 3.2 have no cub::DeviceTopK, so ggml_top_k falls back to a full argsort + copy (~12 bytes of temp per cell). For sparse-attention top-k over long contexts this OOMs small cards (200K cols x 128 rows ~= 190MB+ of temp per layer). Reuse the exact radix selection from #27466 (merged for HIP) on CUDA when CUB_TOP_K_AVAILABLE is off: O(nrows) temp, same selected set. Also gate next_power_of_2, unused on that path now.
|
Hi @Rhonstin, thanks for your contribution! Per our contribution guidelines, the automated PR checker found the following issue(s) that need your attention:
Please note that maintainers reserve the right to make final decisions on PRs. If you believe there is a mistake, please comment below. |
|
sure why not, but this is silly: |
|
Done - replaced with a single |
Enable the preserved 0005r1 fallback for CUB builds without DeviceTopK at 8192 columns or more. Retain the argsort control switch and existing radix kernels. Document source provenance, bounded quality evidence, toolkit eligibility, and a manual benchmark client. Related upstream work: ggml-org#28366 and ggml-org#27466. Assisted-by: Codex Astra
Overview
CUDA builds with CCCL < 3.2 have no
cub::DeviceTopK, soggml_cuda_op_top_kfalls back to a full argsort + copy at ~12 bytes of temp per cell. On long-context sparse-attention top-k that kills small cards: my 10 GB card (about 600 MB free) died incuMemCreateon QSA top-k over ~200K cols x 128 rows. That's 190+ MB of temp per layer.This PR reuses the radix selection from #27466 (merged for HIP) on CUDA when
CUB_TOP_K_AVAILABLEis off. NewGGML_CUDA_TOP_K_RADIXgate. Temp drops to O(nrows): per-row state plusnrows x blocks_per_row x 256histogram ints, single-digit MBs. Same set out (ordered-bit radix; ties break either way in both paths, and downstream reads the indices as a set plus mask). Also gatednext_power_of_2, unused on that path now.Nothing changes when
CUB_TOP_K_AVAILABLEis set (that branch is untouched and still wins), or on HIP (same guards, extended).Additional information
What I checked:
DeviceTopKbranch still wins (MaxPairspresent), radix compiled out.DeviceTopKthrough newer CCCL headers on the same CUDA 12.4 toolchain gave +9% prefill (220.9 vs 202.0 tok/s) at 207K context against the argsort fallback.Related: #27466.
Requirements