Signed-off-by: wangyu <410167048@qq.com> Signed-off-by: [Your Name] <your.email@example.com> Signed-off-by: wangyu <53896905+yenuo26@users.noreply.github.com>
306 lines
8.9 KiB
Python
306 lines
8.9 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
|
|
"""Fused MiniMax H3 modulation with FP32 accumulation."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import torch
|
|
from vllm.triton_utils import tl, triton
|
|
|
|
|
|
@triton.jit
|
|
def _indexed_scale_shift_kernel(
|
|
output_ptr,
|
|
x_ptr,
|
|
shift_ptr,
|
|
scale_ptr,
|
|
indices_ptr,
|
|
hidden_size,
|
|
stride_x_row,
|
|
stride_shift_row,
|
|
stride_scale_row,
|
|
stride_indices,
|
|
block_n: tl.constexpr,
|
|
):
|
|
row = tl.program_id(0)
|
|
columns = tl.arange(0, block_n)
|
|
mask = columns < hidden_size
|
|
index = tl.load(indices_ptr + row * stride_indices)
|
|
|
|
x = tl.load(x_ptr + row * stride_x_row + columns, mask=mask, other=0.0).to(tl.float32)
|
|
shift = tl.load(shift_ptr + index * stride_shift_row + columns, mask=mask, other=0.0).to(tl.float32)
|
|
scale = tl.load(scale_ptr + index * stride_scale_row + columns, mask=mask, other=0.0).to(tl.float32)
|
|
|
|
tl.store(
|
|
output_ptr + row * stride_x_row + columns,
|
|
x * (1.0 + scale) + shift,
|
|
mask=mask,
|
|
)
|
|
|
|
|
|
@triton.jit
|
|
def _indexed_gate_kernel(
|
|
output_ptr,
|
|
x_ptr,
|
|
gate_ptr,
|
|
other_ptr,
|
|
indices_ptr,
|
|
hidden_size,
|
|
stride_output_row,
|
|
stride_x_row,
|
|
stride_gate_row,
|
|
stride_other_row,
|
|
stride_indices,
|
|
block_n: tl.constexpr,
|
|
):
|
|
row = tl.program_id(0)
|
|
columns = tl.arange(0, block_n)
|
|
mask = columns < hidden_size
|
|
index = tl.load(indices_ptr + row * stride_indices)
|
|
|
|
x = tl.load(x_ptr + row * stride_x_row + columns, mask=mask, other=0.0).to(tl.float32)
|
|
gate = tl.load(gate_ptr + index * stride_gate_row + columns, mask=mask, other=0.0).to(tl.float32)
|
|
other = tl.load(other_ptr + row * stride_other_row + columns, mask=mask, other=0.0).to(tl.float32)
|
|
|
|
tl.store(
|
|
output_ptr + row * stride_output_row + columns,
|
|
x + gate * other,
|
|
mask=mask,
|
|
)
|
|
|
|
|
|
@triton.jit
|
|
def _rms_norm_indexed_scale_shift_kernel(
|
|
output_ptr,
|
|
x_ptr,
|
|
weight_ptr,
|
|
shift_ptr,
|
|
scale_ptr,
|
|
indices_ptr,
|
|
hidden_size: tl.constexpr,
|
|
eps: tl.constexpr,
|
|
stride_x_row,
|
|
stride_shift_row,
|
|
stride_scale_row,
|
|
stride_indices,
|
|
block_n: tl.constexpr,
|
|
):
|
|
row = tl.program_id(0)
|
|
columns = tl.arange(0, block_n)
|
|
mask = columns < hidden_size
|
|
index = tl.load(indices_ptr + row * stride_indices)
|
|
|
|
x = tl.load(x_ptr + row * stride_x_row + columns, mask=mask, other=0.0).to(tl.float32)
|
|
weight = tl.load(weight_ptr + columns, mask=mask, other=0.0).to(tl.float32)
|
|
variance = tl.sum(x * x, axis=0) / hidden_size
|
|
normalized = x * tl.rsqrt(variance + eps) * weight
|
|
|
|
shift = tl.load(shift_ptr + index * stride_shift_row + columns, mask=mask, other=0.0).to(tl.float32)
|
|
scale = tl.load(scale_ptr + index * stride_scale_row + columns, mask=mask, other=0.0).to(tl.float32)
|
|
tl.store(
|
|
output_ptr + row * hidden_size + columns,
|
|
normalized * (1.0 + scale) + shift,
|
|
mask=mask,
|
|
)
|
|
|
|
|
|
@triton.jit
|
|
def _indexed_gate_rms_norm_scale_shift_kernel(
|
|
residual_out_ptr,
|
|
modulated_out_ptr,
|
|
residual_ptr,
|
|
gate_ptr,
|
|
branch_ptr,
|
|
weight_ptr,
|
|
shift_ptr,
|
|
scale_ptr,
|
|
indices_ptr,
|
|
hidden_size: tl.constexpr,
|
|
eps: tl.constexpr,
|
|
stride_residual_row,
|
|
stride_gate_row,
|
|
stride_branch_row,
|
|
stride_shift_row,
|
|
stride_scale_row,
|
|
stride_indices,
|
|
block_n: tl.constexpr,
|
|
):
|
|
row = tl.program_id(0)
|
|
columns = tl.arange(0, block_n)
|
|
mask = columns < hidden_size
|
|
index = tl.load(indices_ptr + row * stride_indices)
|
|
|
|
residual = tl.load(residual_ptr + row * stride_residual_row + columns, mask=mask, other=0.0).to(tl.float32)
|
|
gate = tl.load(gate_ptr + index * stride_gate_row + columns, mask=mask, other=0.0).to(tl.float32)
|
|
branch = tl.load(branch_ptr + row * stride_branch_row + columns, mask=mask, other=0.0).to(tl.float32)
|
|
updated = residual + gate * branch
|
|
tl.store(residual_out_ptr + row * hidden_size + columns, updated, mask=mask)
|
|
|
|
weight = tl.load(weight_ptr + columns, mask=mask, other=0.0).to(tl.float32)
|
|
variance = tl.sum(updated * updated, axis=0) / hidden_size
|
|
normalized = updated * tl.rsqrt(variance + eps) * weight
|
|
shift = tl.load(shift_ptr + index * stride_shift_row + columns, mask=mask, other=0.0).to(tl.float32)
|
|
scale = tl.load(scale_ptr + index * stride_scale_row + columns, mask=mask, other=0.0).to(tl.float32)
|
|
tl.store(
|
|
modulated_out_ptr + row * hidden_size + columns,
|
|
normalized * (1.0 + scale) + shift,
|
|
mask=mask,
|
|
)
|
|
|
|
|
|
def indexed_scale_shift_(
|
|
x: torch.Tensor,
|
|
shift: torch.Tensor,
|
|
scale: torch.Tensor,
|
|
indices: torch.Tensor,
|
|
) -> torch.Tensor:
|
|
"""Apply indexed scale/shift in-place to a disposable contiguous input."""
|
|
if x.is_cpu:
|
|
x.copy_((x * (1.0 + scale.index_select(0, indices)) + shift.index_select(0, indices)).to(x.dtype))
|
|
return x
|
|
rows, hidden_size = x.shape
|
|
if rows == 0:
|
|
return x
|
|
_indexed_scale_shift_kernel[(rows,)](
|
|
x,
|
|
x,
|
|
shift,
|
|
scale,
|
|
indices,
|
|
hidden_size,
|
|
x.stride(0),
|
|
shift.stride(0),
|
|
scale.stride(0),
|
|
indices.stride(0),
|
|
block_n=triton.next_power_of_2(hidden_size),
|
|
num_warps=8,
|
|
)
|
|
return x
|
|
|
|
|
|
def indexed_gate(
|
|
x: torch.Tensor,
|
|
gate: torch.Tensor,
|
|
other: torch.Tensor,
|
|
indices: torch.Tensor,
|
|
) -> torch.Tensor:
|
|
"""Return ``x + gate[indices] * other`` without indexed temporaries."""
|
|
if x.is_cpu:
|
|
return (x + gate.index_select(0, indices) * other).to(x.dtype)
|
|
output = torch.empty_like(x)
|
|
rows, hidden_size = x.shape
|
|
if rows == 0:
|
|
return output
|
|
_indexed_gate_kernel[(rows,)](
|
|
output,
|
|
x,
|
|
gate,
|
|
other,
|
|
indices,
|
|
hidden_size,
|
|
output.stride(0),
|
|
x.stride(0),
|
|
gate.stride(0),
|
|
other.stride(0),
|
|
indices.stride(0),
|
|
block_n=triton.next_power_of_2(hidden_size),
|
|
num_warps=8,
|
|
)
|
|
return output
|
|
|
|
|
|
def rms_norm_indexed_scale_shift(
|
|
x: torch.Tensor,
|
|
weight: torch.Tensor,
|
|
shift: torch.Tensor,
|
|
scale: torch.Tensor,
|
|
indices: torch.Tensor,
|
|
eps: float,
|
|
) -> torch.Tensor:
|
|
"""Fuse H3 RMSNorm with its indexed AdaLN affine transform."""
|
|
if x.is_cpu:
|
|
input_dtype = x.dtype
|
|
normalized = x.float()
|
|
variance = normalized.pow(2).mean(-1, keepdim=True)
|
|
normalized = normalized * torch.rsqrt(variance + eps)
|
|
normalized = (weight.float() * normalized).to(input_dtype)
|
|
return (normalized * (1.0 + scale.index_select(0, indices)) + shift.index_select(0, indices)).to(input_dtype)
|
|
output = torch.empty_like(x)
|
|
rows, hidden_size = x.shape
|
|
if rows:
|
|
_rms_norm_indexed_scale_shift_kernel[(rows,)](
|
|
output,
|
|
x,
|
|
weight,
|
|
shift,
|
|
scale,
|
|
indices,
|
|
hidden_size,
|
|
eps,
|
|
x.stride(0),
|
|
shift.stride(0),
|
|
scale.stride(0),
|
|
indices.stride(0),
|
|
block_n=triton.next_power_of_2(hidden_size),
|
|
num_warps=8,
|
|
)
|
|
return output
|
|
|
|
|
|
def indexed_gate_rms_norm_scale_shift(
|
|
residual: torch.Tensor,
|
|
gate: torch.Tensor,
|
|
branch: torch.Tensor,
|
|
weight: torch.Tensor,
|
|
shift: torch.Tensor,
|
|
scale: torch.Tensor,
|
|
indices: torch.Tensor,
|
|
eps: float,
|
|
) -> tuple[torch.Tensor, torch.Tensor]:
|
|
"""Fuse gated residual, the following RMSNorm, and AdaLN affine."""
|
|
if residual.is_cpu:
|
|
input_dtype = residual.dtype
|
|
residual_out = (residual + gate.index_select(0, indices) * branch).to(input_dtype)
|
|
normalized = residual_out.float()
|
|
variance = normalized.pow(2).mean(-1, keepdim=True)
|
|
normalized = normalized * torch.rsqrt(variance + eps)
|
|
normalized = (weight.float() * normalized).to(input_dtype)
|
|
modulated_out = (normalized * (1.0 + scale.index_select(0, indices)) + shift.index_select(0, indices)).to(
|
|
input_dtype
|
|
)
|
|
return residual_out, modulated_out
|
|
residual_out = torch.empty_like(residual)
|
|
modulated_out = torch.empty_like(residual)
|
|
rows, hidden_size = residual.shape
|
|
if rows:
|
|
_indexed_gate_rms_norm_scale_shift_kernel[(rows,)](
|
|
residual_out,
|
|
modulated_out,
|
|
residual,
|
|
gate,
|
|
branch,
|
|
weight,
|
|
shift,
|
|
scale,
|
|
indices,
|
|
hidden_size,
|
|
eps,
|
|
residual.stride(0),
|
|
gate.stride(0),
|
|
branch.stride(0),
|
|
shift.stride(0),
|
|
scale.stride(0),
|
|
indices.stride(0),
|
|
block_n=triton.next_power_of_2(hidden_size),
|
|
num_warps=8,
|
|
)
|
|
return residual_out, modulated_out
|
|
|
|
|
|
__all__ = [
|
|
"indexed_gate",
|
|
"indexed_gate_rms_norm_scale_shift",
|
|
"indexed_scale_shift_",
|
|
"rms_norm_indexed_scale_shift",
|
|
]
|