diff --git a/ggml/src/ggml-cuda/top-k.cu b/ggml/src/ggml-cuda/top-k.cu index c7a0c831788..e452c84eafd 100644 --- a/ggml/src/ggml-cuda/top-k.cu +++ b/ggml/src/ggml-cuda/top-k.cu @@ -48,7 +48,9 @@ static int next_power_of_2(int x) { #endif // CUB_TOP_K_AVAILABLE -#if !defined(GGML_CUDA_USE_CUB) && defined(GGML_USE_HIP) +#define GGML_CUDA_TOP_K_RADIX + +#ifdef GGML_CUDA_TOP_K_RADIX static __device__ __forceinline__ uint32_t top_k_float_to_ordered(float value) { const uint32_t bits = __float_as_uint(value); @@ -208,7 +210,17 @@ static void top_k_radix_cuda( src, dst, states, ncols, k, blocks_per_row); } -#endif // !defined(GGML_CUDA_USE_CUB) && defined(GGML_USE_HIP) +// nrows above which grid-over-rows radix select beats a per-row loop; env-tunable for sweeps +static int top_k_radix_min_rows() { + static int v = -1; + if (v < 0) { + const char * e = getenv("GGML_CUDA_TOPK_RADIX_MIN_ROWS"); + v = e ? atoi(e) : 8; + } + return v; +} + +#endif // GGML_CUDA_TOP_K_RADIX void ggml_cuda_op_top_k(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; @@ -229,10 +241,18 @@ void ggml_cuda_op_top_k(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { // TODO: Switch to `DeviceSegmentedTopK` for multi-row TopK once implemented // https://github.com/NVIDIA/cccl/issues/6391 // TODO: investigate if there exists a point where parallelized argsort is faster than sequential top-k - for (int i = 0; i < nrows; i++) { - top_k_cub(pool, src0_d + i * ncols, dst_d + i * k, ncols, k, stream); + if (nrows >= top_k_radix_min_rows() && ncols > 1024) { + top_k_radix_cuda(pool, src0_d, dst_d, ncols, nrows, k, stream); + } else { + for (int i = 0; i < nrows; i++) { + top_k_cub(pool, src0_d + i * ncols, dst_d + i * k, ncols, k, stream); + } } #elif defined(GGML_CUDA_USE_CUB) // CUB_TOP_K_AVAILABLE + if (nrows >= top_k_radix_min_rows() && ncols > 1024) { + top_k_radix_cuda(pool, src0_d, dst_d, ncols, nrows, k, stream); + return; + } // Fall back to argsort + copy const int ncols_pad = next_power_of_2(ncols); const size_t shared_mem = ncols_pad * sizeof(int);