Coverage for / home / jenkins / .local / lib / python3.10 / site-packages / hyper_parallel / core / dtensor / debug / _call_records.py: 95%
57 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-08-04 05:18 +0800
« prev ^ index » next coverage.py v7.13.1, created at 2026-08-04 05:18 +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"""Structured call record classes for CommDebugMode tracing."""
16import time
17from dataclasses import dataclass, field
18from typing import List, Optional, Tuple
21@dataclass
22class TensorInfo:
23 """Metadata snapshot of a tensor at trace time."""
24 shape: Tuple[int, ...]
25 dtype: str
26 is_dtensor: bool = False
27 placements: Optional[Tuple] = None
28 mesh_shape: Optional[Tuple[int, ...]] = None
31@dataclass
32class DebugCall:
33 """Base class for all traced call records.
35 Maintains a tree structure via ``children`` so that collective calls
36 appear nested under the operator that triggered them.
37 """
38 call_depth: int = 0
39 timestamp: float = field(default_factory=time.time)
40 children: List["DebugCall"] = field(default_factory=list)
42 def _render_self(self) -> str:
43 return f"[DebugCall depth={self.call_depth}]"
45 def render(self, indent: int = 0) -> str:
46 prefix = " " * indent
47 lines = [f"{prefix}{self._render_self()}"]
48 for child in self.children:
49 lines.append(child.render(indent + 1))
50 return "\n".join(lines)
53@dataclass
54class OpCall(DebugCall):
55 """Record of a DTensor operator dispatch."""
56 op_name: str = ""
57 input_infos: List[TensorInfo] = field(default_factory=list)
58 output_infos: List[TensorInfo] = field(default_factory=list)
60 def _render_self(self) -> str:
61 inputs_str = ", ".join(
62 f"{'DTensor' if t.is_dtensor else 'Tensor'}{list(t.shape)}"
63 for t in self.input_infos
64 )
65 outputs_str = ", ".join(
66 f"{'DTensor' if t.is_dtensor else 'Tensor'}{list(t.shape)}"
67 for t in self.output_infos
68 )
69 return f"Op({self.op_name}) inputs=[{inputs_str}] outputs=[{outputs_str}]"
72@dataclass
73class CollectiveCall(DebugCall):
74 """Record of a collective communication operation."""
75 collective_type: str = ""
76 group_size: int = 0
77 group: Optional[str] = None
78 input_shape: Optional[Tuple[int, ...]] = None
79 output_shape: Optional[Tuple[int, ...]] = None
80 input_dtype: str = ""
82 def _render_self(self) -> str:
83 group_str = f"group={self.group}" if self.group is not None else f"group_size={self.group_size}"
84 return (
85 f"Collective({self.collective_type}) "
86 f"{group_str} "
87 f"input_shape={self.input_shape} "
88 f"output_shape={self.output_shape}"
89 )
92@dataclass
93class RedistributeCall(DebugCall):
94 """Record of a DTensor redistribute operation."""
95 src_placements: Optional[Tuple] = None
96 dst_placements: Optional[Tuple] = None
97 tensor_shape: Optional[Tuple[int, ...]] = None
99 def _render_self(self) -> str:
100 return (
101 f"Redistribute(shape={self.tensor_shape}) "
102 f"{self.src_placements} -> {self.dst_placements}"
103 )
106@dataclass
107class AnnotateCall(DebugCall):
108 """Record of a module boundary event (enter/exit)."""
109 annotation: str = ""
110 module_fqn: str = ""
111 event_type: str = "" # "enter" or "exit"
113 def _render_self(self) -> str:
114 return f"Module({self.module_fqn}) [{self.event_type}]"