Coverage for / home / jenkins / .local / lib / python3.10 / site-packages / hyper_parallel / auto_parallel / hyper_offload / _patch_accelerator.py: 40%
58 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-07-06 05:41 +0800
« prev ^ index » next coverage.py v7.13.1, created at 2026-07-06 05:41 +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"""Monkey-patch ``torch.accelerator`` on PyTorch < 2.6.
17PyTorch 2.5.x (and earlier) do **not** include the ``torch.accelerator``
18module that was introduced in PyTorch 2.6. This module creates a
19compatible namespace and injects it into the ``torch`` module so that
20all ``torch.accelerator.xxx`` calls work transparently regardless of
21the PyTorch version.
23Backend detection priority
24 #1. Ascend NPU — ``torch.npu.is_available()``
25 #2. NVIDIA GPU — ``torch.cuda.is_available()``
26 #3. No accelerator — stub (``is_available()`` returns ``False``)
28Usage
29 Importing this module applies the patch as a side-effect::
31 import hyper_parallel.auto_parallel.hyper_offload._patch_accelerator
33 Or simply import the parent package (``__init__.py`` already does this)::
35 import hyper_parallel.auto_parallel.hyper_offload # patch applied
37Notes
38 For NPU backends the APIs ``reset_peak_memory_stats`` and
39 ``max_memory_allocated`` are guarded with ``hasattr`` — if the
40 installed ``torch_npu`` does not provide them, they fall back to
41 no-ops / zero-returning stubs so that callers do not crash.
42 ``current_stream`` and ``empty_cache`` are expected on any
43 accelerator backend; if absent they will raise ``AttributeError``
44 at call time (fail-fast).
45"""
47from __future__ import annotations
49import types
51import torch
54def _patch() -> None:
55 """Inject ``torch.accelerator`` if not already present (PyTorch ≥ 2.6)."""
56 if hasattr(torch, "accelerator"):
57 return # PyTorch ≥ 2.6 — native support
59 accelerator = types.ModuleType("accelerator")
60 accelerator.__doc__ = "Monkey-patched ``torch.accelerator`` for PyTorch < 2.6"
62 # ── Backend detection ────────────────────────────────────────────
64 if hasattr(torch, "npu") and torch.npu.is_available():
65 # ---- Ascend NPU backend ----
66 def is_available() -> bool:
67 return torch.npu.is_available()
69 def current_accelerator() -> torch.device:
70 return torch.device("npu", index=torch.npu.current_device())
72 accelerator.is_available = is_available
73 accelerator.current_accelerator = current_accelerator
74 accelerator.current_stream = torch.npu.current_stream
75 accelerator.empty_cache = torch.npu.empty_cache
77 # These may not exist in older torch_npu versions
78 if hasattr(torch.npu, "reset_peak_memory_stats"):
79 accelerator.reset_peak_memory_stats = torch.npu.reset_peak_memory_stats
80 else:
81 def _npu_reset_peak_memory_stats() -> None:
82 pass # no-op fallback
83 accelerator.reset_peak_memory_stats = _npu_reset_peak_memory_stats
85 if hasattr(torch.npu, "max_memory_allocated"):
86 accelerator.max_memory_allocated = torch.npu.max_memory_allocated
87 else:
88 def _npu_max_memory_allocated() -> int:
89 return 0 # fallback
90 accelerator.max_memory_allocated = _npu_max_memory_allocated
92 elif torch.cuda.is_available():
93 # ---- NVIDIA GPU (CUDA) backend ----
94 def is_available() -> bool:
95 return torch.cuda.is_available()
97 def current_accelerator() -> torch.device:
98 return torch.device("cuda", index=torch.cuda.current_device())
100 accelerator.is_available = is_available
101 accelerator.current_accelerator = current_accelerator
102 accelerator.current_stream = torch.cuda.current_stream
103 accelerator.empty_cache = torch.cuda.empty_cache
104 accelerator.reset_peak_memory_stats = torch.cuda.reset_peak_memory_stats
105 accelerator.max_memory_allocated = torch.cuda.max_memory_allocated
107 else:
108 # ---- No accelerator available (CPU-only) ----
109 def is_available() -> bool:
110 return False
112 def current_accelerator() -> torch.device:
113 raise RuntimeError(
114 "No accelerator available (torch.accelerator not supported on CPU)"
115 )
117 def current_stream() -> torch.Stream:
118 raise RuntimeError(
119 "No accelerator available (torch.accelerator not supported on CPU)"
120 )
122 def empty_cache() -> None:
123 pass
125 def reset_peak_memory_stats() -> None:
126 pass
128 def max_memory_allocated() -> int:
129 return 0
131 accelerator.is_available = is_available
132 accelerator.current_accelerator = current_accelerator
133 accelerator.current_stream = current_stream
134 accelerator.empty_cache = empty_cache
135 accelerator.reset_peak_memory_stats = reset_peak_memory_stats
136 accelerator.max_memory_allocated = max_memory_allocated
138 # ── Inject into torch ────────────────────────────────────────────
139 torch.accelerator = accelerator
142_patch()