94057c3d3e
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
215 lines
7.8 KiB
Plaintext
215 lines
7.8 KiB
Plaintext
#include <sgl_kernel/tensor.h>
|
|
#include <sgl_kernel/utils.h>
|
|
|
|
#include <sgl_kernel/runtime.cuh>
|
|
#include <sgl_kernel/utils.cuh>
|
|
#include <sgl_kernel/warp.cuh>
|
|
|
|
#include <tvm/ffi/container/tensor.h>
|
|
|
|
#include <cmath>
|
|
#include <cstdint>
|
|
|
|
namespace {
|
|
|
|
[[maybe_unused]]
|
|
SGL_DEVICE float act_sqrt_softplus(float x) {
|
|
const float softplus = fmaxf(x, 0.0f) + log1pf(expf(-fabsf(x)));
|
|
return sqrtf(softplus);
|
|
}
|
|
|
|
struct MoEHashTopKParams {
|
|
const float* __restrict__ router_logits;
|
|
const int64_t* __restrict__ input_id;
|
|
const int32_t* __restrict__ tid2eid;
|
|
int32_t* __restrict__ topk_ids;
|
|
float* __restrict__ topk_weights;
|
|
uint32_t num_tokens;
|
|
uint32_t topk;
|
|
uint32_t num_routed_experts;
|
|
uint32_t num_shared_experts;
|
|
float routed_scaling_factor;
|
|
};
|
|
|
|
template <auto Fn, bool kUsePDL>
|
|
__global__ void moe_hash_topk_fused(const MoEHashTopKParams __grid_constant__ params) {
|
|
using namespace device;
|
|
const auto& [
|
|
router_logits, input_id, tid2eid, topk_ids, topk_weights, // pointers
|
|
num_tokens, topk, num_routed_experts, num_shared_experts, routed_scaling_factor] =
|
|
params;
|
|
|
|
const uint32_t topk_fused = topk + num_shared_experts;
|
|
const uint32_t tid = blockIdx.x * blockDim.x + threadIdx.x;
|
|
const uint32_t warp_id = tid / kWarpThreads;
|
|
const uint32_t lane_id = tid % kWarpThreads;
|
|
if (warp_id >= num_tokens) return;
|
|
// we can safely prefetch the token id
|
|
const auto token_id = input_id[warp_id];
|
|
|
|
PDLWaitPrimary<kUsePDL>();
|
|
|
|
float routed_weight = 0.0f;
|
|
int32_t expert_id = 0;
|
|
if (lane_id < topk) {
|
|
expert_id = tid2eid[token_id * topk + lane_id];
|
|
routed_weight = Fn(router_logits[warp_id * num_routed_experts + expert_id]);
|
|
}
|
|
|
|
const auto routed_sum = device::warp::reduce_sum(routed_weight);
|
|
if (lane_id < topk_fused) {
|
|
const bool is_shared = lane_id >= topk;
|
|
const auto output_offset = warp_id * topk_fused + lane_id;
|
|
topk_ids[output_offset] = is_shared ? num_routed_experts + lane_id - topk : expert_id;
|
|
topk_weights[output_offset] = is_shared ? 1.0f / routed_scaling_factor : routed_weight / routed_sum;
|
|
}
|
|
|
|
PDLTriggerSecondary<kUsePDL>();
|
|
}
|
|
|
|
struct TopKParams {
|
|
int32_t* __restrict__ topk_ids;
|
|
// Exactly one is active: ntn_ptr == nullptr means use ntn_value.
|
|
const int32_t* __restrict__ ntn_ptr;
|
|
int32_t ntn_value;
|
|
int64_t stride;
|
|
uint32_t topk;
|
|
uint32_t num_tokens;
|
|
};
|
|
|
|
__global__ void mask_topk_ids_padded_region(const TopKParams __grid_constant__ params) {
|
|
const uint32_t tid = blockIdx.x * blockDim.x + threadIdx.x;
|
|
const uint32_t warp_id = tid / device::kWarpThreads;
|
|
const uint32_t lane_id = tid % device::kWarpThreads;
|
|
if (warp_id >= params.num_tokens || lane_id >= params.topk) return;
|
|
device::PDLWaitPrimary<true>();
|
|
const uint32_t num = (params.ntn_ptr != nullptr) //
|
|
? static_cast<uint32_t>(params.ntn_ptr[0])
|
|
: static_cast<uint32_t>(params.ntn_value);
|
|
if (warp_id >= num) params.topk_ids[warp_id * params.stride + lane_id] = -1;
|
|
device::PDLTriggerSecondary<true>();
|
|
}
|
|
|
|
template <auto Fn, bool kUsePDL>
|
|
struct HashTopKKernel {
|
|
static constexpr auto kernel = moe_hash_topk_fused<Fn, kUsePDL>;
|
|
|
|
static void
|
|
run(const tvm::ffi::TensorView router_logits,
|
|
const tvm::ffi::TensorView input_id,
|
|
const tvm::ffi::TensorView tid2eid,
|
|
const tvm::ffi::TensorView topk_weights,
|
|
const tvm::ffi::TensorView topk_ids,
|
|
float routed_scaling_factor) {
|
|
using namespace host;
|
|
|
|
auto N = SymbolicSize{"num_tokens"};
|
|
auto E = SymbolicSize{"num_routed_experts"};
|
|
auto K = SymbolicSize{"topk_fused"};
|
|
auto device = SymbolicDevice{};
|
|
device.set_options<kDLCUDA>();
|
|
|
|
TensorMatcher({N, E}) //
|
|
.with_dtype<float>()
|
|
.with_device(device)
|
|
.verify(router_logits);
|
|
TensorMatcher({N}) //
|
|
.with_dtype<int64_t>()
|
|
.with_device(device)
|
|
.verify(input_id);
|
|
TensorMatcher({-1, -1}) //
|
|
.with_dtype<int32_t>()
|
|
.with_device(device)
|
|
.verify(tid2eid);
|
|
TensorMatcher({N, K}) //
|
|
.with_dtype<float>()
|
|
.with_device(device)
|
|
.verify(topk_weights);
|
|
TensorMatcher({N, K}) //
|
|
.with_dtype<int32_t>()
|
|
.with_device(device)
|
|
.verify(topk_ids);
|
|
|
|
const auto num_tokens = static_cast<uint32_t>(N.unwrap());
|
|
const auto topk_fused = static_cast<uint32_t>(K.unwrap());
|
|
const auto topk = static_cast<uint32_t>(tid2eid.size(1));
|
|
const auto shared_experts = topk_fused - topk;
|
|
RuntimeCheck(topk <= topk_fused, "HashTopKKernel requires topk <= topk_fused");
|
|
RuntimeCheck(topk_fused <= device::kWarpThreads, "HashTopKKernel requires topk_fused <= warp size");
|
|
|
|
const auto params = MoEHashTopKParams{
|
|
.router_logits = static_cast<const float*>(router_logits.data_ptr()),
|
|
.input_id = static_cast<const int64_t*>(input_id.data_ptr()),
|
|
.tid2eid = static_cast<const int32_t*>(tid2eid.data_ptr()),
|
|
.topk_ids = static_cast<int32_t*>(topk_ids.data_ptr()),
|
|
.topk_weights = static_cast<float*>(topk_weights.data_ptr()),
|
|
.num_tokens = num_tokens,
|
|
.topk = topk,
|
|
.num_routed_experts = static_cast<uint32_t>(E.unwrap()),
|
|
.num_shared_experts = shared_experts,
|
|
.routed_scaling_factor = routed_scaling_factor,
|
|
};
|
|
const auto kBlockSize = 128u;
|
|
const auto kNumWarps = kBlockSize / device::kWarpThreads;
|
|
const auto num_blocks = div_ceil(num_tokens, kNumWarps);
|
|
LaunchKernel(num_blocks, kBlockSize, device.unwrap()) //
|
|
.enable_pdl(kUsePDL)(kernel, params);
|
|
}
|
|
};
|
|
|
|
// TODO this may not be related to *hash* topk, thus may move
|
|
struct MaskKernel {
|
|
static constexpr auto kernel = mask_topk_ids_padded_region;
|
|
|
|
static void run(tvm::ffi::TensorView topk_ids, tvm::ffi::TensorView num_token_non_padded) {
|
|
using namespace host;
|
|
|
|
auto N = SymbolicSize{"num_tokens"};
|
|
auto K = SymbolicSize{"topk"};
|
|
auto D = SymbolicSize{"stride"};
|
|
auto device = SymbolicDevice{};
|
|
device.set_options<kDLCUDA>();
|
|
TensorMatcher({N, K}) //
|
|
.with_strides({D, 1})
|
|
.with_dtype<int32_t>()
|
|
.with_device(device)
|
|
.verify(topk_ids);
|
|
RuntimeCheck(num_token_non_padded.numel() == 1, "num_token_non_padded should be a scalar");
|
|
RuntimeCheck(K.unwrap() <= device::kWarpThreads, "MaskKernel requires topk <= warp size");
|
|
const int32_t* ntn_ptr = nullptr;
|
|
int32_t ntn_value = 0;
|
|
const auto ntn_dev = num_token_non_padded.device().device_type;
|
|
if (ntn_dev == kDLCUDA) {
|
|
RuntimeCheck(is_type<int32_t>(num_token_non_padded.dtype()), "num_token_non_padded on CUDA must be int32");
|
|
ntn_ptr = static_cast<const int32_t*>(num_token_non_padded.data_ptr());
|
|
} else if (ntn_dev == kDLCPU) {
|
|
if (is_type<int32_t>(num_token_non_padded.dtype())) {
|
|
ntn_value = *static_cast<const int32_t*>(num_token_non_padded.data_ptr());
|
|
} else if (is_type<int64_t>(num_token_non_padded.dtype())) {
|
|
ntn_value = static_cast<int32_t>(*static_cast<const int64_t*>(num_token_non_padded.data_ptr()));
|
|
} else {
|
|
RuntimeCheck(false, "num_token_non_padded on CPU must be int32 or int64");
|
|
}
|
|
} else {
|
|
RuntimeCheck(false, "num_token_non_padded must be on CPU or CUDA");
|
|
}
|
|
|
|
const auto num_tokens = static_cast<uint32_t>(N.unwrap());
|
|
const auto params = TopKParams{
|
|
.topk_ids = static_cast<int32_t*>(topk_ids.data_ptr()),
|
|
.ntn_ptr = ntn_ptr,
|
|
.ntn_value = ntn_value,
|
|
.stride = static_cast<int64_t>(D.unwrap()),
|
|
.topk = static_cast<uint32_t>(K.unwrap()),
|
|
.num_tokens = num_tokens,
|
|
};
|
|
const auto kBlockSize = 128u;
|
|
const auto kNumWarps = kBlockSize / device::kWarpThreads;
|
|
const auto num_blocks = div_ceil(num_tokens, kNumWarps);
|
|
LaunchKernel(num_blocks, kBlockSize, device.unwrap()) //
|
|
.enable_pdl(true)(kernel, params);
|
|
}
|
|
};
|
|
|
|
} // namespace
|