Skip to main content

Environment Setup

We strongly recommend using clangd as the language server for JIT kernel development. For Ubuntu/Debian, you can download clangd from apt.llvm.org. If you are using VS Code, we recommend installing the clangd extension for better IDE integration. All JIT-related files are located in python/sglang/jit_kernel. Unlike sgl-kernel, which compiles CUDA/C++ binaries ahead of time (AOT), just-in-time (JIT) kernels are compiled at runtime. Consequently, a static compile_commands.json cannot be generated. To enable code completion with clangd, run python -m sglang.jit_kernel to generate a .clangd configuration file in your current directory. After generating the file, restart the clangd language server. It should now recognize all JIT kernel files.

Code Structure

C++ Implementation

C++ source code is located in python/sglang/jit_kernel/csrc. Reusable functions should be placed in python/sglang/jit_kernel/include. We use tvm-ffi for efficient foreign language bindings. Refer to the documentation for advanced usage, such as exporting C++ objects. Typically, tvm::ffi::TensorView is sufficient for passing PyTorch Tensors from Python.

Python Interface

Python interfaces are defined in python/sglang/jit_kernel. The load_jit utility function in python/sglang/jit_kernel/utils.py loads and returns the compiled module. To export a C++ function (e.g., cpp_func), pass cuda_wrappers=[("func", "cpp_func")] to load_jit. The function can then be called in Python as module.func. For caching compiled modules, prefer sglang.jit_kernel.utils.cache_once over functools.lru_cache. functools.lru_cache is not compatible with torch.compile.

C++ Utilities

The following C++ utilities are available:

Integer Range

Similar to PyTorch, we provide an irange function to represent an integer range.
Example

Runtime Checking

CHECK_HOST is the preferred runtime check: stream-style, and zero overhead when the check passes — the message expressions are only evaluated on failure. RuntimeCheck is the function-style alternative; note its message arguments are always evaluated, even when the check passes. RuntimeDeviceCheck verifies the status of the last kernel launch, and CHECK_CUDA is its stream-style equivalent for checking a cudaError_t with extra context.
Example

Tensor Checking

TensorMatcher provides a readable way to validate and extract tensor shape information.
Example
Configure the TensorMatcher with expected stride, dtype, and device properties before verification.
  • If with_strides is omitted, the tensor is expected to be contiguous.
  • Template arguments in with_dtype restrict the allowed data types.
  • Template arguments in with_device restrict the allowed devices.
  • Values passed to with_xxx methods enforce equality checks.
  • Passing -1 for size or stride allows matching any value.
A Symbolic variable must resolve to the same value across all verifications. Use .unwrap() to retrieve the matched value after verification.
Note: TensorMatcher is a temporary expression and should not be stored in a variable.
Tip: Add // at the end of the TensorMatcher chain to enforce proper indentation.

Kernel Launching

LaunchKernel::resolve_device retrieves the current cudaStream from PyTorch. Kernels can also be launched directly using LaunchKernel.
Example

Add new kernels

This section walks through a complete, end-to-end example of adding a new JIT kernel to the system. We use a simple add_constant kernel as a running example, which adds a constant integer value to every element of an input tensor. Conceptually, the Python interface looks like this:
Example

STEP 1: Write the C++ kernel

Write your CUDA kernel in jit_kernel/csrc/add_constant.cuh. For demonstration purposes, we pass the constant value as a template parameter.
Example

STEP 2: Create Python Interfaces

Next, expose the kernel through a Python wrapper. Create a new file at jit_kernel/add_constant.py and expose the needed interfaces.
Example
Keep the Python wrapper thin, but still validate the basic invariants such as device and dtype before dispatch. In the current JIT/FFI path, invalid tensors are not always rejected safely before launch.

STEP 3: Use your kernel

Finally, import and use the kernel like a regular Python function:
Example
For a complete, runnable example, refer to test_add_constant.py.

C++ Include Library Reference

The JIT kernel framework provides a set of reusable C++ headers in python/sglang/jit_kernel/include/sgl_kernel/. Each header is designed to be lightweight and self-contained. Below is a summary of each header and its key APIs.

Core Utilities

HeaderNamespacePurpose
utils.hhostHost-side essentials: RuntimeCheck, CHECK_HOST(cond) << …, Panic, div_ceil, irange
utils.cuhdevice / hostType aliases (fp16_t, bf16_t, …), SGL_DEVICE macro, PDL helpers, LaunchKernel, RuntimeDeviceCheck, CHECK_CUDA(expr) << …
source_location.h(global)Portable std::source_location wrapper for error reporting
runtime.cuhhost::runtimeCUDA runtime queries: get_blocks_per_sm, get_sm_count, get_cc_major, get_runtime_version, get_available_dynamic_smem_per_block

Tensor Validation

HeaderNamespacePurpose
tensor.hhostTensorMatcher, SymbolicSize, SymbolicDType, SymbolicDevice

Math & Type System

HeaderNamespacePurpose
math.cuhdevice::mathmax, min, abs, sqrt, rsqrt, exp, sin, cos, constants
type.cuh(global) / deviceDTypeTrait<T>, packed_t<T>, device::cast<To>(from)

Memory Access

HeaderNamespacePurpose
vec.cuhdeviceAlignedVector<T, N> - vectorized load/store (up to 128-bit; 256-bit requires Blackwell GPUs)
tile.cuhdevice::tileMemory<T> - cooperative tiled memory I/O (thread/warp/CTA)

Parallel Primitives

HeaderNamespacePurpose
warp.cuhdevice::warpreduce<Op, kNumThreads, kInner> (SUM/MAX/MIN, grouped or inter-group) and reduce_sum / reduce_max / reduce_min wrappers via __shfl_xor_sync
cta.cuhdevice::ctareduce_max across warps via shared memory
atomic.cuhdevice::atomicmax - atomic float max (CUDA + ROCm fallback)

Reusable Kernel Templates

HeaderNamespacePurpose
impl/norm.cuhhost::norm / device::normRMSNorm building blocks (warp & CTA paths, StorageType)