Coverage for / home / jenkins / .local / lib / python3.10 / site-packages / hyper_multicore / modules / mega_gate / diagnostics.py: 96%
55 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-11-15 05:03 +0800
« prev ^ index » next coverage.py v7.13.1, created at 2026-11-15 05:03 +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"""MegaGate broadcast task identities and native GM operand bindings."""
17from typing import Any
19from hyper_multicore._core_spec import get_device_core_spec
20from hyper_multicore.diagnostics.common.graph import bind_graph_tensor_ports
21from hyper_multicore.diagnostics.dump.l1 import L1TensorView, L1TensorViewContext
22from hyper_multicore.scheduler.graph import ComputeGraph, OperatorNode, OpType, SplitSpec, TensorSpec
25MEGA_GATE_OWNER_LABEL = "TokenRowShard"
26MEGA_GATE_ROUTE_STAGE_NAMES = (
27 "Softplus",
28 "Sqrt",
29 "AddBias",
30 "TopK",
31 "Gather",
32 "ReduceSum",
33 "AddEpsilon",
34 "Div",
35 "MulScale",
36 "CastIndex",
37)
39MEGA_GATE_ROUTE_GRAD_STAGE_NAMES = (
40 "MulsScaleGrad",
41 "BroadcastDenominator",
42 "Neg",
43 "DivSelected",
44 "DivSelectedRatio",
45 "MulCross",
46 "DivDirect",
47 "ReduceSum",
48 "BroadcastRowSum",
49 "AddSelectedGrad",
50 "ZerosLike",
51)
53MEGA_GATE_ROUTE_GRAD_K1_STAGE_NAMES = (
54 "MulsScaleGrad",
55 "ZerosLike",
56)
60def _port(name: str, position: int, dtype_size: int = 4) -> TensorSpec:
61 """Bind one native GM operand; shapes are invocation-owned."""
62 return TensorSpec(name, [], position, dtype_size=dtype_size, is_dynamic=True)
65def _row_view(context: L1TensorViewContext) -> L1TensorView:
66 """Mirror Route/RouteGrad tiling without running a Device-side resolver."""
67 tensor = context.parameters[context.tensor_spec.param_position]
68 shape = tuple(tensor.shape)
69 tokens = int(context.parameters[0].shape[0])
70 if context.tensor_spec.name in ("text_bias", "vision_bias") or (
71 context.tensor_spec.name == "image_mask" and tensor.numel() == 1
72 ):
73 return context.make_view(shape, source_offset_bytes=0)
74 cache_key = -1
75 if cache_key not in context.parameter_cache:
76 cores = int(context.runtime_config.num_workers)
77 if tensor.device.type == "npu":
78 cores = min(cores, get_device_core_spec(tensor.device.index).num_vector_cores)
79 workers = min(tokens, cores)
80 context.parameter_cache[cache_key] = (tokens + workers - 1) // workers
81 rows_per_worker = context.parameter_cache[cache_key]
82 offset = context.core_id * rows_per_worker
83 rows = max(0, min(rows_per_worker, tokens - offset))
84 if rows == 0:
85 return context.make_view((0, *shape[1:]), source_offset_bytes=0)
86 row_elements = tensor.numel() // tokens
87 return context.make_view((rows, *shape[1:]),
88 source_offset_bytes=offset * row_elements * tensor.element_size())
91def bind_pipeline_graph(graph: Any, config: Any, *, backward: bool = False) -> ComputeGraph:
92 """Build diagnostic ports only; native stages still use their original ABI.
94 RouteGrad's scatter/sqrt/softplus tail is launched by ACLNN after the MegaKernel.
95 A zero-task boundary node describes its L0 result, not an L1 Device capture.
96 Internal CANN workspace arrays are deliberately not advertised as ABI Tensors.
98 Args:
99 graph: Graph placeholder replaced by the lazily constructed broadcast graph.
100 config: Configuration consumed by this callback.
101 backward: Whether to prepare the RouteGrad pipeline instead of Route.
102 """
103 p = _port
104 if backward:
105 names = MEGA_GATE_ROUTE_GRAD_K1_STAGE_NAMES if config.task_num == 2 else MEGA_GATE_ROUTE_GRAD_STAGE_NAMES
106 bindings = {name: ([], []) for name in names}
107 bindings["MulsScaleGrad"] = ([p("grad_routing_weights", 2)], [])
108 if config.task_num != 2:
109 bindings["BroadcastDenominator"] = ([p("normalization_denominator", 1)], [])
110 bindings["DivSelected"] = ([p("selected_scores", 0)], [])
111 bindings["RouteGradPost"] = (
112 [p("logits", 10), p("route_scores", 3), p("expert_indices", 4, 8),
113 p("selected_scores", 0), p("normalization_denominator", 1)], [p("grad_logits", 9)],
114 )
115 names = (*names, "RouteGradPost")
116 else:
117 names = MEGA_GATE_ROUTE_STAGE_NAMES
118 score, selected, denominator = p("route_scores", 8), p("selected_scores", 9), p("normalization_denominator", 10)
119 bindings = {
120 "Softplus": ([p("logits", 0)], []),
121 "Sqrt": ([], [score]),
122 "AddBias": ([score, p("text_bias", 1), p("vision_bias", 2), p("image_mask", 3, 1)], []),
123 "TopK": ([], []), "Gather": ([score], [selected]), "ReduceSum": ([selected], []),
124 "AddEpsilon": ([], [denominator]), "Div": ([selected, denominator], []),
125 "MulScale": ([], [p("routing_weights", 6)]), "CastIndex": ([], [p("expert_indices", 7, 8)]),
126 }
127 graph = ComputeGraph()
128 previous = None
129 for index, name in enumerate(names):
130 node = OperatorNode(name, OpType.AIV_PIPELINE, [], [], [], 0, SplitSpec(None, lambda _: 1), 0, None,
131 diagnostic_name=name)
132 node.task_num = 1 if index < config.task_num else 0
133 graph.add_op(node)
134 if previous is not None:
135 graph.add_edge(previous, node)
136 previous = node
137 return bind_graph_tensor_ports(graph, bindings, _row_view)