hip: enable GGML_CUDA_USE_CUB via hipCUB (fixes TOP_K abort for >1024 rows) - #136
hip: enable GGML_CUDA_USE_CUB via hipCUB (fixes TOP_K abort for >1024 rows)#136davidcanar wants to merge 1 commit into
Conversation
Without CUB, ggml_cuda_op_top_k falls back to the bitonic argsort, which
launches one block of next_power_of_2(ncols) threads. CUB was disabled
unconditionally on HIP, so any ggml_top_k over more than 1024 rows (a
GLM-5-Next / GLM-5.3-Flash lightning-indexer selection over more than
4096 KV cells, i.e. any conversation past ~4k tokens) asked for a
>= 2048-thread block and aborted the backend with:
ggml_cuda_compute_forward: TOP_K failed
ROCm error: invalid configuration argument
hipCUB provides every primitive the GGML_CUDA_USE_CUB paths use, so
enable the define on HIP and bridge the differences in common.cuh:
- alias namespace cub = hipcub (hipCUB has no <cub/cub.cuh>)
- map cudaStreamCaptureStatus / cudaStreamIsCapturing onto the HIP
names used by the capture checks in argsort.cu / mean.cu
Two HIP-only adjustments inside the CUB paths:
- keep the CCCL >= 3.2 DeviceTopK and CCCL >= 3.1 strided-iterator
paths off on HIP (hipCUB has no cuda::execution / cuda/iterator)
- argsort.cu: route the multi-row non-capturing path through
DeviceSegmentedRadixSort instead of DeviceSegmentedSort, which
hipCUB does not provide
CUDA builds are untouched; everything new is inside GGML_USE_HIP.
Verified on a Radeon 8060S (gfx1151) RPC pair running GLM-5.3-Flash
UD-Q4_K_XL: an 8.8k-token prompt processes end to end where the
bitonic path aborted the RPC server; prompt processing is unchanged.
|
Worth noting this isn't only a GLM problem — I hit the same thing running qwen4exp (Qwen3.8-Flash-Next) on gfx1100. The sampler's top-k goes over the whole vocab row, ~151k wide, so it's past the 1024 limit on the first token of any request. No long context needed. It doesn't crash, supports_op declares the limit, so it just silently moves sampling to the CPU. Any HIP build with default sampling hits it as far as i can tell, whatever the model. Seeing it on b10715-mix-86bd2d3 (rocm-gfx110X) on 3x 7900 XT. |
Problem
On HIP builds
GGML_CUDA_USE_CUBis disabled unconditionally (common.cuh), soggml_cuda_op_top_kalways takes the no-CUB bitonic argsort fallback. That kernel launches one block ofnext_power_of_2(ncols)threads, which is only valid forncols <= 1024- the CUDA-sidesupports_opforTOP_K/ARGSORTeven advertisesne[0] <= 1024when CUB is off, but nothing enforces it at launch time.GLM-5-Next / GLM-5.3-Flash (PR ggml-org#27754) runs
ggml_top_kovern_kv / index_kpoollightning-indexer pools, so once a conversation grows past ~4k tokens of KV the selection exceeds 1024 rows, the block exceeds the device's 1024-thread limit, and the backend aborts:With the tensor hosted on a
ggml-rpc-server(the natural way to run the 200 GB Q4 GGUF), this aborts the RPC server and takes the whole llama-server with it.Fix
Enable
GGML_CUDA_USE_CUBon HIP and source CUB from hipCUB, which provides every primitive these paths use:common.cuh:#include <hipcub/hipcub.hpp>,namespace cub = hipcub(hipCUB has no<cub/cub.cuh>), and a small mapping ofcudaStreamCaptureStatus/cudaStreamIsCapturingonto thehip*equivalents used by the capture checks inargsort.cu/mean.cu.DeviceTopK::MaxPairspath intop-k.cuand the CCCL >= 3.1 strided-iterator path inargsort.curemain off on HIP (hipCUB has nocuda::execution/cuda/iterator); HIP gets the offsets-array + radix-sort paths instead.argsort.cu: the multi-row non-capturing branch routes throughDeviceSegmentedRadixSorton HIP because hipCUB has noDeviceSegmentedSort(same call shape already used for the stream-capturing case).cumsum.cu/mean.cu/sum.cu: include<cub/cub.cuh>only when not on HIP.CUDA builds are untouched - everything new is inside
#ifdef GGML_USE_HIP.Verification
Ryzen AI Max+ 395 (Radeon 8060S, gfx1151) pair, built with the system
hipcc(ROCm 7.1), runtime on ROCm 7.14, running GLM-5.3-Flash UD-Q4_K_XL distributed over RPC (--rpc, CUDA graphs enabled):TOP_K failed/invalid configuration argumentFixes the HIP half of the wide-top-k story for
glm5next/upstream; happy to rebase onto a different branch if that is preferred.