Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions ggml/src/ggml-cuda/top-k.cu
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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];
Expand All @@ -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);
Expand Down