[AMD] Support fast_topk kernels in sgl-kernel (#15172)

This commit is contained in:
Hubert Lu
2025-12-19 22:19:09 -08:00
committed by GitHub
parent 6468cb5823
commit 51e2eaa458
4 changed files with 47 additions and 4 deletions
+14 -1
View File
@@ -20,7 +20,7 @@ limitations under the License.
TORCH_LIBRARY_EXPAND(sgl_kernel, m) {
/*
* From csrc/activation
* From csrc/elementwise
*/
m.def("silu_and_mul(Tensor! out, Tensor input) -> ()");
m.impl("silu_and_mul", torch::kCUDA, &silu_and_mul);
@@ -34,6 +34,19 @@ TORCH_LIBRARY_EXPAND(sgl_kernel, m) {
m.def("gelu_quick(Tensor! out, Tensor input) -> ()");
m.impl("gelu_quick", torch::kCUDA, &gelu_quick);
m.def("fast_topk(Tensor score, Tensor indices, Tensor lengths, Tensor? row_starts) -> ()");
m.impl("fast_topk", torch::kCUDA, &fast_topk_interface);
m.def(
"fast_topk_transform_fused(Tensor score, Tensor lengths, Tensor dst_page_table, Tensor src_page_table, Tensor "
"cu_seqlens_q, Tensor? row_starts) -> ()");
m.impl("fast_topk_transform_fused", torch::kCUDA, &fast_topk_transform_interface);
m.def(
"fast_topk_transform_ragged_fused(Tensor score, Tensor lengths, Tensor topk_indices_ragged, Tensor "
"topk_indices_offset, Tensor ? row_starts) -> ()");
m.impl("fast_topk_transform_ragged_fused", torch::kCUDA, &fast_topk_transform_ragged_interface);
/*
* From csrc/allreduce
*/
+24 -3
View File
@@ -22,7 +22,18 @@ namespace {
constexpr int TopK = 2048;
constexpr int kThreadsPerBlock = 1024;
constexpr size_t kSmem = 32 * 1024 * sizeof(uint32_t); // 128KB
#ifdef USE_ROCM
// On ROCm, the per-workgroup LDS budget depends on the target arch, so we inject a
// per-arch value from `setup_rocm.py` via `-DSGL_TOPK_DYNAMIC_SMEM_BYTES=...`.
#ifdef SGL_TOPK_DYNAMIC_SMEM_BYTES
constexpr size_t kSmem = static_cast<size_t>(SGL_TOPK_DYNAMIC_SMEM_BYTES);
#else
constexpr size_t kSmem = 48 * 1024; // bytes
#endif
#else
constexpr size_t kSmem = 32 * 1024 * sizeof(uint32_t); // 128KB (bytes)
#endif
struct FastTopKParams {
const float* __restrict__ input; // [B, input_stride]
@@ -401,8 +412,18 @@ auto get_params(
template <auto* f, size_t max_dynamic_smem>
void setup_kernel_smem_once() {
[[maybe_unused]]
static const auto result =
[] { return ::cudaFuncSetAttribute(f, ::cudaFuncAttributeMaxDynamicSharedMemorySize, max_dynamic_smem); }();
static const auto result = [] {
#ifdef USE_ROCM
// hipify will turn cudaFuncSetAttribute -> hipFuncSetAttribute. On ROCm,
// hipFuncSetAttribute expects `const void*` and hipcc does not accept passing
// a function pointer directly, so cast explicitly.
return ::cudaFuncSetAttribute(
reinterpret_cast<const void*>(f), ::cudaFuncAttributeMaxDynamicSharedMemorySize, max_dynamic_smem);
#else
// CUDA: keep original behavior (no cast needed).
return ::cudaFuncSetAttribute(f, ::cudaFuncAttributeMaxDynamicSharedMemorySize, max_dynamic_smem);
#endif
}();
TORCH_CHECK(result == cudaSuccess, "set_up_kernel_once failed:", ::cudaGetErrorString(result));
}