Coverage for / home / jenkins / .local / lib / python3.10 / site-packages / hyper_parallel / components / functional / mhc_pre.py: 38%
37 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-10-25 05:45 +0800
« prev ^ index » next coverage.py v7.13.1, created at 2026-10-25 05:45 +0800
1# Copyright 2026 Huawei Technologies Co., Ltd
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ============================================================================
15"""Manifold hyper-connection pre-processing functions."""
17from typing import Any, Optional, Tuple
19import torch # pylint: disable=forbidden-backend-import
21try:
22 import omni_training_custom_ops # noqa: F401 # pylint: disable=unused-import
23except ImportError:
24 omni_training_custom_ops = None
26from hyper_parallel.components.functional.sinkhorn import sinkhorn
29def _mhc_pre_backward(ctx, dh_in, dh_post, dh_res, dh_x):
30 """Invoke the MHC gradient operator with the saved forward state."""
31 x, phi, alpha, gamma, h_post, inv_rms, h_mix, h_pre = ctx.saved_tensors
32 return torch.ops.custom.npu_manifold_constrained_hyper_connection_pre_grad(
33 x, phi, alpha, dh_in, dh_post, dh_res, inv_rms, h_mix, h_pre, h_post,
34 gamma=gamma,
35 hc_eps=ctx.hc_eps,
36 grad_x_post=dh_x,
37 )
40class _MhcPre(torch.autograd.Function):
41 """Autograd bridge for the NPU MHC pre custom operator."""
43 @staticmethod
44 def forward(
45 ctx: Any,
46 x: torch.Tensor,
47 phi: torch.Tensor,
48 alpha: torch.Tensor,
49 bias: torch.Tensor,
50 gamma: Optional[torch.Tensor] = None,
51 out_flag: bool = True,
52 norm_eps: float = 1e-6,
53 hc_eps: float = 1e-6,
54 ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]:
55 """Run the NPU MHC pre forward operator."""
56 if omni_training_custom_ops is None:
57 raise ImportError("MHC AscendC requires omni_training_custom_ops")
58 hin, h_post, h_comb_before, inv_rms, h_mix, h_pre = (
59 torch.ops.custom.npu_manifold_constrained_hyper_connection_pre(
60 x,
61 phi,
62 alpha,
63 bias,
64 gamma=gamma,
65 out_flag=out_flag,
66 norm_eps=norm_eps,
67 hc_eps=hc_eps,
68 )
69 )
70 ctx.save_for_backward(x, phi, alpha, gamma, h_post, inv_rms, h_mix, h_pre)
71 ctx.hc_eps = hc_eps
72 ctx.has_gamma = gamma is not None
73 return hin, h_pre, h_post, h_comb_before, x
75 @staticmethod
76 def backward(
77 ctx: Any,
78 dh_in: torch.Tensor,
79 dh_pre: torch.Tensor,
80 dh_post: torch.Tensor,
81 dh_res: torch.Tensor,
82 dh_x: torch.Tensor,
83 ) -> tuple:
84 """Run the NPU MHC pre backward operator."""
85 del dh_pre
86 dx, dphi, dalpha, dbias, dgamma = _mhc_pre_backward(ctx, dh_in, dh_post, dh_res, dh_x)
87 if not ctx.has_gamma:
88 dgamma = None
89 grads = [dx, dphi, dalpha, dbias, dgamma, None, None, None]
90 return tuple(grads)
93def mhc_pre(
94 x: torch.Tensor,
95 phi: torch.Tensor,
96 branch_alpha: torch.Tensor,
97 branch_beta: torch.Tensor,
98 num_stream: int,
99 sinkhorn_iters: int = 20,
100 norm_eps: float = 1e-6,
101 hc_eps: float = 1e-6,
102 gamma: Optional[torch.Tensor] = None,
103) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]:
104 """Prepare an input and its mixing coefficients for an MHC-wrapped block.
106 Args:
107 x: Flattened residual streams.
108 phi: MHC projection weight.
109 branch_alpha: Learned scale for each coefficient group.
110 branch_beta: Learned bias for each coefficient group.
111 num_stream: Number of residual streams.
112 sinkhorn_iters: Number of Sinkhorn iterations.
113 norm_eps: RMS normalization epsilon.
114 hc_eps: Hyper-connection numerical stability epsilon.
115 gamma: Optional RMS normalization scale.
117 Returns:
118 Block input, post coefficients, residual coefficients, and residual buffer.
119 """
120 shape = x.size()
121 x = x.reshape(shape[0], shape[1], num_stream, -1)
122 if gamma is not None:
123 gamma = gamma.reshape(num_stream, -1).float()
124 y, _, h_post, h_comb_before, residual = _MhcPre.apply(
125 x,
126 phi.float(),
127 branch_alpha.float(),
128 branch_beta.float(),
129 gamma,
130 True,
131 norm_eps,
132 hc_eps,
133 )
134 h_res = sinkhorn(h_comb_before, sinkhorn_iters, hc_eps)
135 residual = residual.reshape(shape[0], shape[1], -1)
136 return y, h_post, h_res, residual