Instructions to use kernels-community/liger-kernels with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Kernels
How to use kernels-community/liger-kernels with Kernels:
# !pip install kernels from kernels import get_kernel kernel = get_kernel("kernels-community/liger-kernels") - Notebooks
- Google Colab
- Kaggle
Uploaded using `kernel-builder`.
Browse files- build/torch-xpu/_ops.py +1 -1
- build/torch-xpu/layers.py +51 -0
- build/torch-xpu/metadata.json +1 -1
- build/torch-xpu/tiled_mlp.py +136 -0
build/torch-xpu/_ops.py
CHANGED
|
@@ -22,7 +22,7 @@ def get_backend() -> str:
|
|
| 22 |
|
| 23 |
def _find_ops_name() -> str:
|
| 24 |
kernel_name = "liger_kernels"
|
| 25 |
-
unique_id = "
|
| 26 |
backend = get_backend()
|
| 27 |
return f"_{kernel_name}_{backend}_{unique_id}"
|
| 28 |
|
|
|
|
| 22 |
|
| 23 |
def _find_ops_name() -> str:
|
| 24 |
kernel_name = "liger_kernels"
|
| 25 |
+
unique_id = "ab435e2"
|
| 26 |
backend = get_backend()
|
| 27 |
return f"_{kernel_name}_{backend}_{unique_id}"
|
| 28 |
|
build/torch-xpu/layers.py
CHANGED
|
@@ -17,6 +17,7 @@ from .qwen2vl_mrope import LigerQwen2VLMRopeFunction
|
|
| 17 |
from .rms_norm import LigerRMSNormFunction
|
| 18 |
from .rope import LigerRopeFunction
|
| 19 |
from .swiglu import LigerSiLUMulFunction
|
|
|
|
| 20 |
from .tvd import LigerTVDLossFunction
|
| 21 |
|
| 22 |
|
|
@@ -306,6 +307,54 @@ class LigerGEGLUMLP(nn.Module):
|
|
| 306 |
return self.down_proj(LigerGELUMulFunction.apply(self.gate_proj(x), self.up_proj(x)))
|
| 307 |
|
| 308 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 309 |
@dataclass
|
| 310 |
class CrossEntropyOutput:
|
| 311 |
loss: torch.Tensor
|
|
@@ -455,6 +504,8 @@ __all__ = [
|
|
| 455 |
"LigerTVDLoss",
|
| 456 |
"LigerSwiGLUMLP",
|
| 457 |
"LigerGEGLUMLP",
|
|
|
|
|
|
|
| 458 |
"CrossEntropyOutput",
|
| 459 |
"liger_fused_linear_cross_entropy",
|
| 460 |
"LigerForCausalLMLoss",
|
|
|
|
| 17 |
from .rms_norm import LigerRMSNormFunction
|
| 18 |
from .rope import LigerRopeFunction
|
| 19 |
from .swiglu import LigerSiLUMulFunction
|
| 20 |
+
from .tiled_mlp import apply_tiled_mlp
|
| 21 |
from .tvd import LigerTVDLossFunction
|
| 22 |
|
| 23 |
|
|
|
|
| 307 |
return self.down_proj(LigerGELUMulFunction.apply(self.gate_proj(x), self.up_proj(x)))
|
| 308 |
|
| 309 |
|
| 310 |
+
class LigerTiledGEGLUMLP(nn.Module):
|
| 311 |
+
gate_proj: nn.Linear
|
| 312 |
+
up_proj: nn.Linear
|
| 313 |
+
down_proj: nn.Linear
|
| 314 |
+
num_shards: int
|
| 315 |
+
|
| 316 |
+
def _mlp_forward(self, module, x):
|
| 317 |
+
"""Internal MLP forward function for tiled computation."""
|
| 318 |
+
gate = module.gate_proj(x)
|
| 319 |
+
up = module.up_proj(x)
|
| 320 |
+
return module.down_proj(LigerGELUMulFunction.apply(gate, up))
|
| 321 |
+
|
| 322 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 323 |
+
compute_params = [p for p in self.parameters() if p.requires_grad]
|
| 324 |
+
|
| 325 |
+
return apply_tiled_mlp(
|
| 326 |
+
fn=self._mlp_forward,
|
| 327 |
+
mlp_module=self,
|
| 328 |
+
x=x,
|
| 329 |
+
num_shards=self.num_shards,
|
| 330 |
+
compute_params=compute_params,
|
| 331 |
+
)
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
class LigerTiledSwiGLUMLP(nn.Module):
|
| 335 |
+
gate_proj: nn.Linear
|
| 336 |
+
up_proj: nn.Linear
|
| 337 |
+
down_proj: nn.Linear
|
| 338 |
+
num_shards: int
|
| 339 |
+
|
| 340 |
+
def _mlp_forward(self, module, x):
|
| 341 |
+
"""Internal MLP forward function for tiled computation."""
|
| 342 |
+
gate = module.gate_proj(x)
|
| 343 |
+
up = module.up_proj(x)
|
| 344 |
+
return module.down_proj(LigerSiLUMulFunction.apply(gate, up))
|
| 345 |
+
|
| 346 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 347 |
+
compute_params = [p for p in self.parameters() if p.requires_grad]
|
| 348 |
+
|
| 349 |
+
return apply_tiled_mlp(
|
| 350 |
+
fn=self._mlp_forward,
|
| 351 |
+
mlp_module=self,
|
| 352 |
+
x=x,
|
| 353 |
+
num_shards=self.num_shards,
|
| 354 |
+
compute_params=compute_params,
|
| 355 |
+
)
|
| 356 |
+
|
| 357 |
+
|
| 358 |
@dataclass
|
| 359 |
class CrossEntropyOutput:
|
| 360 |
loss: torch.Tensor
|
|
|
|
| 504 |
"LigerTVDLoss",
|
| 505 |
"LigerSwiGLUMLP",
|
| 506 |
"LigerGEGLUMLP",
|
| 507 |
+
"LigerTiledGEGLUMLP",
|
| 508 |
+
"LigerTiledSwiGLUMLP",
|
| 509 |
"CrossEntropyOutput",
|
| 510 |
"liger_fused_linear_cross_entropy",
|
| 511 |
"LigerForCausalLMLoss",
|
build/torch-xpu/metadata.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
{
|
| 2 |
"name": "liger-kernels",
|
| 3 |
-
"id": "
|
| 4 |
"version": 1,
|
| 5 |
"license": "BSD-2-Clause",
|
| 6 |
"python-depends": [],
|
|
|
|
| 1 |
{
|
| 2 |
"name": "liger-kernels",
|
| 3 |
+
"id": "_liger_kernels_xpu_ab435e2",
|
| 4 |
"version": 1,
|
| 5 |
"license": "BSD-2-Clause",
|
| 6 |
"python-depends": [],
|
build/torch-xpu/tiled_mlp.py
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import math
|
| 2 |
+
|
| 3 |
+
from typing import Callable
|
| 4 |
+
from typing import List
|
| 5 |
+
from typing import Optional
|
| 6 |
+
|
| 7 |
+
import torch
|
| 8 |
+
|
| 9 |
+
from .utils import ensure_contiguous
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class LigerTiledMLPFunction(torch.autograd.Function):
|
| 13 |
+
"""
|
| 14 |
+
Based on DeepSpeed's TiledMLP:
|
| 15 |
+
https://github.com/deepspeedai/DeepSpeed/blob/v0.18.2/deepspeed/runtime/sequence_parallel/ulysses_sp.py#L838
|
| 16 |
+
|
| 17 |
+
Perform a tiled MLP computation to massively reduce memory usage needed to compute MLP
|
| 18 |
+
when using very long sequence lengths.
|
| 19 |
+
|
| 20 |
+
This module re-computes `forward` in the `backward`. So the `forward` occurs twice each iteration.
|
| 21 |
+
And if you're using activation checkpointing it then occurs thrice.
|
| 22 |
+
|
| 23 |
+
Args:
|
| 24 |
+
fn: the function to call on sharded inputs (e.g., mlp.forward)
|
| 25 |
+
mlp_module: the MLP nn.Module object
|
| 26 |
+
x: the input to MLP.forward (hidden_states)
|
| 27 |
+
shards: how many shards to use
|
| 28 |
+
compute_params: a list of weights engaged in the compute
|
| 29 |
+
|
| 30 |
+
Returns:
|
| 31 |
+
the computed hidden_states
|
| 32 |
+
"""
|
| 33 |
+
|
| 34 |
+
@staticmethod
|
| 35 |
+
@ensure_contiguous
|
| 36 |
+
def forward(
|
| 37 |
+
ctx,
|
| 38 |
+
fn: Callable,
|
| 39 |
+
mlp_module: torch.nn.Module,
|
| 40 |
+
x: torch.Tensor,
|
| 41 |
+
shards: int,
|
| 42 |
+
compute_params: Optional[List[torch.nn.Parameter]] = None,
|
| 43 |
+
) -> torch.Tensor:
|
| 44 |
+
ctx.fn = fn
|
| 45 |
+
ctx.mlp_module = mlp_module
|
| 46 |
+
ctx.shards = shards
|
| 47 |
+
ctx.save_for_backward(x)
|
| 48 |
+
|
| 49 |
+
# x.shape could be [bs, seqlen, hidden_size] or [seqlen, hidden_size] (moe experts)
|
| 50 |
+
x_shards = list(torch.chunk(x, chunks=shards, dim=-2))
|
| 51 |
+
with torch.no_grad():
|
| 52 |
+
output_shards = [fn(mlp_module, x_shard) for x_shard in x_shards]
|
| 53 |
+
output_unsharded = torch.cat(output_shards, dim=-2)
|
| 54 |
+
|
| 55 |
+
return output_unsharded
|
| 56 |
+
|
| 57 |
+
@staticmethod
|
| 58 |
+
@ensure_contiguous
|
| 59 |
+
def backward(ctx, *grads) -> tuple:
|
| 60 |
+
fn = ctx.fn
|
| 61 |
+
(x,) = ctx.saved_tensors
|
| 62 |
+
mlp_module = ctx.mlp_module
|
| 63 |
+
shards = ctx.shards
|
| 64 |
+
|
| 65 |
+
x_requires_grad = x.requires_grad
|
| 66 |
+
x = x.detach()
|
| 67 |
+
# detach() unsets x.requires_grad, so restore it
|
| 68 |
+
x.requires_grad_(x_requires_grad)
|
| 69 |
+
|
| 70 |
+
# x.shape could be [bs, seqlen, hidden_size] or [seqlen, hidden_size] (moe experts)
|
| 71 |
+
hidden_size = x.shape[-1]
|
| 72 |
+
x_shape_orig = x.shape
|
| 73 |
+
|
| 74 |
+
# flatten bs+seqlen to avoid having stride issues when narrowing into seqlen w/ bs>1
|
| 75 |
+
x = x.view(-1, hidden_size)
|
| 76 |
+
incoming_grad = grads[0].view(-1, hidden_size)
|
| 77 |
+
x_grad = torch.zeros_like(x)
|
| 78 |
+
|
| 79 |
+
x_shards = list(torch.chunk(x, chunks=shards, dim=0))
|
| 80 |
+
|
| 81 |
+
for i, x_shard in enumerate(x_shards):
|
| 82 |
+
x_shard.requires_grad_(x_requires_grad)
|
| 83 |
+
|
| 84 |
+
# if seqlen is not exactly divisible by shards the last step will be shorter than shard_step
|
| 85 |
+
shard_step = x_shards[i].shape[0]
|
| 86 |
+
shard_offset = i * x_shards[0].shape[0]
|
| 87 |
+
|
| 88 |
+
x_shard.grad = x_grad.narrow(0, shard_offset, shard_step).view_as(x_shard)
|
| 89 |
+
incoming_grad_shard = incoming_grad.narrow(0, shard_offset, shard_step).view_as(x_shard)
|
| 90 |
+
|
| 91 |
+
with torch.enable_grad():
|
| 92 |
+
output = fn(mlp_module, x_shard)
|
| 93 |
+
torch.autograd.backward(output, incoming_grad_shard)
|
| 94 |
+
|
| 95 |
+
# unflatten
|
| 96 |
+
x_grad = x_grad.view(x_shape_orig)
|
| 97 |
+
|
| 98 |
+
return (None, None, x_grad, None, None)
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
def apply_tiled_mlp(
|
| 102 |
+
fn: Callable,
|
| 103 |
+
mlp_module: torch.nn.Module,
|
| 104 |
+
x: torch.Tensor,
|
| 105 |
+
num_shards: Optional[int] = None,
|
| 106 |
+
compute_params: Optional[List[torch.nn.Parameter]] = None,
|
| 107 |
+
) -> torch.Tensor:
|
| 108 |
+
"""
|
| 109 |
+
Apply tiled MLP computation for memory efficiency.
|
| 110 |
+
|
| 111 |
+
Args:
|
| 112 |
+
fn: the function to call on sharded inputs (e.g., lambda module, x: module(x))
|
| 113 |
+
mlp_module: the MLP nn.Module object
|
| 114 |
+
x: the input tensor with shape [bs, seqlen, hidden_size] or [seqlen, hidden_size]
|
| 115 |
+
num_shards: number of shards to use. If None, automatically calculated as ceil(seqlen / hidden_size)
|
| 116 |
+
compute_params: list of parameters for DeepSpeed ZeRO optimization
|
| 117 |
+
|
| 118 |
+
Returns:
|
| 119 |
+
output tensor with the same shape as input
|
| 120 |
+
"""
|
| 121 |
+
if num_shards is None:
|
| 122 |
+
# x.shape could be [bs, seqlen, hidden_size] or [seqlen, hidden_size]
|
| 123 |
+
hidden_size = x.shape[-1]
|
| 124 |
+
seqlen = x.shape[-2]
|
| 125 |
+
num_shards = math.ceil(seqlen / hidden_size)
|
| 126 |
+
|
| 127 |
+
# Ensure num_shards is at least 1
|
| 128 |
+
num_shards = max(1, num_shards)
|
| 129 |
+
|
| 130 |
+
return LigerTiledMLPFunction.apply(
|
| 131 |
+
fn,
|
| 132 |
+
mlp_module,
|
| 133 |
+
x,
|
| 134 |
+
num_shards,
|
| 135 |
+
compute_params,
|
| 136 |
+
)
|