Coverage for / home / jenkins / .local / lib / python3.10 / site-packages / hyper_parallel / core / dtensor / debug / _module_tracker.py: 17%
35 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"""nn.Module forward/backward hook tracker for CommDebugMode."""
16from typing import Callable, List
18from hyper_parallel.core.dtensor.dtensor import _distribute_module_named_modules
21class ModuleTracker:
22 """Registers hooks on *root_module* to track forward enter/exit events.
24 Args:
25 root_module: The top-level ``nn.Module`` to instrument.
26 on_module_event: Callback with ``(module_fqn, event_type)`` where
27 *event_type* is ``"enter"`` or ``"exit"``.
28 """
30 def __init__(self, root_module, on_module_event: Callable):
31 self._root = root_module
32 self._callback = on_module_event
33 self._hook_handles: List = []
34 self._fqn_map = {}
36 def install(self):
37 """Register forward_pre_hook and forward_hook on all sub-modules."""
38 # Build fully-qualified name map.
39 for name, mod in _distribute_module_named_modules(self._root):
40 self._fqn_map[id(mod)] = name or "(root)"
42 for _, mod in _distribute_module_named_modules(self._root):
43 fqn = self._fqn_map.get(id(mod), "unknown")
45 def _make_pre_hook(module_fqn):
46 def hook(module, inputs):
47 # pylint: disable=W0613
48 try:
49 self._callback(module_fqn, "enter")
50 except Exception: # pylint: disable=W0703
51 pass
52 return hook
54 def _make_post_hook(module_fqn):
55 def hook(module, inputs, output):
56 # pylint: disable=W0613
57 try:
58 self._callback(module_fqn, "exit")
59 except Exception: # pylint: disable=W0703
60 pass
61 return hook
63 handle_pre = mod.register_forward_pre_hook(_make_pre_hook(fqn))
64 handle_post = mod.register_forward_hook(_make_post_hook(fqn))
65 self._hook_handles.extend([handle_pre, handle_post])
67 def uninstall(self):
68 """Remove all registered hooks."""
69 for handle in self._hook_handles:
70 handle.remove()
71 self._hook_handles.clear()
72 self._fqn_map.clear()