175 lines
4.1 KiB
Python
175 lines
4.1 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
|
import torch
|
|
import torch.nn.functional as F
|
|
from torch import Tensor
|
|
|
|
from vllm.triton_utils import tl, triton
|
|
from vllm.utils.torch_utils import direct_register_custom_op
|
|
|
|
|
|
@triton.jit
|
|
def _rmsnorm_nw_kernel(
|
|
x_ptr,
|
|
out_ptr,
|
|
stride_row,
|
|
D,
|
|
eps,
|
|
RBLOCK: tl.constexpr,
|
|
):
|
|
"""Weight-free RMSNorm Triton kernel: out = x * rsqrt(mean(x², -1) + eps)."""
|
|
row = tl.program_id(0)
|
|
cols = tl.arange(0, RBLOCK)
|
|
mask = cols < D
|
|
|
|
x = tl.load(
|
|
x_ptr + row * stride_row + cols,
|
|
mask=mask,
|
|
other=0.0,
|
|
eviction_policy="evict_first",
|
|
).to(tl.float32)
|
|
|
|
var = tl.sum(x * x, 0) / D
|
|
rstd = tl.rsqrt(var + eps)
|
|
|
|
out = (x * rstd).to(out_ptr.dtype.element_ty)
|
|
tl.store(out_ptr + row * D + cols, out, mask=mask, eviction_policy="evict_first")
|
|
|
|
|
|
def rmsnorm_nw(x: Tensor, eps: float) -> Tensor:
|
|
"""Weight-free RMSNorm over the last dimension.
|
|
|
|
Treats *x* as ``[num_rows, D]`` where ``num_rows = product(shape[:-1])``.
|
|
Returns a contiguous tensor with the same shape and dtype as *x*.
|
|
"""
|
|
orig_shape = x.shape
|
|
D = orig_shape[-1]
|
|
x_2d = x.reshape(-1, D)
|
|
num_rows = x_2d.shape[0]
|
|
|
|
out = torch.empty_like(x_2d)
|
|
RBLOCK = triton.next_power_of_2(D)
|
|
|
|
_rmsnorm_nw_kernel[(num_rows,)](
|
|
x_2d,
|
|
out,
|
|
x_2d.stride(0),
|
|
D,
|
|
eps,
|
|
RBLOCK=RBLOCK,
|
|
num_warps=1 if RBLOCK <= 512 else (4 if RBLOCK <= 4096 else 8),
|
|
)
|
|
return out.view(orig_shape)
|
|
|
|
|
|
@triton.jit
|
|
def _hc_head_reduce_store_kernel(
|
|
pre_ptr,
|
|
x_ptr,
|
|
out_ptr,
|
|
hidden_size: tl.constexpr,
|
|
hc_mult: tl.constexpr,
|
|
pre_stride_t: tl.constexpr,
|
|
pre_stride_m: tl.constexpr,
|
|
x_stride_t: tl.constexpr,
|
|
x_stride_m: tl.constexpr,
|
|
x_stride_h: tl.constexpr,
|
|
out_stride_t: tl.constexpr,
|
|
out_stride_h: tl.constexpr,
|
|
BLOCK_H: tl.constexpr,
|
|
):
|
|
token_idx = tl.program_id(0)
|
|
block_idx = tl.program_id(1)
|
|
offsets = block_idx * BLOCK_H + tl.arange(0, BLOCK_H)
|
|
mask = offsets < hidden_size
|
|
|
|
acc = tl.zeros((BLOCK_H,), dtype=tl.float32)
|
|
for mix_idx in tl.static_range(0, hc_mult):
|
|
pre = tl.load(pre_ptr + token_idx * pre_stride_t + mix_idx * pre_stride_m).to(
|
|
tl.float32
|
|
)
|
|
x = tl.load(
|
|
x_ptr
|
|
+ token_idx * x_stride_t
|
|
+ mix_idx * x_stride_m
|
|
+ offsets * x_stride_h,
|
|
mask=mask,
|
|
other=0.0,
|
|
).to(tl.float32)
|
|
acc += pre * x
|
|
|
|
tl.store(
|
|
out_ptr + token_idx * out_stride_t + offsets * out_stride_h,
|
|
acc,
|
|
mask=mask,
|
|
)
|
|
|
|
|
|
def hc_head_reduce_triton_kernel(
|
|
x: torch.Tensor,
|
|
hc_fn: torch.Tensor,
|
|
hc_scale: torch.Tensor,
|
|
hc_base: torch.Tensor,
|
|
out: torch.Tensor,
|
|
norm_eps: float,
|
|
hc_eps: float,
|
|
) -> None:
|
|
x_flat = x.flatten(-2)
|
|
x_normed = rmsnorm_nw(x_flat, norm_eps)
|
|
mixes = F.linear(x_normed.float(), hc_fn)
|
|
pre = torch.sigmoid(mixes * hc_scale + hc_base) + hc_eps
|
|
|
|
hidden_size = x.shape[-1]
|
|
hc_mult = x.shape[-2]
|
|
block_h = 1024
|
|
_hc_head_reduce_store_kernel[(x.shape[0], (hidden_size + block_h - 1) // block_h)](
|
|
pre,
|
|
x,
|
|
out,
|
|
hidden_size,
|
|
hc_mult,
|
|
pre.stride(0),
|
|
pre.stride(1),
|
|
x.stride(0),
|
|
x.stride(1),
|
|
x.stride(2),
|
|
out.stride(0),
|
|
out.stride(1),
|
|
BLOCK_H=block_h,
|
|
num_warps=4,
|
|
)
|
|
|
|
|
|
def _hc_head_triton(
|
|
hs_flat: torch.Tensor,
|
|
fn: torch.Tensor,
|
|
hc_scale: torch.Tensor,
|
|
hc_base: torch.Tensor,
|
|
out: torch.Tensor,
|
|
hidden_size: int,
|
|
rms_eps: float,
|
|
hc_eps: float,
|
|
hc_mult: int,
|
|
) -> None:
|
|
"""Fill pre-allocated `out` (T, H) in-place with the hc_head result."""
|
|
if hs_flat.shape[0] == 0:
|
|
return
|
|
|
|
hc_head_reduce_triton_kernel(
|
|
hs_flat,
|
|
fn,
|
|
hc_scale,
|
|
hc_base,
|
|
out,
|
|
rms_eps,
|
|
hc_eps,
|
|
)
|
|
return
|
|
|
|
|
|
direct_register_custom_op(
|
|
op_name="hc_head_triton",
|
|
op_func=_hc_head_triton,
|
|
mutates_args=["out"],
|
|
)
|