Kernels
kernels-bot commited on
Commit
cb16f2b
·
verified ·
1 Parent(s): 1d24e8a

Uploaded using `kernel-builder`.

Browse files
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 = "08b4d53"
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": "_liger_kernels_xpu_08b4d53",
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
+ )