用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/OpenMOSS/sglang --skill add-sgl-kernel命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | add-sgl-kernel |
| description | Step-by-step tutorial for adding a heavyweight AOT CUDA/C++ kernel to sgl-kernel (including tests & benchmarks) |
sgl-kernel (AOT / Heavyweight)This tutorial walks through adding a simple element-wise scale operation as an AOT kernel. We'll implement scale(x, factor) = x * factor to demonstrate the complete workflow.
Add a new operation that scales each element of a tensor by a scalar factor:
x (CUDA) and scalar factor (float)x * factor (element-wise, in-place or into pre-allocated out)torch.float16), BF16 (torch.bfloat16), FP32 (torch.float32)
DISPATCH_PYTORCH_DTYPE_TO_CTYPE_FLOAT_FP16 macro (defined in sgl-kernel/include/utils.h)sgl-kernel. If it depends on CUTLASS / FlashInfer / DeepGEMM (or similarly heavy stacks), implement it in sgl-kernel/.python/sglang/jit_kernel. If it is small, has few dependencies, and benefits from rapid iteration, implement it as a JIT kernel instead.In addition, every new kernel must ship with:
You will typically touch these files/areas:
sgl-kernel/csrc/elementwise/scale.cu (pick the right subdirectory)sgl-kernel/include/sgl_kernel_ops.hsgl-kernel/csrc/common_extension.ccsgl-kernel/CMakeLists.txt (set(SOURCES ...))sgl-kernel/python/sgl_kernel/ and sgl-kernel/python/sgl_kernel/__init__.pysgl-kernel/tests/test_scale.pysgl-kernel/benchmark/bench_scale.pycsrc/Pick the right subdirectory:
csrc/elementwise/ — for element-wise ops (our example)csrc/gemm/, csrc/attention/, csrc/moe/ — for other categoriesCreate sgl-kernel/csrc/elementwise/scale.cu:
#include <ATen/cuda/CUDAContext.h>
#include <c10/cuda/CUDAGuard.h>
#include <torch/all.h>
#include "utils.h" // DISPATCH_PYTORCH_DTYPE_TO_CTYPE_FLOAT_FP16
// scale_kernel: out[i] = input[i] * factor
// Supports float, half (__half), __nv_bfloat16 via template T
template <typename T>
__global__ void scale_kernel(T* __restrict__ out,
const T* __restrict__ input,
float factor,
int64_t n) {
int64_t idx = static_cast<int64_t>(blockIdx.x) * blockDim.x + threadIdx.x;
if (idx < n) {
out[idx] = static_cast<T>(static_cast<float>(input[idx]) * factor);
}
}
void scale(at::Tensor& out, const at::Tensor& input, double factor) {
TORCH_CHECK(input.is_cuda(), "input must be a CUDA tensor");
TORCH_CHECK(input.is_contiguous(), "input must be contiguous");
TORCH_CHECK(out.is_cuda(), "out must be a CUDA tensor");
TORCH_CHECK(out.is_contiguous(), );
(out.() == input.(), );
(out.() == input.(),
);
n = input.();
threads = ;
blocks = (n + threads - ) / threads;
cudaStream_t stream = at::cuda::();
at::;
(input.(), c_type, [&] {
scale_kernel<c_type><<<blocks, threads, , stream>>>(
<c_type*>(out.()),
< c_type*>(input.()),
<>(factor),
n);
cudaError_t status = ();
(status == cudaSuccess,
, (status));
;
});
}
Key points:
at::Tensor (PyTorch tensors), TORCH_CHECK for validation, at::cuda::getCurrentCUDAStream() for streamDISPATCH_PYTORCH_DTYPE_TO_CTYPE_FLOAT_FP16 covers float, half (FP16), __nv_bfloat16 (BF16)TORCH_CHECK and skip logic in testsinclude/sgl_kernel_ops.hEdit sgl-kernel/include/sgl_kernel_ops.h, add to the elementwise section:
void scale(at::Tensor& out, const at::Tensor& input, double factor);
csrc/common_extension.ccEdit sgl-kernel/csrc/common_extension.cc, inside TORCH_LIBRARY_FRAGMENT(sgl_kernel, m):
// From csrc/elementwise
m.def("scale(Tensor! out, Tensor input, float factor) -> ()");
m.impl("scale", torch::kCUDA, &scale);
Key points:
Tensor! means in-place / mutable output argumenttorch.compile and for consistent call signaturesfloat but PyTorch bindings expect double, the implicit cast is fine for scalars; use shims if needed for other typesCMakeLists.txtEdit sgl-kernel/CMakeLists.txt, add to set(SOURCES ...):
csrc/elementwise/scale.cu
Key points:
sgl-kernel/python/sgl_kernel/In sgl-kernel/python/sgl_kernel/__init__.py, add:
from torch.ops import sgl_kernel as _ops
def scale(out: torch.Tensor, input: torch.Tensor, factor: float) -> None:
"""
Element-wise scale: out = input * factor (in-place into out).
Supported dtypes: torch.float16, torch.bfloat16, torch.float32.
Parameters
----------
out : pre-allocated CUDA output tensor (same shape/dtype as input)
input : CUDA input tensor
factor : scale factor (float)
"""
_ops.scale(out, input, factor)
Or export it from the existing module organisation — follow the pattern already used by similar ops in __init__.py.
Create sgl-kernel/tests/test_scale.py:
import pytest
import torch
import sgl_kernel
@pytest.mark.parametrize("dtype", [torch.float16, torch.bfloat16, torch.float32])
@pytest.mark.parametrize("size", [128, 1024, 4096, 65536])
@pytest.mark.parametrize("factor", [0.5, 1.0, 2.0])
def test_scale_correctness(dtype, size, factor):
input = torch.randn(size, dtype=dtype, device="cuda")
out = torch.empty_like(input)
sgl_kernel.scale(out, input, factor)
expected = input * factor
rtol, atol = (1e-5, 1e-6) if dtype == torch.float32 else (1e-2, 1e-2)
torch.testing.assert_close(out, expected, rtol=rtol, atol=atol)
def test_scale_shape_mismatch():
input = torch.randn(128, dtype=torch.float16, device="cuda")
out = torch.empty(256, dtype=torch.float16, device="cuda")
with pytest.raises(RuntimeError, match="same shape"):
sgl_kernel.scale(out, input, 2.0)
def test_scale_cpu_input():
input = torch.randn(, dtype=torch.float16)
out = torch.empty_like()
pytest.raises(RuntimeError, =):
sgl_kernel.scale(out, , )
__name__ == :
pytest.main([__file__, ])
Run:
pytest sgl-kernel/tests/test_scale.py -q
Create sgl-kernel/benchmark/bench_scale.py:
import itertools
import os
import torch
import triton
import triton.testing
import sgl_kernel
IS_CI = (
os.getenv("CI", "false").lower() == "true"
or os.getenv("GITHUB_ACTIONS", "false").lower() == "true"
)
dtypes = [torch.float16] if IS_CI else [torch.float16, torch.bfloat16, torch.float32]
sizes = [4096] if IS_CI else [2**n for n in range(10, 20)] # 1K … 512K
factors = [2.0]
configs = list(itertools.product(dtypes, sizes))
def torch_scale(input: torch.Tensor, factor: float) -> torch.Tensor:
return input * factor
@triton.testing.perf_report(
triton.testing.Benchmark(
x_names=["dtype", "size"],
x_vals=configs,
line_arg="provider",
line_vals=["sglang", "torch"],
line_names=["SGL Kernel", "PyTorch"],
styles=[("green", "-"), ("red", "--")],
ylabel=,
plot_name=,
args={},
)
)
():
= torch.randn(size, dtype=dtype, device=)
out = torch.empty_like()
factor =
provider == :
fn = : sgl_kernel.scale(out, , factor)
:
fn = : torch_scale(, factor)
ms, min_ms, max_ms = triton.testing.do_bench_cudagraph(
fn, quantiles=[, , ]
)
* ms, * max_ms, * min_ms
__name__ == :
benchmark.run(print_data=)
Run:
python sgl-kernel/benchmark/bench_scale.py
Build:
cd sgl-kernel
make build -j16
If you need to limit host resource usage:
cd sgl-kernel
make build -j1 MAX_JOBS=2 CMAKE_ARGS="-DSGL_KERNEL_COMPILE_THREADS=1"
Validate:
pytest sgl-kernel/tests/test_scale.py -q
python sgl-kernel/benchmark/bench_scale.py
CUDA_LAUNCH_BLOCKING=1compute-sanitizer --tool memcheck python ...MAX_JOBS and SGL_KERNEL_COMPILE_THREADSsgl-kernel/analyze_whl_kernel_sizes.py.cu file is missing from SOURCES, the symbol will be undefined at link timesgl-kernel/README.mdsgl-kernel/include/sgl_kernel_ops.hsgl-kernel/csrc/common_extension.ccsgl-kernel/CMakeLists.txtsgl-kernel/include/utils.h — DISPATCH_PYTORCH_DTYPE_TO_CTYPE_FLOAT_FP16 macro and friendssgl-kernel/csrc/elementwise/activation.cu — reference for the FP16/BF16/FP32 dispatch patternsgl-kernel/csrc/elementwise/scale.cu # NEW: CUDA kernel + launcher
sgl-kernel/include/sgl_kernel_ops.h # MODIFIED: C++ declaration
sgl-kernel/csrc/common_extension.cc # MODIFIED: schema + dispatch registration
sgl-kernel/CMakeLists.txt # MODIFIED: add source file (alphabetical)
sgl-kernel/python/sgl_kernel/__init__.py # MODIFIED: export Python API
sgl-kernel/tests/test_scale.py # NEW: tests
sgl-kernel/benchmark/bench_scale.py # NEW: benchmark
基于 SOC 职业分类