main
py 80 lines 2.58 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 import torch
4 from torch import Tensor
5
6 from ..op import register_op
7
8
9 @register_op
10 def rms_norm(
11 x: Tensor, weight: Tensor | None, epsilon: float, variance_size: int | None = None
12 ) -> Tensor:
13 """Weighted root-mean-square layer normalization."""
14 orig_dtype = x.dtype
15 x = x.to(torch.float32)
16 x_var = x if variance_size is None else x[..., :variance_size]
17 variance = x_var.pow(2).mean(dim=-1, keepdim=True)
18 x = x * torch.rsqrt(variance + epsilon)
19 if weight is not None:
20 x = x.to(weight.dtype) * weight
21 return x.to(orig_dtype)
22
23
24 @rms_norm.register_input_generator
25 def _rms_norm_input_generator(
26 num_tokens: int,
27 hidden_size: int,
28 dtype: torch.dtype,
29 epsilon: float = 1e-5,
30 device: torch.device | str | None = None,
31 ) -> tuple:
32 x = torch.randn(num_tokens, hidden_size, dtype=dtype, device=device)
33 weight = torch.randn(hidden_size, dtype=dtype, device=device)
34 return x, weight, epsilon
35
36
37 # Reductions in rms_norm accumulate rounding error at large shapes
38 # (e.g. 32768x16384), causing a few elements out of millions to exceed
39 # the default float16 tolerance.
40 rms_norm.override_tolerance(torch.float16, atol=1e-2, rtol=2e-3)
41
42
43 @register_op(allow_inplace=True)
44 def fused_add_rms_norm(
45 x: Tensor,
46 x_residual: Tensor,
47 weight: Tensor | None,
48 epsilon: float,
49 variance_size: int | None = None,
50 ) -> tuple[Tensor, Tensor]:
51 """Fused add and weighted root-mean-square layer normalization."""
52 orig_dtype = x.dtype
53 x = x.to(torch.float32)
54 x = x + x_residual.to(torch.float32)
55 x_residual = x.to(orig_dtype)
56
57 x_var = x if variance_size is None else x[..., :variance_size]
58 variance = x_var.pow(2).mean(dim=-1, keepdim=True)
59 x = x * torch.rsqrt(variance + epsilon)
60 if weight is not None:
61 x = x.to(weight.dtype) * weight
62 return x.to(orig_dtype), x_residual
63
64
65 # fused_add_rms_norm has similar rounding error accumulation as rms_norm
66 fused_add_rms_norm.override_tolerance(torch.float16, atol=1e-2, rtol=2e-3)
67
68
69 @fused_add_rms_norm.register_input_generator
70 def _fused_add_rms_norm_input_generator(
71 num_tokens: int,
72 hidden_size: int,
73 dtype: torch.dtype,
74 epsilon: float = 1e-5,
75 device: torch.device | str | None = None,
76 ) -> tuple:
77 x = torch.randn(num_tokens, hidden_size, dtype=dtype, device=device)
78 x_residual = torch.randn(num_tokens, hidden_size, dtype=dtype, device=device)
79 weight = torch.randn(hidden_size, dtype=dtype, device=device)
80 return x, x_residual, weight, epsilon