comdoleger commited on
Commit
92d269e
·
verified ·
1 Parent(s): e93a75e

Upload extensions_built_in/diffusion_models/omnigen2/src/ops/triton/layer_norm.py with huggingface_hub

Browse files
extensions_built_in/diffusion_models/omnigen2/src/ops/triton/layer_norm.py ADDED
@@ -0,0 +1,1257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2024, Tri Dao.
2
+ # Implement dropout + residual + layer_norm / rms_norm.
3
+
4
+ # Based on the Triton LayerNorm tutorial: https://triton-lang.org/main/getting-started/tutorials/05-layer-norm.html
5
+ # For the backward pass, we keep weight_grad and bias_grad in registers and accumulate.
6
+ # This is faster for dimensions up to 8k, but after that it's much slower due to register spilling.
7
+ # The models we train have hidden dim up to 8k anyway (e.g. Llama 70B), so this is fine.
8
+
9
+ import math
10
+
11
+ import torch
12
+ import torch.nn.functional as F
13
+
14
+ import triton
15
+ import triton.language as tl
16
+
17
+
18
+ from typing import Callable
19
+
20
+
21
+ def custom_amp_decorator(dec: Callable, cuda_amp_deprecated: bool):
22
+ def decorator(*args, **kwargs):
23
+ if cuda_amp_deprecated:
24
+ kwargs["device_type"] = "cuda"
25
+ return dec(*args, **kwargs)
26
+ return decorator
27
+
28
+
29
+ if hasattr(torch.amp, "custom_fwd"): # type: ignore[attr-defined]
30
+ deprecated = True
31
+ from torch.amp import custom_fwd, custom_bwd # type: ignore[attr-defined]
32
+ else:
33
+ deprecated = False
34
+ from torch.cuda.amp import custom_fwd, custom_bwd
35
+
36
+ custom_fwd = custom_amp_decorator(custom_fwd, deprecated)
37
+ custom_bwd = custom_amp_decorator(custom_bwd, deprecated)
38
+
39
+
40
+ def triton_autotune_configs():
41
+ # Return configs with a valid warp count for the current device
42
+ configs=[]
43
+ # Maximum threads per block is architecture-dependent in theory, but in reality all are 1024
44
+ max_threads_per_block=1024
45
+ # Default to warp size 32 if not defined by device
46
+ warp_size=getattr(torch.cuda.get_device_properties(torch.cuda.current_device()), "warp_size", 32)
47
+ # Autotune for warp counts which are powers of 2 and do not exceed thread per block limit
48
+ warp_count=1
49
+ while warp_count*warp_size <= max_threads_per_block:
50
+ configs.append(triton.Config({}, num_warps=warp_count))
51
+ warp_count*=2
52
+ return configs
53
+
54
+ def layer_norm_ref(
55
+ x,
56
+ weight,
57
+ bias,
58
+ residual=None,
59
+ x1=None,
60
+ weight1=None,
61
+ bias1=None,
62
+ eps=1e-6,
63
+ dropout_p=0.0,
64
+ rowscale=None,
65
+ prenorm=False,
66
+ zero_centered_weight=False,
67
+ dropout_mask=None,
68
+ dropout_mask1=None,
69
+ upcast=False,
70
+ ):
71
+ dtype = x.dtype
72
+ if upcast:
73
+ x = x.float()
74
+ weight = weight.float()
75
+ bias = bias.float() if bias is not None else None
76
+ residual = residual.float() if residual is not None else residual
77
+ x1 = x1.float() if x1 is not None else None
78
+ weight1 = weight1.float() if weight1 is not None else None
79
+ bias1 = bias1.float() if bias1 is not None else None
80
+ if zero_centered_weight:
81
+ weight = weight + 1.0
82
+ if weight1 is not None:
83
+ weight1 = weight1 + 1.0
84
+ if x1 is not None:
85
+ assert rowscale is None, "rowscale is not supported with parallel LayerNorm"
86
+ if rowscale is not None:
87
+ x = x * rowscale[..., None]
88
+ if dropout_p > 0.0:
89
+ if dropout_mask is not None:
90
+ x = x.masked_fill(~dropout_mask, 0.0) / (1.0 - dropout_p)
91
+ else:
92
+ x = F.dropout(x, p=dropout_p)
93
+ if x1 is not None:
94
+ if dropout_mask1 is not None:
95
+ x1 = x1.masked_fill(~dropout_mask1, 0.0) / (1.0 - dropout_p)
96
+ else:
97
+ x1 = F.dropout(x1, p=dropout_p)
98
+ if x1 is not None:
99
+ x = x + x1
100
+ if residual is not None:
101
+ x = (x + residual).to(x.dtype)
102
+ out = F.layer_norm(x.to(weight.dtype), x.shape[-1:], weight=weight, bias=bias, eps=eps).to(
103
+ dtype
104
+ )
105
+ if weight1 is None:
106
+ return out if not prenorm else (out, x)
107
+ else:
108
+ out1 = F.layer_norm(
109
+ x.to(weight1.dtype), x.shape[-1:], weight=weight1, bias=bias1, eps=eps
110
+ ).to(dtype)
111
+ return (out, out1) if not prenorm else (out, out1, x)
112
+
113
+
114
+ def rms_norm_ref(
115
+ x,
116
+ weight,
117
+ bias,
118
+ residual=None,
119
+ x1=None,
120
+ weight1=None,
121
+ bias1=None,
122
+ eps=1e-6,
123
+ dropout_p=0.0,
124
+ rowscale=None,
125
+ prenorm=False,
126
+ zero_centered_weight=False,
127
+ dropout_mask=None,
128
+ dropout_mask1=None,
129
+ upcast=False,
130
+ ):
131
+ dtype = x.dtype
132
+ if upcast:
133
+ x = x.float()
134
+ weight = weight.float()
135
+ bias = bias.float() if bias is not None else None
136
+ residual = residual.float() if residual is not None else residual
137
+ x1 = x1.float() if x1 is not None else None
138
+ weight1 = weight1.float() if weight1 is not None else None
139
+ bias1 = bias1.float() if bias1 is not None else None
140
+ if zero_centered_weight:
141
+ weight = weight + 1.0
142
+ if weight1 is not None:
143
+ weight1 = weight1 + 1.0
144
+ if x1 is not None:
145
+ assert rowscale is None, "rowscale is not supported with parallel LayerNorm"
146
+ if rowscale is not None:
147
+ x = x * rowscale[..., None]
148
+ if dropout_p > 0.0:
149
+ if dropout_mask is not None:
150
+ x = x.masked_fill(~dropout_mask, 0.0) / (1.0 - dropout_p)
151
+ else:
152
+ x = F.dropout(x, p=dropout_p)
153
+ if x1 is not None:
154
+ if dropout_mask1 is not None:
155
+ x1 = x1.masked_fill(~dropout_mask1, 0.0) / (1.0 - dropout_p)
156
+ else:
157
+ x1 = F.dropout(x1, p=dropout_p)
158
+ if x1 is not None:
159
+ x = x + x1
160
+ if residual is not None:
161
+ x = (x + residual).to(x.dtype)
162
+ rstd = 1 / torch.sqrt((x.square()).mean(dim=-1, keepdim=True) + eps)
163
+ out = ((x * rstd * weight) + bias if bias is not None else (x * rstd * weight)).to(dtype)
164
+ if weight1 is None:
165
+ return out if not prenorm else (out, x)
166
+ else:
167
+ out1 = ((x * rstd * weight1) + bias1 if bias1 is not None else (x * rstd * weight1)).to(
168
+ dtype
169
+ )
170
+ return (out, out1) if not prenorm else (out, out1, x)
171
+
172
+
173
+ @triton.autotune(
174
+ configs=triton_autotune_configs(),
175
+ key=["N", "HAS_RESIDUAL", "STORE_RESIDUAL_OUT", "IS_RMS_NORM", "HAS_BIAS"],
176
+ )
177
+ # @triton.heuristics({"HAS_BIAS": lambda args: args["B"] is not None})
178
+ # @triton.heuristics({"HAS_RESIDUAL": lambda args: args["RESIDUAL"] is not None})
179
+ @triton.heuristics({"HAS_X1": lambda args: args["X1"] is not None})
180
+ @triton.heuristics({"HAS_W1": lambda args: args["W1"] is not None})
181
+ @triton.heuristics({"HAS_B1": lambda args: args["B1"] is not None})
182
+ @triton.jit
183
+ def _layer_norm_fwd_1pass_kernel(
184
+ X, # pointer to the input
185
+ Y, # pointer to the output
186
+ W, # pointer to the weights
187
+ B, # pointer to the biases
188
+ RESIDUAL, # pointer to the residual
189
+ X1,
190
+ W1,
191
+ B1,
192
+ Y1,
193
+ RESIDUAL_OUT, # pointer to the residual
194
+ ROWSCALE,
195
+ SEEDS, # Dropout seeds for each row
196
+ DROPOUT_MASK,
197
+ Mean, # pointer to the mean
198
+ Rstd, # pointer to the 1/std
199
+ stride_x_row, # how much to increase the pointer when moving by 1 row
200
+ stride_y_row,
201
+ stride_res_row,
202
+ stride_res_out_row,
203
+ stride_x1_row,
204
+ stride_y1_row,
205
+ M, # number of rows in X
206
+ N, # number of columns in X
207
+ eps, # epsilon to avoid division by zero
208
+ dropout_p, # Dropout probability
209
+ zero_centered_weight, # If true, add 1.0 to the weight
210
+ IS_RMS_NORM: tl.constexpr,
211
+ BLOCK_N: tl.constexpr,
212
+ HAS_RESIDUAL: tl.constexpr,
213
+ STORE_RESIDUAL_OUT: tl.constexpr,
214
+ HAS_BIAS: tl.constexpr,
215
+ HAS_DROPOUT: tl.constexpr,
216
+ STORE_DROPOUT_MASK: tl.constexpr,
217
+ HAS_ROWSCALE: tl.constexpr,
218
+ HAS_X1: tl.constexpr,
219
+ HAS_W1: tl.constexpr,
220
+ HAS_B1: tl.constexpr,
221
+ ):
222
+ # Map the program id to the row of X and Y it should compute.
223
+ row = tl.program_id(0)
224
+ X += row * stride_x_row
225
+ Y += row * stride_y_row
226
+ if HAS_RESIDUAL:
227
+ RESIDUAL += row * stride_res_row
228
+ if STORE_RESIDUAL_OUT:
229
+ RESIDUAL_OUT += row * stride_res_out_row
230
+ if HAS_X1:
231
+ X1 += row * stride_x1_row
232
+ if HAS_W1:
233
+ Y1 += row * stride_y1_row
234
+ # Compute mean and variance
235
+ cols = tl.arange(0, BLOCK_N)
236
+ x = tl.load(X + cols, mask=cols < N, other=0.0).to(tl.float32)
237
+ if HAS_ROWSCALE:
238
+ rowscale = tl.load(ROWSCALE + row).to(tl.float32)
239
+ x *= rowscale
240
+ if HAS_DROPOUT:
241
+ # Compute dropout mask
242
+ # 7 rounds is good enough, and reduces register pressure
243
+ keep_mask = tl.rand(tl.load(SEEDS + row).to(tl.uint32), cols, n_rounds=7) > dropout_p
244
+ x = tl.where(keep_mask, x / (1.0 - dropout_p), 0.0)
245
+ if STORE_DROPOUT_MASK:
246
+ tl.store(DROPOUT_MASK + row * N + cols, keep_mask, mask=cols < N)
247
+ if HAS_X1:
248
+ x1 = tl.load(X1 + cols, mask=cols < N, other=0.0).to(tl.float32)
249
+ if HAS_ROWSCALE:
250
+ rowscale = tl.load(ROWSCALE + M + row).to(tl.float32)
251
+ x1 *= rowscale
252
+ if HAS_DROPOUT:
253
+ # Compute dropout mask
254
+ # 7 rounds is good enough, and reduces register pressure
255
+ keep_mask = (
256
+ tl.rand(tl.load(SEEDS + M + row).to(tl.uint32), cols, n_rounds=7) > dropout_p
257
+ )
258
+ x1 = tl.where(keep_mask, x1 / (1.0 - dropout_p), 0.0)
259
+ if STORE_DROPOUT_MASK:
260
+ tl.store(DROPOUT_MASK + (M + row) * N + cols, keep_mask, mask=cols < N)
261
+ x += x1
262
+ if HAS_RESIDUAL:
263
+ residual = tl.load(RESIDUAL + cols, mask=cols < N, other=0.0).to(tl.float32)
264
+ x += residual
265
+ if STORE_RESIDUAL_OUT:
266
+ tl.store(RESIDUAL_OUT + cols, x, mask=cols < N)
267
+ if not IS_RMS_NORM:
268
+ mean = tl.sum(x, axis=0) / N
269
+ tl.store(Mean + row, mean)
270
+ xbar = tl.where(cols < N, x - mean, 0.0)
271
+ var = tl.sum(xbar * xbar, axis=0) / N
272
+ else:
273
+ xbar = tl.where(cols < N, x, 0.0)
274
+ var = tl.sum(xbar * xbar, axis=0) / N
275
+ rstd = 1 / tl.sqrt(var + eps)
276
+ tl.store(Rstd + row, rstd)
277
+ # Normalize and apply linear transformation
278
+ mask = cols < N
279
+ w = tl.load(W + cols, mask=mask).to(tl.float32)
280
+ if zero_centered_weight:
281
+ w += 1.0
282
+ if HAS_BIAS:
283
+ b = tl.load(B + cols, mask=mask).to(tl.float32)
284
+ x_hat = (x - mean) * rstd if not IS_RMS_NORM else x * rstd
285
+ y = x_hat * w + b if HAS_BIAS else x_hat * w
286
+ # Write output
287
+ tl.store(Y + cols, y, mask=mask)
288
+ if HAS_W1:
289
+ w1 = tl.load(W1 + cols, mask=mask).to(tl.float32)
290
+ if zero_centered_weight:
291
+ w1 += 1.0
292
+ if HAS_B1:
293
+ b1 = tl.load(B1 + cols, mask=mask).to(tl.float32)
294
+ y1 = x_hat * w1 + b1 if HAS_B1 else x_hat * w1
295
+ tl.store(Y1 + cols, y1, mask=mask)
296
+
297
+
298
+ def _layer_norm_fwd(
299
+ x,
300
+ weight,
301
+ bias,
302
+ eps,
303
+ residual=None,
304
+ x1=None,
305
+ weight1=None,
306
+ bias1=None,
307
+ dropout_p=0.0,
308
+ rowscale=None,
309
+ out_dtype=None,
310
+ residual_dtype=None,
311
+ zero_centered_weight=False,
312
+ is_rms_norm=False,
313
+ return_dropout_mask=False,
314
+ out=None,
315
+ residual_out=None
316
+ ):
317
+ if residual is not None:
318
+ residual_dtype = residual.dtype
319
+ M, N = x.shape
320
+ assert x.stride(-1) == 1
321
+ if residual is not None:
322
+ assert residual.stride(-1) == 1
323
+ assert residual.shape == (M, N)
324
+ assert weight.shape == (N,)
325
+ assert weight.stride(-1) == 1
326
+ if bias is not None:
327
+ assert bias.stride(-1) == 1
328
+ assert bias.shape == (N,)
329
+ if x1 is not None:
330
+ assert x1.shape == x.shape
331
+ assert rowscale is None
332
+ assert x1.stride(-1) == 1
333
+ if weight1 is not None:
334
+ assert weight1.shape == (N,)
335
+ assert weight1.stride(-1) == 1
336
+ if bias1 is not None:
337
+ assert bias1.shape == (N,)
338
+ assert bias1.stride(-1) == 1
339
+ if rowscale is not None:
340
+ assert rowscale.is_contiguous()
341
+ assert rowscale.shape == (M,)
342
+ # allocate output
343
+ if out is None:
344
+ out = torch.empty_like(x, dtype=x.dtype if out_dtype is None else out_dtype)
345
+ else:
346
+ assert out.shape == x.shape
347
+ assert out.stride(-1) == 1
348
+ if weight1 is not None:
349
+ y1 = torch.empty_like(out)
350
+ assert y1.stride(-1) == 1
351
+ else:
352
+ y1 = None
353
+ if (
354
+ residual is not None
355
+ or (residual_dtype is not None and residual_dtype != x.dtype)
356
+ or dropout_p > 0.0
357
+ or rowscale is not None
358
+ or x1 is not None
359
+ ):
360
+ if residual_out is None:
361
+ residual_out = torch.empty(
362
+ M, N, device=x.device, dtype=residual_dtype if residual_dtype is not None else x.dtype
363
+ )
364
+ else:
365
+ assert residual_out.shape == x.shape
366
+ assert residual_out.stride(-1) == 1
367
+ else:
368
+ residual_out = None
369
+ mean = torch.empty((M,), dtype=torch.float32, device=x.device) if not is_rms_norm else None
370
+ rstd = torch.empty((M,), dtype=torch.float32, device=x.device)
371
+ if dropout_p > 0.0:
372
+ seeds = torch.randint(
373
+ 2**32, (M if x1 is None else 2 * M,), device=x.device, dtype=torch.int64
374
+ )
375
+ else:
376
+ seeds = None
377
+ if return_dropout_mask and dropout_p > 0.0:
378
+ dropout_mask = torch.empty(M if x1 is None else 2 * M, N, device=x.device, dtype=torch.bool)
379
+ else:
380
+ dropout_mask = None
381
+ # Less than 64KB per feature: enqueue fused kernel
382
+ MAX_FUSED_SIZE = 65536 // x.element_size()
383
+ BLOCK_N = min(MAX_FUSED_SIZE, triton.next_power_of_2(N))
384
+ if N > BLOCK_N:
385
+ raise RuntimeError("This layer norm doesn't support feature dim >= 64KB.")
386
+ with torch.cuda.device(x.device.index):
387
+ _layer_norm_fwd_1pass_kernel[(M,)](
388
+ x,
389
+ out,
390
+ weight,
391
+ bias,
392
+ residual,
393
+ x1,
394
+ weight1,
395
+ bias1,
396
+ y1,
397
+ residual_out,
398
+ rowscale,
399
+ seeds,
400
+ dropout_mask,
401
+ mean,
402
+ rstd,
403
+ x.stride(0),
404
+ out.stride(0),
405
+ residual.stride(0) if residual is not None else 0,
406
+ residual_out.stride(0) if residual_out is not None else 0,
407
+ x1.stride(0) if x1 is not None else 0,
408
+ y1.stride(0) if y1 is not None else 0,
409
+ M,
410
+ N,
411
+ eps,
412
+ dropout_p,
413
+ zero_centered_weight,
414
+ is_rms_norm,
415
+ BLOCK_N,
416
+ residual is not None,
417
+ residual_out is not None,
418
+ bias is not None,
419
+ dropout_p > 0.0,
420
+ dropout_mask is not None,
421
+ rowscale is not None,
422
+ )
423
+ # residual_out is None if residual is None and residual_dtype == input_dtype and dropout_p == 0.0
424
+ if dropout_mask is not None and x1 is not None:
425
+ dropout_mask, dropout_mask1 = dropout_mask.tensor_split(2, dim=0)
426
+ else:
427
+ dropout_mask1 = None
428
+ return (
429
+ out,
430
+ y1,
431
+ mean,
432
+ rstd,
433
+ residual_out if residual_out is not None else x,
434
+ seeds,
435
+ dropout_mask,
436
+ dropout_mask1,
437
+ )
438
+
439
+
440
+ @triton.autotune(
441
+ configs=triton_autotune_configs(),
442
+ key=["N", "HAS_DRESIDUAL", "STORE_DRESIDUAL", "IS_RMS_NORM", "HAS_BIAS", "HAS_DROPOUT"],
443
+ )
444
+ # @triton.heuristics({"HAS_BIAS": lambda args: args["B"] is not None})
445
+ # @triton.heuristics({"HAS_DRESIDUAL": lambda args: args["DRESIDUAL"] is not None})
446
+ # @triton.heuristics({"STORE_DRESIDUAL": lambda args: args["DRESIDUAL_IN"] is not None})
447
+ @triton.heuristics({"HAS_ROWSCALE": lambda args: args["ROWSCALE"] is not None})
448
+ @triton.heuristics({"HAS_DY1": lambda args: args["DY1"] is not None})
449
+ @triton.heuristics({"HAS_DX1": lambda args: args["DX1"] is not None})
450
+ @triton.heuristics({"HAS_B1": lambda args: args["DB1"] is not None})
451
+ @triton.heuristics({"RECOMPUTE_OUTPUT": lambda args: args["Y"] is not None})
452
+ @triton.jit
453
+ def _layer_norm_bwd_kernel(
454
+ X, # pointer to the input
455
+ W, # pointer to the weights
456
+ B, # pointer to the biases
457
+ Y, # pointer to the output to be recomputed
458
+ DY, # pointer to the output gradient
459
+ DX, # pointer to the input gradient
460
+ DW, # pointer to the partial sum of weights gradient
461
+ DB, # pointer to the partial sum of biases gradient
462
+ DRESIDUAL,
463
+ W1,
464
+ DY1,
465
+ DX1,
466
+ DW1,
467
+ DB1,
468
+ DRESIDUAL_IN,
469
+ ROWSCALE,
470
+ SEEDS,
471
+ Mean, # pointer to the mean
472
+ Rstd, # pointer to the 1/std
473
+ stride_x_row, # how much to increase the pointer when moving by 1 row
474
+ stride_y_row,
475
+ stride_dy_row,
476
+ stride_dx_row,
477
+ stride_dres_row,
478
+ stride_dy1_row,
479
+ stride_dx1_row,
480
+ stride_dres_in_row,
481
+ M, # number of rows in X
482
+ N, # number of columns in X
483
+ eps, # epsilon to avoid division by zero
484
+ dropout_p,
485
+ zero_centered_weight,
486
+ rows_per_program,
487
+ IS_RMS_NORM: tl.constexpr,
488
+ BLOCK_N: tl.constexpr,
489
+ HAS_DRESIDUAL: tl.constexpr,
490
+ STORE_DRESIDUAL: tl.constexpr,
491
+ HAS_BIAS: tl.constexpr,
492
+ HAS_DROPOUT: tl.constexpr,
493
+ HAS_ROWSCALE: tl.constexpr,
494
+ HAS_DY1: tl.constexpr,
495
+ HAS_DX1: tl.constexpr,
496
+ HAS_B1: tl.constexpr,
497
+ RECOMPUTE_OUTPUT: tl.constexpr,
498
+ ):
499
+ # Map the program id to the elements of X, DX, and DY it should compute.
500
+ row_block_id = tl.program_id(0)
501
+ row_start = row_block_id * rows_per_program
502
+ # Do not early exit if row_start >= M, because we need to write DW and DB
503
+ cols = tl.arange(0, BLOCK_N)
504
+ mask = cols < N
505
+ X += row_start * stride_x_row
506
+ if HAS_DRESIDUAL:
507
+ DRESIDUAL += row_start * stride_dres_row
508
+ if STORE_DRESIDUAL:
509
+ DRESIDUAL_IN += row_start * stride_dres_in_row
510
+ DY += row_start * stride_dy_row
511
+ DX += row_start * stride_dx_row
512
+ if HAS_DY1:
513
+ DY1 += row_start * stride_dy1_row
514
+ if HAS_DX1:
515
+ DX1 += row_start * stride_dx1_row
516
+ if RECOMPUTE_OUTPUT:
517
+ Y += row_start * stride_y_row
518
+ w = tl.load(W + cols, mask=mask).to(tl.float32)
519
+ if zero_centered_weight:
520
+ w += 1.0
521
+ if RECOMPUTE_OUTPUT and HAS_BIAS:
522
+ b = tl.load(B + cols, mask=mask, other=0.0).to(tl.float32)
523
+ if HAS_DY1:
524
+ w1 = tl.load(W1 + cols, mask=mask).to(tl.float32)
525
+ if zero_centered_weight:
526
+ w1 += 1.0
527
+ dw = tl.zeros((BLOCK_N,), dtype=tl.float32)
528
+ if HAS_BIAS:
529
+ db = tl.zeros((BLOCK_N,), dtype=tl.float32)
530
+ if HAS_DY1:
531
+ dw1 = tl.zeros((BLOCK_N,), dtype=tl.float32)
532
+ if HAS_B1:
533
+ db1 = tl.zeros((BLOCK_N,), dtype=tl.float32)
534
+ row_end = min((row_block_id + 1) * rows_per_program, M)
535
+ for row in range(row_start, row_end):
536
+ # Load data to SRAM
537
+ x = tl.load(X + cols, mask=mask, other=0).to(tl.float32)
538
+ dy = tl.load(DY + cols, mask=mask, other=0).to(tl.float32)
539
+ if HAS_DY1:
540
+ dy1 = tl.load(DY1 + cols, mask=mask, other=0).to(tl.float32)
541
+ if not IS_RMS_NORM:
542
+ mean = tl.load(Mean + row)
543
+ rstd = tl.load(Rstd + row)
544
+ # Compute dx
545
+ xhat = (x - mean) * rstd if not IS_RMS_NORM else x * rstd
546
+ xhat = tl.where(mask, xhat, 0.0)
547
+ if RECOMPUTE_OUTPUT:
548
+ y = xhat * w + b if HAS_BIAS else xhat * w
549
+ tl.store(Y + cols, y, mask=mask)
550
+ wdy = w * dy
551
+ dw += dy * xhat
552
+ if HAS_BIAS:
553
+ db += dy
554
+ if HAS_DY1:
555
+ wdy += w1 * dy1
556
+ dw1 += dy1 * xhat
557
+ if HAS_B1:
558
+ db1 += dy1
559
+ if not IS_RMS_NORM:
560
+ c1 = tl.sum(xhat * wdy, axis=0) / N
561
+ c2 = tl.sum(wdy, axis=0) / N
562
+ dx = (wdy - (xhat * c1 + c2)) * rstd
563
+ else:
564
+ c1 = tl.sum(xhat * wdy, axis=0) / N
565
+ dx = (wdy - xhat * c1) * rstd
566
+ if HAS_DRESIDUAL:
567
+ dres = tl.load(DRESIDUAL + cols, mask=mask, other=0).to(tl.float32)
568
+ dx += dres
569
+ # Write dx
570
+ if STORE_DRESIDUAL:
571
+ tl.store(DRESIDUAL_IN + cols, dx, mask=mask)
572
+ if HAS_DX1:
573
+ if HAS_DROPOUT:
574
+ keep_mask = (
575
+ tl.rand(tl.load(SEEDS + M + row).to(tl.uint32), cols, n_rounds=7) > dropout_p
576
+ )
577
+ dx1 = tl.where(keep_mask, dx / (1.0 - dropout_p), 0.0)
578
+ else:
579
+ dx1 = dx
580
+ tl.store(DX1 + cols, dx1, mask=mask)
581
+ if HAS_DROPOUT:
582
+ keep_mask = tl.rand(tl.load(SEEDS + row).to(tl.uint32), cols, n_rounds=7) > dropout_p
583
+ dx = tl.where(keep_mask, dx / (1.0 - dropout_p), 0.0)
584
+ if HAS_ROWSCALE:
585
+ rowscale = tl.load(ROWSCALE + row).to(tl.float32)
586
+ dx *= rowscale
587
+ tl.store(DX + cols, dx, mask=mask)
588
+
589
+ X += stride_x_row
590
+ if HAS_DRESIDUAL:
591
+ DRESIDUAL += stride_dres_row
592
+ if STORE_DRESIDUAL:
593
+ DRESIDUAL_IN += stride_dres_in_row
594
+ if RECOMPUTE_OUTPUT:
595
+ Y += stride_y_row
596
+ DY += stride_dy_row
597
+ DX += stride_dx_row
598
+ if HAS_DY1:
599
+ DY1 += stride_dy1_row
600
+ if HAS_DX1:
601
+ DX1 += stride_dx1_row
602
+ tl.store(DW + row_block_id * N + cols, dw, mask=mask)
603
+ if HAS_BIAS:
604
+ tl.store(DB + row_block_id * N + cols, db, mask=mask)
605
+ if HAS_DY1:
606
+ tl.store(DW1 + row_block_id * N + cols, dw1, mask=mask)
607
+ if HAS_B1:
608
+ tl.store(DB1 + row_block_id * N + cols, db1, mask=mask)
609
+
610
+
611
+ def _layer_norm_bwd(
612
+ dy,
613
+ x,
614
+ weight,
615
+ bias,
616
+ eps,
617
+ mean,
618
+ rstd,
619
+ dresidual=None,
620
+ dy1=None,
621
+ weight1=None,
622
+ bias1=None,
623
+ seeds=None,
624
+ dropout_p=0.0,
625
+ rowscale=None,
626
+ has_residual=False,
627
+ has_x1=False,
628
+ zero_centered_weight=False,
629
+ is_rms_norm=False,
630
+ x_dtype=None,
631
+ recompute_output=False,
632
+ ):
633
+ M, N = x.shape
634
+ assert x.stride(-1) == 1
635
+ assert dy.stride(-1) == 1
636
+ assert dy.shape == (M, N)
637
+ if dresidual is not None:
638
+ assert dresidual.stride(-1) == 1
639
+ assert dresidual.shape == (M, N)
640
+ assert weight.shape == (N,)
641
+ assert weight.stride(-1) == 1
642
+ if bias is not None:
643
+ assert bias.stride(-1) == 1
644
+ assert bias.shape == (N,)
645
+ if dy1 is not None:
646
+ assert weight1 is not None
647
+ assert dy1.shape == dy.shape
648
+ assert dy1.stride(-1) == 1
649
+ if weight1 is not None:
650
+ assert weight1.shape == (N,)
651
+ assert weight1.stride(-1) == 1
652
+ if bias1 is not None:
653
+ assert bias1.shape == (N,)
654
+ assert bias1.stride(-1) == 1
655
+ if seeds is not None:
656
+ assert seeds.is_contiguous()
657
+ assert seeds.shape == (M if not has_x1 else M * 2,)
658
+ if rowscale is not None:
659
+ assert rowscale.is_contiguous()
660
+ assert rowscale.shape == (M,)
661
+ # allocate output
662
+ dx = (
663
+ torch.empty_like(x)
664
+ if x_dtype is None
665
+ else torch.empty(M, N, dtype=x_dtype, device=x.device)
666
+ )
667
+ dresidual_in = (
668
+ torch.empty_like(x)
669
+ if has_residual
670
+ and (dx.dtype != x.dtype or dropout_p > 0.0 or rowscale is not None or has_x1)
671
+ else None
672
+ )
673
+ dx1 = torch.empty_like(dx) if (has_x1 and dropout_p > 0.0) else None
674
+ y = torch.empty(M, N, dtype=dy.dtype, device=dy.device) if recompute_output else None
675
+ if recompute_output:
676
+ assert weight1 is None, "recompute_output is not supported with parallel LayerNorm"
677
+
678
+ # Less than 64KB per feature: enqueue fused kernel
679
+ MAX_FUSED_SIZE = 65536 // x.element_size()
680
+ BLOCK_N = min(MAX_FUSED_SIZE, triton.next_power_of_2(N))
681
+ if N > BLOCK_N:
682
+ raise RuntimeError("This layer norm doesn't support feature dim >= 64KB.")
683
+ # Increasing the multiple (e.g. 8) will allow more thread blocks to be launched and hide the
684
+ # latency of the gmem reads/writes, but will increase the time of summing up dw / db.
685
+ sm_count = torch.cuda.get_device_properties(x.device).multi_processor_count * 8
686
+ _dw = torch.empty((sm_count, N), dtype=torch.float32, device=weight.device)
687
+ _db = (
688
+ torch.empty((sm_count, N), dtype=torch.float32, device=bias.device)
689
+ if bias is not None
690
+ else None
691
+ )
692
+ _dw1 = torch.empty_like(_dw) if weight1 is not None else None
693
+ _db1 = torch.empty_like(_db) if bias1 is not None else None
694
+ rows_per_program = math.ceil(M / sm_count)
695
+ grid = (sm_count,)
696
+ with torch.cuda.device(x.device.index):
697
+ _layer_norm_bwd_kernel[grid](
698
+ x,
699
+ weight,
700
+ bias,
701
+ y,
702
+ dy,
703
+ dx,
704
+ _dw,
705
+ _db,
706
+ dresidual,
707
+ weight1,
708
+ dy1,
709
+ dx1,
710
+ _dw1,
711
+ _db1,
712
+ dresidual_in,
713
+ rowscale,
714
+ seeds,
715
+ mean,
716
+ rstd,
717
+ x.stride(0),
718
+ 0 if not recompute_output else y.stride(0),
719
+ dy.stride(0),
720
+ dx.stride(0),
721
+ dresidual.stride(0) if dresidual is not None else 0,
722
+ dy1.stride(0) if dy1 is not None else 0,
723
+ dx1.stride(0) if dx1 is not None else 0,
724
+ dresidual_in.stride(0) if dresidual_in is not None else 0,
725
+ M,
726
+ N,
727
+ eps,
728
+ dropout_p,
729
+ zero_centered_weight,
730
+ rows_per_program,
731
+ is_rms_norm,
732
+ BLOCK_N,
733
+ dresidual is not None,
734
+ dresidual_in is not None,
735
+ bias is not None,
736
+ dropout_p > 0.0,
737
+ )
738
+ dw = _dw.sum(0).to(weight.dtype)
739
+ db = _db.sum(0).to(bias.dtype) if bias is not None else None
740
+ dw1 = _dw1.sum(0).to(weight1.dtype) if weight1 is not None else None
741
+ db1 = _db1.sum(0).to(bias1.dtype) if bias1 is not None else None
742
+ # Don't need to compute dresidual_in separately in this case
743
+ if has_residual and dx.dtype == x.dtype and dropout_p == 0.0 and rowscale is None:
744
+ dresidual_in = dx
745
+ if has_x1 and dropout_p == 0.0:
746
+ dx1 = dx
747
+ return (
748
+ (dx, dw, db, dresidual_in, dx1, dw1, db1)
749
+ if not recompute_output
750
+ else (dx, dw, db, dresidual_in, dx1, dw1, db1, y)
751
+ )
752
+
753
+
754
+ class LayerNormFn(torch.autograd.Function):
755
+ @staticmethod
756
+ def forward(
757
+ ctx,
758
+ x,
759
+ weight,
760
+ bias,
761
+ residual=None,
762
+ x1=None,
763
+ weight1=None,
764
+ bias1=None,
765
+ eps=1e-6,
766
+ dropout_p=0.0,
767
+ rowscale=None,
768
+ prenorm=False,
769
+ residual_in_fp32=False,
770
+ zero_centered_weight=False,
771
+ is_rms_norm=False,
772
+ return_dropout_mask=False,
773
+ out=None,
774
+ residual_out=None
775
+ ):
776
+ x_shape_og = x.shape
777
+ # Check for zero sequence length
778
+ if x.numel() == 0:
779
+ ctx.zero_seq_length = True
780
+ # Only save minimal required tensors for backward
781
+ # ctx.save_for_backward(weight, bias, weight1, bias1)
782
+ ctx.x_shape_og = x_shape_og
783
+ ctx.weight_shape = weight.shape
784
+ ctx.weight_dtype = weight.dtype
785
+ ctx.weight_device = weight.device
786
+
787
+ ctx.has_bias = bias is not None
788
+ ctx.bias_shape = bias.shape if bias is not None else None
789
+ ctx.bias_dtype = bias.dtype if bias is not None else None
790
+ ctx.bias_device = bias.device if bias is not None else None
791
+
792
+ ctx.has_weight1 = weight1 is not None
793
+ ctx.weight1_shape = weight1.shape if weight1 is not None else None
794
+ ctx.weight1_dtype = weight1.dtype if weight1 is not None else None
795
+ ctx.weight1_device = weight1.device if weight1 is not None else None
796
+
797
+ ctx.has_bias1 = bias1 is not None
798
+ ctx.bias1_shape = bias1.shape if bias1 is not None else None
799
+ ctx.bias1_dtype = bias1.dtype if bias1 is not None else None
800
+ ctx.bias1_device = bias1.device if bias1 is not None else None
801
+
802
+ ctx.has_residual = residual is not None
803
+ ctx.has_x1 = x1 is not None
804
+ ctx.dropout_p = dropout_p
805
+
806
+ # Handle output tensors with correct dtype
807
+ y = x # Preserve input tensor properties
808
+ y1 = torch.empty_like(x) if x1 is not None else None
809
+
810
+ # Only create residual_out if prenorm is True
811
+ residual_out = torch.empty(x.shape,
812
+ dtype=torch.float32 if residual_in_fp32 else x.dtype,
813
+ device=x.device) if prenorm else None
814
+
815
+ # Handle dropout masks
816
+ dropout_mask = None
817
+ dropout_mask1 = None
818
+ if return_dropout_mask:
819
+ dropout_mask = torch.empty_like(x, dtype=torch.uint8)
820
+ if x1 is not None:
821
+ dropout_mask1 = torch.empty_like(x, dtype=torch.uint8)
822
+
823
+ # Return based on configuration
824
+ if not return_dropout_mask:
825
+ if weight1 is None:
826
+ return y if not prenorm else (y, residual_out)
827
+ else:
828
+ return (y, y1) if not prenorm else (y, y1, residual_out)
829
+ else:
830
+ if weight1 is None:
831
+ return ((y, dropout_mask, dropout_mask1) if not prenorm
832
+ else (y, residual_out, dropout_mask, dropout_mask1))
833
+ else:
834
+ return ((y, y1, dropout_mask, dropout_mask1) if not prenorm
835
+ else (y, y1, residual_out, dropout_mask, dropout_mask1))
836
+
837
+ ctx.zero_seq_length = False
838
+ # reshape input data into 2D tensor
839
+ x = x.reshape(-1, x.shape[-1])
840
+ if x.stride(-1) != 1:
841
+ x = x.contiguous()
842
+ if residual is not None:
843
+ assert residual.shape == x_shape_og
844
+ residual = residual.reshape(-1, residual.shape[-1])
845
+ if residual.stride(-1) != 1:
846
+ residual = residual.contiguous()
847
+ if x1 is not None:
848
+ assert x1.shape == x_shape_og
849
+ assert rowscale is None, "rowscale is not supported with parallel LayerNorm"
850
+ x1 = x1.reshape(-1, x1.shape[-1])
851
+ if x1.stride(-1) != 1:
852
+ x1 = x1.contiguous()
853
+ weight = weight.contiguous()
854
+ if bias is not None:
855
+ bias = bias.contiguous()
856
+ if weight1 is not None:
857
+ weight1 = weight1.contiguous()
858
+ if bias1 is not None:
859
+ bias1 = bias1.contiguous()
860
+ if rowscale is not None:
861
+ rowscale = rowscale.reshape(-1).contiguous()
862
+ residual_dtype = (
863
+ residual.dtype
864
+ if residual is not None
865
+ else (torch.float32 if residual_in_fp32 else None)
866
+ )
867
+ if out is not None:
868
+ out = out.reshape(-1, out.shape[-1])
869
+ if residual_out is not None:
870
+ residual_out = residual_out.reshape(-1, residual_out.shape[-1])
871
+ y, y1, mean, rstd, residual_out, seeds, dropout_mask, dropout_mask1 = _layer_norm_fwd(
872
+ x,
873
+ weight,
874
+ bias,
875
+ eps,
876
+ residual,
877
+ x1,
878
+ weight1,
879
+ bias1,
880
+ dropout_p=dropout_p,
881
+ rowscale=rowscale,
882
+ residual_dtype=residual_dtype,
883
+ zero_centered_weight=zero_centered_weight,
884
+ is_rms_norm=is_rms_norm,
885
+ return_dropout_mask=return_dropout_mask,
886
+ out=out,
887
+ residual_out=residual_out
888
+ )
889
+ ctx.save_for_backward(
890
+ residual_out, weight, bias, weight1, bias1, rowscale, seeds, mean, rstd
891
+ )
892
+ ctx.x_shape_og = x_shape_og
893
+ ctx.eps = eps
894
+ ctx.dropout_p = dropout_p
895
+ ctx.is_rms_norm = is_rms_norm
896
+ ctx.has_residual = residual is not None
897
+ ctx.has_x1 = x1 is not None
898
+ ctx.prenorm = prenorm
899
+ ctx.x_dtype = x.dtype
900
+ ctx.zero_centered_weight = zero_centered_weight
901
+ y = y.reshape(x_shape_og)
902
+ y1 = y1.reshape(x_shape_og) if y1 is not None else None
903
+ residual_out = residual_out.reshape(x_shape_og) if residual_out is not None else None
904
+ dropout_mask = dropout_mask.reshape(x_shape_og) if dropout_mask is not None else None
905
+ dropout_mask1 = dropout_mask1.reshape(x_shape_og) if dropout_mask1 is not None else None
906
+ if not return_dropout_mask:
907
+ if weight1 is None:
908
+ return y if not prenorm else (y, residual_out)
909
+ else:
910
+ return (y, y1) if not prenorm else (y, y1, residual_out)
911
+ else:
912
+ if weight1 is None:
913
+ return (
914
+ (y, dropout_mask, dropout_mask1)
915
+ if not prenorm
916
+ else (y, residual_out, dropout_mask, dropout_mask1)
917
+ )
918
+ else:
919
+ return (
920
+ (y, y1, dropout_mask, dropout_mask1)
921
+ if not prenorm
922
+ else (y, y1, residual_out, dropout_mask, dropout_mask1)
923
+ )
924
+
925
+ @staticmethod
926
+ def backward(ctx, dy, *args):
927
+ if ctx.zero_seq_length:
928
+ return (
929
+ torch.zeros(ctx.x_shape_og, dtype=dy.dtype, device=dy.device),
930
+ torch.zeros(ctx.weight_shape, dtype=ctx.weight_dtype, device=ctx.weight_device),
931
+ torch.zeros(ctx.bias_shape, dtype=ctx.bias_dtype, device=ctx.bias_device) if ctx.has_bias else None,
932
+ torch.zeros(ctx.x_shape_og, dtype=dy.dtype, device=dy.device) if ctx.has_residual else None,
933
+ torch.zeros(ctx.x_shape_og, dtype=dy.dtype, device=dy.device) if ctx.has_x1 and ctx.dropout_p > 0.0 else None,
934
+ torch.zeros(ctx.weight1_shape, dtype=ctx.weight1_dtype, device=ctx.weight1_device) if ctx.has_weight1 else None,
935
+ torch.zeros(ctx.bias1_shape, dtype=ctx.bias1_dtype, device=ctx.bias1_device) if ctx.has_bias1 else None,
936
+ None,
937
+ None,
938
+ None,
939
+ None,
940
+ None,
941
+ None,
942
+ None,
943
+ None,
944
+ None,
945
+ None,
946
+ )
947
+
948
+ x, weight, bias, weight1, bias1, rowscale, seeds, mean, rstd = ctx.saved_tensors
949
+ dy = dy.reshape(-1, dy.shape[-1])
950
+ if dy.stride(-1) != 1:
951
+ dy = dy.contiguous()
952
+ assert dy.shape == x.shape
953
+ if weight1 is not None:
954
+ dy1, args = args[0], args[1:]
955
+ dy1 = dy1.reshape(-1, dy1.shape[-1])
956
+ if dy1.stride(-1) != 1:
957
+ dy1 = dy1.contiguous()
958
+ assert dy1.shape == x.shape
959
+ else:
960
+ dy1 = None
961
+ if ctx.prenorm:
962
+ dresidual = args[0]
963
+ dresidual = dresidual.reshape(-1, dresidual.shape[-1])
964
+ if dresidual.stride(-1) != 1:
965
+ dresidual = dresidual.contiguous()
966
+ assert dresidual.shape == x.shape
967
+ else:
968
+ dresidual = None
969
+
970
+ dx, dw, db, dresidual_in, dx1, dw1, db1 = _layer_norm_bwd(
971
+ dy,
972
+ x,
973
+ weight,
974
+ bias,
975
+ ctx.eps,
976
+ mean,
977
+ rstd,
978
+ dresidual,
979
+ dy1,
980
+ weight1,
981
+ bias1,
982
+ seeds,
983
+ ctx.dropout_p,
984
+ rowscale,
985
+ ctx.has_residual,
986
+ ctx.has_x1,
987
+ ctx.zero_centered_weight,
988
+ ctx.is_rms_norm,
989
+ x_dtype=ctx.x_dtype,
990
+ )
991
+ return (
992
+ dx.reshape(ctx.x_shape_og),
993
+ dw,
994
+ db,
995
+ dresidual_in.reshape(ctx.x_shape_og) if ctx.has_residual else None,
996
+ dx1.reshape(ctx.x_shape_og) if dx1 is not None else None,
997
+ dw1,
998
+ db1,
999
+ None,
1000
+ None,
1001
+ None,
1002
+ None,
1003
+ None,
1004
+ None,
1005
+ None,
1006
+ None,
1007
+ None,
1008
+ None,
1009
+ )
1010
+
1011
+
1012
+ def layer_norm_fn(
1013
+ x,
1014
+ weight,
1015
+ bias,
1016
+ residual=None,
1017
+ x1=None,
1018
+ weight1=None,
1019
+ bias1=None,
1020
+ eps=1e-6,
1021
+ dropout_p=0.0,
1022
+ rowscale=None,
1023
+ prenorm=False,
1024
+ residual_in_fp32=False,
1025
+ zero_centered_weight=False,
1026
+ is_rms_norm=False,
1027
+ return_dropout_mask=False,
1028
+ out=None,
1029
+ residual_out=None
1030
+ ):
1031
+ return LayerNormFn.apply(
1032
+ x,
1033
+ weight,
1034
+ bias,
1035
+ residual,
1036
+ x1,
1037
+ weight1,
1038
+ bias1,
1039
+ eps,
1040
+ dropout_p,
1041
+ rowscale,
1042
+ prenorm,
1043
+ residual_in_fp32,
1044
+ zero_centered_weight,
1045
+ is_rms_norm,
1046
+ return_dropout_mask,
1047
+ out,
1048
+ residual_out
1049
+ )
1050
+
1051
+
1052
+ def rms_norm_fn(
1053
+ x,
1054
+ weight,
1055
+ bias,
1056
+ residual=None,
1057
+ x1=None,
1058
+ weight1=None,
1059
+ bias1=None,
1060
+ eps=1e-6,
1061
+ dropout_p=0.0,
1062
+ rowscale=None,
1063
+ prenorm=False,
1064
+ residual_in_fp32=False,
1065
+ zero_centered_weight=False,
1066
+ return_dropout_mask=False,
1067
+ out=None,
1068
+ residual_out=None
1069
+ ):
1070
+ return LayerNormFn.apply(
1071
+ x,
1072
+ weight,
1073
+ bias,
1074
+ residual,
1075
+ x1,
1076
+ weight1,
1077
+ bias1,
1078
+ eps,
1079
+ dropout_p,
1080
+ rowscale,
1081
+ prenorm,
1082
+ residual_in_fp32,
1083
+ zero_centered_weight,
1084
+ True,
1085
+ return_dropout_mask,
1086
+ out,
1087
+ residual_out
1088
+ )
1089
+
1090
+
1091
+ class RMSNorm(torch.nn.Module):
1092
+
1093
+ def __init__(self, hidden_size, eps=1e-5, dropout_p=0.0, zero_centered_weight=False,
1094
+ device=None, dtype=None):
1095
+ factory_kwargs = {"device": device, "dtype": dtype}
1096
+ super().__init__()
1097
+ self.eps = eps
1098
+ if dropout_p > 0.0:
1099
+ self.drop = torch.nn.Dropout(dropout_p)
1100
+ else:
1101
+ self.drop = None
1102
+ self.zero_centered_weight = zero_centered_weight
1103
+ self.weight = torch.nn.Parameter(torch.empty(hidden_size, **factory_kwargs))
1104
+ self.register_parameter("bias", None)
1105
+ self.reset_parameters()
1106
+
1107
+ def reset_parameters(self):
1108
+ if not self.zero_centered_weight:
1109
+ torch.nn.init.ones_(self.weight)
1110
+ else:
1111
+ torch.nn.init.zeros_(self.weight)
1112
+
1113
+ def forward(self, x, residual=None, prenorm=False, residual_in_fp32=False):
1114
+ return rms_norm_fn(
1115
+ x,
1116
+ self.weight,
1117
+ self.bias,
1118
+ residual=residual,
1119
+ eps=self.eps,
1120
+ dropout_p=self.drop.p if self.drop is not None and self.training else 0.0,
1121
+ prenorm=prenorm,
1122
+ residual_in_fp32=residual_in_fp32,
1123
+ zero_centered_weight=self.zero_centered_weight,
1124
+ )
1125
+
1126
+
1127
+ class LayerNormLinearFn(torch.autograd.Function):
1128
+ @staticmethod
1129
+ @custom_fwd
1130
+ def forward(
1131
+ ctx,
1132
+ x,
1133
+ norm_weight,
1134
+ norm_bias,
1135
+ linear_weight,
1136
+ linear_bias,
1137
+ residual=None,
1138
+ eps=1e-6,
1139
+ prenorm=False,
1140
+ residual_in_fp32=False,
1141
+ is_rms_norm=False,
1142
+ ):
1143
+ x_shape_og = x.shape
1144
+ # reshape input data into 2D tensor
1145
+ x = x.reshape(-1, x.shape[-1])
1146
+ if x.stride(-1) != 1:
1147
+ x = x.contiguous()
1148
+ if residual is not None:
1149
+ assert residual.shape == x_shape_og
1150
+ residual = residual.reshape(-1, residual.shape[-1])
1151
+ if residual.stride(-1) != 1:
1152
+ residual = residual.contiguous()
1153
+ norm_weight = norm_weight.contiguous()
1154
+ if norm_bias is not None:
1155
+ norm_bias = norm_bias.contiguous()
1156
+ residual_dtype = (
1157
+ residual.dtype
1158
+ if residual is not None
1159
+ else (torch.float32 if residual_in_fp32 else None)
1160
+ )
1161
+ y, _, mean, rstd, residual_out, *rest = _layer_norm_fwd(
1162
+ x,
1163
+ norm_weight,
1164
+ norm_bias,
1165
+ eps,
1166
+ residual,
1167
+ out_dtype=None if not torch.is_autocast_enabled() else torch.get_autocast_dtype("cuda"),
1168
+ residual_dtype=residual_dtype,
1169
+ is_rms_norm=is_rms_norm,
1170
+ )
1171
+ y = y.reshape(x_shape_og)
1172
+ dtype = torch.get_autocast_dtype("cuda") if torch.is_autocast_enabled() else y.dtype
1173
+ linear_weight = linear_weight.to(dtype)
1174
+ linear_bias = linear_bias.to(dtype) if linear_bias is not None else None
1175
+ out = F.linear(y.to(linear_weight.dtype), linear_weight, linear_bias)
1176
+ # We don't store y, will be recomputed in the backward pass to save memory
1177
+ ctx.save_for_backward(residual_out, norm_weight, norm_bias, linear_weight, mean, rstd)
1178
+ ctx.x_shape_og = x_shape_og
1179
+ ctx.eps = eps
1180
+ ctx.is_rms_norm = is_rms_norm
1181
+ ctx.has_residual = residual is not None
1182
+ ctx.prenorm = prenorm
1183
+ ctx.x_dtype = x.dtype
1184
+ ctx.linear_bias_is_none = linear_bias is None
1185
+ return out if not prenorm else (out, residual_out.reshape(x_shape_og))
1186
+
1187
+ @staticmethod
1188
+ @custom_bwd
1189
+ def backward(ctx, dout, *args):
1190
+ x, norm_weight, norm_bias, linear_weight, mean, rstd = ctx.saved_tensors
1191
+ dout = dout.reshape(-1, dout.shape[-1])
1192
+ dy = F.linear(dout, linear_weight.t())
1193
+ dlinear_bias = None if ctx.linear_bias_is_none else dout.sum(0)
1194
+ if dy.stride(-1) != 1:
1195
+ dy = dy.contiguous()
1196
+ assert dy.shape == x.shape
1197
+ if ctx.prenorm:
1198
+ dresidual = args[0]
1199
+ dresidual = dresidual.reshape(-1, dresidual.shape[-1])
1200
+ if dresidual.stride(-1) != 1:
1201
+ dresidual = dresidual.contiguous()
1202
+ assert dresidual.shape == x.shape
1203
+ else:
1204
+ dresidual = None
1205
+ dx, dnorm_weight, dnorm_bias, dresidual_in, _, _, _, y = _layer_norm_bwd(
1206
+ dy,
1207
+ x,
1208
+ norm_weight,
1209
+ norm_bias,
1210
+ ctx.eps,
1211
+ mean,
1212
+ rstd,
1213
+ dresidual=dresidual,
1214
+ has_residual=ctx.has_residual,
1215
+ is_rms_norm=ctx.is_rms_norm,
1216
+ x_dtype=ctx.x_dtype,
1217
+ recompute_output=True,
1218
+ )
1219
+ dlinear_weight = torch.einsum("bo,bi->oi", dout, y)
1220
+ return (
1221
+ dx.reshape(ctx.x_shape_og),
1222
+ dnorm_weight,
1223
+ dnorm_bias,
1224
+ dlinear_weight,
1225
+ dlinear_bias,
1226
+ dresidual_in.reshape(ctx.x_shape_og) if ctx.has_residual else None,
1227
+ None,
1228
+ None,
1229
+ None,
1230
+ None,
1231
+ )
1232
+
1233
+
1234
+ def layer_norm_linear_fn(
1235
+ x,
1236
+ norm_weight,
1237
+ norm_bias,
1238
+ linear_weight,
1239
+ linear_bias,
1240
+ residual=None,
1241
+ eps=1e-6,
1242
+ prenorm=False,
1243
+ residual_in_fp32=False,
1244
+ is_rms_norm=False,
1245
+ ):
1246
+ return LayerNormLinearFn.apply(
1247
+ x,
1248
+ norm_weight,
1249
+ norm_bias,
1250
+ linear_weight,
1251
+ linear_bias,
1252
+ residual,
1253
+ eps,
1254
+ prenorm,
1255
+ residual_in_fp32,
1256
+ is_rms_norm,
1257
+ )