| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
fix: add TORCH_NPU_WARNING_DISABLE env var and deprecate TORCH_NPU_DISABLED_WARNING Co-authored-by: wanglijun55<wanglijun55@noreply.gitcode.com> Co-authored-by: wanglijun55<wanglijun54@huawei.com> # message auto-generated for no-merge-commit merge: !44647 merge feat/warning-disable-env into master fix: add TORCH_NPU_WARNING_DISABLE env var and deprecate TORCH_NPU_DISABLED_WARNING Created-by: wanglijun55 Commit-by: wanglijun55 Merged-by: ascend-robot Description: # 【合入来源】 https://gitcode.com/Ascend/pytorch/issues/3989 - [x] issue/工单 # 【修改方案】 1. 新增环境变量 TORCH_NPU_WARNING_DISABLE,与现有 TORCH_NPU_DISABLED_WARNING 功能相同,均用于控制是否打印 TorchNPU 告警信息。两者指向同一代码片段。 2. 在 C++ 侧 OptionsManager::ShouldPrintWarning(torch_npu/csrc/core/npu/register/OptionsManager.cpp)与 Python 侧 _should_print_warning(torch_npu/_init/common/warning_utils.py)中,优先读取新变量 TORCH_NPU_WARNING_DISABLE;当新变量未设置而旧变量 TORCH_NPU_DISABLED_WARNING 被设置时,沿用旧变量行为,并通过 TORCH_NPU_WARN_ONCE(C++)/ warnings.warn(DeprecationWarning)(Python)打印一次弃用告警,提示用户迁移到新变量。 3. 当两者同时配置时,新变量 TORCH_NPU_WARNING_DISABLE 优先生效。 4. 文档侧:新增 TORCH_NPU_WARNING_DISABLE.md,在 TORCH_NPU_DISABLED_WARNING.md 顶部添加弃用提示,并同步更新菜单索引与环境变量列表。 # 【资料变更】 - 新增文档 docs/zh/api/environment_variable/alarm_message_printing/TORCH_NPU_WARNING_DISABLE.md - 更新文档 docs/zh/api/environment_variable/alarm_message_printing/TORCH_NPU_DISABLED_WARNING.md,顶部增加弃用提示 - 更新 docs/zh/api/environment_variable/alarm_message_printing/_menu_alarm_message_printing.md、docs/zh/api/environment_variable/_menu_environment_variable.md、docs/zh/api/environment_variable/env_variable_list.md 索引 # 【接口变更】 涉及。TORCH_NPU_DISABLED_WARNING环境变量增加废弃告警,后续用TORCH_NPU_WARNING_DISABLE代替。 # 【功能验证】 - 验证场景:分别设置 TORCH_NPU_WARNING_DISABLE=1、TORCH_NPU_DISABLED_WARNING=1、两者同时设置、均不设置四种情况下,告警打印行为符合预期。 - 验证方法: 1. export TORCH_NPU_WARNING_DISABLE=1 → 告警关闭,无弃用提示 2. export TORCH_NPU_DISABLED_WARNING=1 → 告警关闭,打印一次弃用告警,提示使用新变量 3. 同时设置两者 → 告警关闭,无弃用提示(新变量优先) 4. 均不设置 → 告警按 rank 规则正常打印 老环境变量=0,打印废弃告警;老环境变量=1,不打印  # 【CheckList】 - [x] 代码注释完备,正确记录错误日志 - [x] 代码实现进行了返回值、空指针等校验 - [x] PR标题正确使用类型标签,如:feat、fix、refactor、docs、test等 - [x] PR持续集成流水线(CI)执行通过,代码检查无异常 See merge request: Ascend/pytorch!44647 | 30 天前 | |
fix(inductor): add preload inductor for flight recorder Co-authored-by: ccyyccyyccyycc<changqiaowei@huawei.com> # message auto-generated for no-merge-commit merge: !45811 merge fix/flight-record-import-inductor into master fix(inductor): add preload inductor for flight recorder Created-by: ccyyccyyccyycc Commit-by: ccyyccyyccyycc Merged-by: ascend-robot Description: <!-- PR描述模板更新日期:20260203 --> # 【合入来源】 https://gitcode.com/Ascend/pytorch/issues/4611 - [ ] 需求 - [ ] 问题单 - [x] issue/工单 - [ ] 重构优化 - [ ] 资料更新 # 【修改方案】 **问题原因**:当 rank1 的 Python 线程发生 deadloop 并长期持有 GIL 时,HCCL watchdog 日志停在 ProcessGroupHCCL preparing to dump debug info。当前dump_hccl_trace调用链依赖torch::symbolize,现torch_npu的延迟 Inductor 初始化导致同步等待 GIL,watchdog 卡在 symbolization 阶段,未执行 writer。 **修复方案**:把 _inductor 的首次导入和 PyCodeCache 初始化从 HCCL timeout dump 路径提前到 import torch_npu 初始化阶段,消除首次 symbolization 的 lazy import/初始化时序因素。 1、在optional_features.py中新增_preload_inductor_for_hccl_fr_if_needed()方法; 2、当且仅当TORCH_HCCL_TRACE_BUFFER_SIZE > 0开启FR功能时执行预加载,避免无需使用FR特性时承担 Inductor 启动开销。 # 【资料变更】 不涉及 # 【接口变更】 不涉及 # 【功能验证】 > 说明测试场景,测试方法。如果本次测试方式与常规单元测试不同,请详细说明您的测试步骤\ > 新增/变更内容是否已新增/适配UT测试用例看护,并补充测试自验证截图 - 验证环境: torch-npu-2.13.0-py310、torch-npu-2.13.0-py311 - test\test_torch_npu_init.py#test_01_hccl_flight_recorder_preloads_torch_inductor()  # 【CheckList】 > PR提交人对以下CheckList自检项进行全量自检,自检通过或不涉及,均修改 [ ] 为 [x] - [x] 代码注释完备,正确记录错误日志 - [x] 代码实现进行了返回值、空指针等校验 - [x] PR标题正确使用类型标签,如:feat、fix、refactor、docs、test等 - [x] PR持续集成流水线(CI)执行通过,代码检查无异常 See merge request: Ascend/pytorch!45811 | 13 天前 | |
refactor: eliminate hccl sequence-number patch on torch 2.14+ Co-authored-by: qq_45774794<hetiancheng1@huawei.com> # message auto-generated for no-merge-commit merge: !44969 merge master into master refactor: eliminate hccl sequence-number patch on torch 2.14+ Created-by: qq_45774794 Commit-by: qq_45774794 Merged-by: ascend-robot Description: <!-- PR描述模板更新日期:20260203 --> # 【合入来源】 > <font color="red">**如有社区issue,请关联issue链接**</font>\ > <font color="red">**请勿携带内部流程信息(需求链接、问题单、内部issue等)**</font> - [ ] 需求 - [ ] 问题单 - [x] issue/工单 - [x] 重构优化 - [ ] 资料更新 # 【修改方案】 > 请描述修改内容的具体实现,涉及哪些组件之间进行交互,可以用1、2、3、...进行罗列\ > 如果是需求或者重构类的PR,需要补充详细设计文档(说明上下游组件关系、时序图、类图、DFX能力等内容) ### 1. 上游修复分析(pytorch#190138,2026-07-17 合入 main,2.14 nightly 已包含) 上游 ProcessGroup::getSequenceNumberForGroup() 原来有白名单 gatebackendSupportsSequenceNumbers(),仅放行 GLOO/NCCL/XCCL/UCC,HCCL 注册CUSTOM 后端会被 TORCH_CHECK 拒绝,这是 torch_npu 需要 patch 的根因。该 PR 删除了白名单,改为无条件转发到默认后端: cpp // torch/csrc/distributed/c10d/ProcessGroup.hpp(社区 main,修改后) virtual uint64_t getSequenceNumberForGroup() { return getDefaultBackend()->getSequenceNumberForGroup(); } ### 2. PTA 侧原 patch 代码 torch_npu/_init/patches/distributed_patches.py 将torch._C._distributed_c10d.ProcessGroup._get_sequence_number_for_g roup替换为torch_npu.distributed.distributed_c10d._hccl_get_sequence_number_for_group: python def _hccl_get_sequence_number_for_group(self): backend = torch.distributed.get_backend_config(self) if backend == "hccl" or backend == "npu:hccl": return self._get_backend(torch.device("npu"))._get_sequence_number_for_group() else: return origin_get_sequence_number_for_group(self) ### 3. 消除可行性(两条路径等价) 1. HCCL 注册为 BackendType.CUSTOM 且即默认后端,pg._get_backend(npu) 与 getDefaultBackend() 返回同一 ProcessGroupHCCL实例,该后端已实现 getSequenceNumberForGroup()(返回 seq_), 两条路径结果完全一致; 2. debug 模式 _ProcessGroupWrapper 也 override getSequenceNumberForGroup()并转发底层后端,路径一致; 3. 多后端(如 hccl,gloo)及其它后端:原 patch 本就回退原实现,行为不变。 因此 **torch ≥ 2.14 上该 patch 可消除**,由社区原生实现直接覆盖;torch 2.13 社区代码仍有白名单 gate,patch 需保留。 ### 4. 修改实现(patch 定义与安装整体收敛至 torch_npu/_compat/distributed.py) 参照 torch_npu/_compat/distributed.py 已有 COMPAT 例子的写法(如register_op_strategy / _mm_like_strategy / ShardedTensor npu() patch):版本判断、shim 定义与安装全部封装在 compat 模块内,消费方不感知。 1. torch_npu/_compat/distributed.py:新增 # COMPAT(< 2.14) 块(附 # CAN REMOVE when MIN_SUPPORTED >= (2, 14) 标记),自包含三步——捕获上游原实现 origin_get_sequence_number_for_group → 定义 shim _hccl_get_sequence_number_for_group → 安装到 _C10dProcessGroup._get_sequence_number_for_group。仅 CURRENT_VERSION < (2, 14) 时执行;捕获与安装同处一块,消除中间窗口期; 2. torch_npu/_init/patches/distributed_patches.py:**不改动**。文件头已有的 import torch_npu._compat.distributed 在 import 时即触发上述安装(与 ShardedTensor npu() patch 同一机制),_INTERNAL_REPLACEMENTS 中的无条件替换条目随之删除; 3. torch_npu/distributed/distributed_c10d.py:删除 _hccl_get_sequence_number_for_group 定义与模块级 origin_get_sequence_number_for_group 捕获,旧 torch 专用代码全部收敛进 compat,模块不再承担 patch 载体职责; 4. test/test_torch_npu_init.py test_07:断言改为按版本分支——CURRENT_VERSION < (2, 14) 时断言已替换为 shim(is 精确断言);否则断言 compat 未定义 shim、保持社区原实现。版本判断仍在 compat 模块内; 5. 新增 test/distributed/test_c10d_get_sequence_number.py(参照 _add_ephemeral_timeout_for_all_pgs 的测试模式):2 卡 hccl 用例验证序列号可查询且随 collective 递增(< 2.14 无 shim 时该调用直接抛异常,跑通即证明分派成功);单卡 gloo 用例验证非 hccl 后端走捕获的 origin(< 2.14)或原生实现(≥ 2.14)。 # 【资料变更】 > 请确认是否涉及资料变更。如涉及,需要在PR中体现,并简要说明修改内容。如不涉及,需填写“不涉及” 不涉及 # 【接口变更】 > 请确认是否涉及跨代码仓或者客户面可见的接口变更。如涉及,需要详细说明接口以及对应的变更内容,同时需要在资料中体现。如 不涉及,需填写“不涉及” 不涉及 # 【功能验证】 > 说明测试场景,测试方法。如果本次测试方式与常规单元测试不同,请详细说明您的测试步骤\ > 新增/变更内容是否已新增/适配UT测试用例看护,并补充测试自验证截图 测试环境:**torch 2.13.0+cpu + torch_npu 2.13.0+gita95ebd01**(EulerOS aarch64) 说明:torch 2.14 下的消除效果采用 venv + torch 2.14.0+cpu 验证 compat 分支逻辑(见验证四);hccl 真机 2.14 验证需待 torch_npu 完成 2.14 适配并重编后补验。 ### 验证一:test_07 与新增用例(2.13 < 2.14 分支) bash python test/test_torch_npu_init.py \ TestTorchNpuBootstrap.test_07_distributed_patch_behavior python test/distributed/test_c10d_get_sequence_number.py 预期:全部通过。2.13 上断言 ProcessGroup._get_sequence_number_for_group 仍被替换为 shim(行为与修改前一致),2 卡 hccl 用例输出 [rankN] sequence number OK: x -> y(递增),单卡 gloo 用例通过。 验证截图:   ### 验证二:2.13 功能回归(patch 仍生效) python import os import torch import torch.distributed as dist import torch_npu import torch_npu._compat.distributed as compat_distributed os.environ["MASTER_ADDR"] = "127.0.0.1" os.environ["MASTER_PORT"] = "29500" dist.init_process_group(backend="hccl", world_size=1, rank=0) pg = dist.group.WORLD # 2.13:patch 仍生效,shim 来自 compat 模块 assert torch._C._distributed_c10d.ProcessGroup._get_sequence_number_for_group \ is compat_distributed._hccl_get_sequence_number_for_group assert pg._get_sequence_number_for_group() == 0 dist.all_reduce(torch.ones(8).npu()) assert pg._get_sequence_number_for_group() >= 1 print("sequence number after all_reduce:", pg._get_sequence_number_for_group()) dist.destroy_process_group() 预期:无异常,all_reduce 后 sequence number 递增。  ### 验证三:compat 安装验证(2.13 下 shim 由 compat 模块安装) bash python -c "import torch, torch_npu, torch_npu._compat.distributed as cd; \ assert torch._C._distributed_c10d.ProcessGroup._get_sequence_number_for_group \ is cd._hccl_get_sequence_number_for_group; \ print('shim installed from compat OK')" 预期:输出 shim installed from compat OK。  ### 验证四:2.14 分支行为(venv + torch 2.14.0+cpu 实测) bash python3 -m venv /tmp/t214 && /tmp/t214/bin/pip install torch==2.14.0+cpu \ --extra-index-url https://download.pytorch.org/whl/cpu 在真 torch 2.14 上加载改后的 compat 模块并验证: - compat 文件加载正常; - shim / origin 均不定义(not hasattr 断言通过),ProcessGroup 保持上游实现; - 真实 gloo 单卡进程组走原生实现返回 int(gloo seq = 0)。 预期输出:torch 2.14 分支验证 OK, gloo seq = 0 hccl 真机 2.14:待 torch_npu 2.14 发布包推出后跑同一套测试即可(测试已按两版本分支写好,无需改动)。  # 【CheckList】 > PR提交人对以下CheckList自检项进行全量自检,自检通过或不涉及,均修改 [ ] 为 [x] - [x] 代码注释完备,正确记录错误日志 - [x] 代码实现进行了返回值、空指针等校验 - [x] PR标题正确使用类型标签,如:feat、fix、refactor、docs、test等 - [ ] PR持续集成流水线(CI)执行通过,代码检查无异常 See merge request: Ascend/pytorch!44969 | 9 天前 | |
feat(profiler): mspti backend for torch.profiler PrivateUse1 Co-authored-by: Dmitry Gladkov<gladkov.dmitry1@huawei.com> # message auto-generated for no-merge-commit merge: !44554 merge feat/mspti-kineto-backend into master feat(profiler): mspti backend for torch.profiler PrivateUse1 Created-by: gladkov_dmitry Commit-by: Dmitry Gladkov Merged-by: ascend-robot Description: <!-- PR描述模板更新日期:20260203 --> # 【合入来源】 - [x] Requirement / Feature - [ ] 问题单 - [ ] issue/工单 - [ ] 重构优化 - [ ] 资料更新 # 【Modification Scheme】 torch.profiler on Ascend collected CPU activity only. Nothing supplied device data for ProfilerActivity.PrivateUse1, so the NPU half of the timeline was empty and users had to reach for a second, incompatible profiler to see what the device did. This adds a libkineto plugin backed by mspti. NPU kernels now appear in a standard torch.profiler trace next to CPU operations, on one timeline. > PyTorch and libkineto are unchanged. The plugin registers itself through REGISTER_PRIVATEUSE1_PROFILER and is driven by libkineto through IActivityProfilerSession. > This is not torch_npu.profiler. That is a separate implementation over acl_prof with its own enums and configuration class; the two are independent front ends and can be used side by side. Files: > torch_npu/csrc/profiler/mspti_activity_profiler.{h,cpp}: the session - lifecycle, record conversion, device and stream lanes, flow emission. > torch_npu/csrc/framework/interface/MsptiInterface.{h,cpp}: wrappers over libmspti. Every symbol is resolved at runtime through FunctionLoader, so a missing or older libmspti.so gives an empty device lane rather than a link failure. > torch_npu/_init/registry/backend.py, CMakeLists.txt: registration and build. Kernels are linked back to the operations that launched them. A global RecordFunction callback pushes each operation's handle as an mspti external correlation id; mspti ties that handle to the correlation id of the launch call, which the kernel shares. processTrace turns the join into ac2g flows - the arrows a viewer draws from a CPU operation to the kernel it produced. > About three quarters of kernels link. The rest are launched outside any operation scope - allocator work, autograd internals, runtime housekeeping - and have nothing to point back to. The proportion is stable as the workload grows. > The flow tail is a PRIVATEUSE1_RUNTIME marker on the host process, mirroring CUDA where flows start on a cuda_runtime event rather than on a cpu_op. Two presentation decisions worth knowing when reading a trace: > Device operators export without an mspti:: prefix, so they read the way CUDA kernels do in a torch.profiler trace. > The NPU process takes a sort index above any real pid, so its lane renders below the CPU lane. Correlation ids on exported activities come from a private counter rather than from mspti: mspti's ids are not unique per event and collide with torch's low cpu-side ids, which would fail upstream's uniqueness check. stop() drains until records stop arriving rather than until a fixed deadline. mspti delivers asynchronously, roughly 200 ms behind execution, so a time cap truncated the tail of a recording. The loop now exits once several consecutive flushes add nothing, which captures more and returns in about 150 ms. # 【Documentation Change】 > Not involved. Behaviour and limitations are described in the module header. # 【Interface Change】 > No API signature change. Customer-visible: profiling with activities=[ProfilerActivity.CPU, ProfilerActivity.PrivateUse1] now yields NPU device kernels in the trace and in events() / key_averages(), where previously the device side was empty. Existing CPU-only behaviour is unchanged. # 【Functional Verification】 bash cd /tmp && python test/profiler/test_mspti_backend.py > 12 tests in three classes on Ascend 910B4, CANN 9.1.0, torch 2.13.0+cpu. > TestMsptiBackend: kernels reach the trace, carry type and streamId, export without the mspti:: prefix, the NPU lane sorts below the CPU lane, and every cycle of a schedule() run collects - so the backend re-arms between cycles. > TestMsptiAc2g: flows are emitted as start and finish pairs, every start has a finish, one start per operation, none points backwards in time, the ids match operations recorded by torch, the two ends land on different lanes, and the whole trace fits one timeline. > Kernel counts are never asserted in the tests: mspti delivers records asynchronously, so counts vary between runs. The assertions are structural. Trace view. Collected from bare tensor operations rather than a model, so the device lane holds a predictable set of kernels: python a = torch.randn(4096, 4096, device="npu") b = torch.randn(4096, 4096, device="npu") def phases(): with record_function("matmul"): for _ in range(5): torch.matmul(a, b) with record_function("add"): for _ in range(5): torch.add(a, b) with record_function("sum"): for _ in range(5): torch.sum(a) phases() # warm up outside profiling torch.npu.synchronize() with profile(activities=[ProfilerActivity.CPU, ProfilerActivity.PrivateUse1]) as prof: phases() torch.npu.synchronize() prof.export_chrome_trace("trace.json") Fifteen operations issued, <N> device kernels collected. 4096x4096 keeps each kernel millisecond-scale and visible. Opened at ui.perfetto.dev.  > The NPU lane sits below the CPU lane with its kernels named, against the matmul, add and sum phases above, and an ac2g arrow runs from the operation to the kernel it launched. > The flow tail is placed at the kernel's timestamp rather than the host launch time: the host clock reachable from this path has a different base. The link itself is exact; only the arrow's visual origin is approximate. > On CANN versions: only 9.1.0 is installed on the verification machine, so this was not built against an earlier CANN. The mspti dependency is resolved at runtime through FunctionLoader rather than linked, so a CANN without libmspti.so gives an empty device lane rather than a build or load failure. The kineto include added to CMakeLists.txt points at PyTorch's bundled headers, not CANN's, so it carries no CANN version dependency. # 【CheckList】 - [x] Comments complete - [x] Return-value / null-pointer checks done - [x] PR title uses type label (feat) - [ ] PR持续集成流水线(CI)执行通过,代码检查无异常 See merge request: Ascend/pytorch!44554 | 1 个月前 | |
refactor for torch_npu init module. Co-authored-by: bellatan<tanmei2@huawei.com> # message auto-generated for no-merge-commit merge: !35338 merge torch_npu_init_refactor into master refactor for torch_npu init module. Created-by: bellatan Commit-by: bellatan Merged-by: ascend-robot Description: <!-- PR描述模板更新日期:20260203 --> # 【合入来源】 > <font color="red">**如有社区issue,请关联issue链接**</font>\ > <font color="red">**请勿携带内部流程信息(需求链接、问题单、内部issue等)**</font> - [ ] 需求 - [ ] 问题单 - [ ] issue/工单 - [x] 重构优化 - [ ] 资料更新 # 【修改方案】 本 PR 对 torch_npu 初始化链路进行重构,将原先集中在 torch_npu/__init__.py 中的初始化逻辑拆分到 _init 目录下的多个职责模块中,形成“**顶层编排 + 子模块分阶段执行 + 内部能力统一收口**”的结构。重构后,torch_npu/__init__.py 不再承载大量具体业务初始化细节,只负责固定初始化时序。各类具体能力分别由 _check_device_conflict、_load_core_modules、_register_components、_apply_patches、_enable_optional_features、_initialize_runtime_lifecycle 等内部函数承接。 ## 一、核心修改 ### 1. 重构 torch_npu/__init__.py 顶层初始化入口 重构后的初始化流程如下: python def _initialize(): _check_device_conflict() _load_core_modules() _register_components() _apply_patches() _enable_optional_features() _initialize_runtime_lifecycle() 顶层入口主要负责: 1. 维护 __all__; 2. 在 import torch 前关闭 TORCH_DEVICE_BACKEND_AUTOLOAD,避免 PyTorch 后端自动加载导致循环依赖; 3. 提前导入 torch_npu.utils.patch_getenv,用于捕获初始化阶段的环境变量访问; 4. 按固定顺序调用各初始化阶段入口; 5. 保留 _autoload() 作为 PyTorch 后端自动加载入口,用于恢复 TORCH_DEVICE_BACKEND_AUTOLOAD。 --- ### 2. 新增 _init 目录: 目录结构如下: text torch_npu/_init/ __init__.py common/ warning_utils.py core/ _exports.py module_loader.py optional_features.py runtime_lifecycle.py patches/ __init__.py api_patches.py asd_patches.py distributed_patches.py dynamo_patches.py monkey_patches.py npu_patches.py patch_manager.py profiler_patches.py warning_patches.py registry/ __init__.py backend.py distributed.py dynamo.py registry_manager.py --- ### 3. 通过 _check_device_conflict() 处理前置设备冲突检查 **_check_device_conflict()**:负责最早期的设备冲突检查,避免 NPU 与其他 accelerator 同时启用。该接口属于初始化内部逻辑,不作为 public API 暴露。 --- ### 4. 通过 _load_core_modules() 统一管理核心模块加载、注册副作用和顶层 API 导出 _load_core_modules() 将原先散落在 torch_npu/__init__.py 中的模块导入、底层 _C 子模块准备、基础 runtime 支撑模块初始化、导入即注册副作用以及顶层 API 导出统一收口。该阶段主要负责: 1. 加载 torch_npu 初始化所需的核心模块; 2. 统一准备 _C child submodules; 3. 初始化 logging、profiler、distributed 等基础组件; 4. 在 _C 准备完成后进行 torch_npu.npu 导入检查; 5. 加载需要通过 import 触发注册副作用的 Python 模块; 6. 导出 torch_npu 顶层 public API。 具体包括: * _C 子模块初始化:统一创建并注册 _profiler、_distributed_c10d、_cd、_logging、_flops_count 等 _C child submodules,保证业务 Python 模块只消费这些子模块,不再各自创建。 * torch_npu.npu 导入检查:在 _C 子模块完成准备后再检查 torch_npu.npu 导入状态,既保留对底层依赖缺失的友好报错,又避免 _C 未就绪时提前 import torch_npu.npu 导致循环导入。 * 导入副作用模块加载:统一加载需要通过 import 触发注册副作用的模块,例如 aclnn、optim、afd、custom ops、op_plugin、meta registrations 等,避免注册类副作用散落在初始化流程中。 * 顶层 API 导出:通过 export_all 将 torch_npu 顶层公开 API 统一导出到 globals() 和 __all__ 中,保证 public API 行为与旧版兼容。 * lazy Python API:对 HiFloat8Tensor、erase_stream、matmul_checksum 等接口采用 lazy export,保证接口可见但不在 import 阶段立即加载对应模块,减少循环导入风险。 * NPU custom ops:将 torch.ops.npu 下的公开算子导出到 torch_npu 顶层,并保留 torch.<op> deprecated wrapper。 * dtype symbols:将 _C._cd.DType 中的 dtype 符号导出到 torch_npu 顶层。 --- ### 5. 通过 _register_components() 统一管理框架集成注册 _register_components() 负责 backend 和 framework integration 注册,将原先散落在顶层入口中的 NPU backend、distributed、Dynamo、RPC、Inductor 等注册逻辑统一收口。通过该阶段统一收口后,框架集成注册逻辑不再散落在顶层 __init__.py 中,后续新增集成能力时可直接在 registry 目录下维护。该阶段主要负责: * NPU backend 注册:将 PyTorch PrivateUse1 backend 映射为 NPU,并注册 torch.npu 设备模块和相关方法。 * distributed backend 注册:注册 HCCL、LCCL backend,保证 NPU distributed 能力可用。 * Dynamo 注册:注册 Dynamo backend、NPU device interface 和 trace rules,保证 NPU 能接入 Dynamo 编译链路。 * RPC 注册:注册 NPU RPC backend,保证 RPC 场景下 NPU backend 可用。 * Inductor lightweight override 注册:只注册轻量级 NPU device op override,避免 import 阶段提前加载 heavy module。 * 默认 gradient device type 配置:保持 checkpoint 等场景下默认设备类型与旧行为兼容。 --- ### 6. 通过 _apply_patches() 统一管理 patch 注册与执行 引入集中式 patch 管理机制,统一收口原先散落在初始化入口中的 patch 逻辑。顶层入口 _apply_patches() 负责触发 patch 发现、注册和执行,具体由 PatchManager 承接。_apply_patches() 主要完成以下工作: 1. **patch 分组注册**:各组件 patch 按 group 注册,例如 monkey、api、distributed、dynamo、profiler、npu、warning、asd 等。 2. **内置 patch 自动发现**:PatchManager 会自动扫描 _init/patches 下符合命名规则的 patch 模块。模块被导入后,内部 patch 会完成注册。 3. **固定 patch 执行顺序**:patch group 按默认顺序执行,避免 import 顺序变化导致 patch 行为漂移。 4. **支持自定义 patch 顺序**:PatchManager 支持调整 patch group 执行顺序,便于测试或特殊场景扩展。 5. **异常钩子统一处理**:全局异常钩子由 PatchManager.run() 统一处理,便于初始化失败和运行时异常场景的集中管理。 --- ### 7. 通过 _enable_optional_features() 统一管理可选运行时能力 将 sanitizer、交互式模式配置、transfer_to_npu 等可选能力统一收口到 _enable_optional_features(),避免可选逻辑散落在顶层初始化入口。该阶段主要包括: python _enable_sanitizer_if_needed() _configure_interactive_mode() _enable_transfer_to_npu_if_needed() 具体说明: * sanitizer:仅在用户显式配置 TORCH_NPU_SANITIZER 时启用; * interactive mode:在交互式命令行环境中自动设置相关运行配置,并给出 warning 提示; * transfer_to_npu:通过 TORCH_TRANSFER_TO_NPU 控制是否启用,对非法配置进行显式报错。 --- ### 8. 通过 _initialize_runtime_lifecycle() 统一管理 runtime 生命周期 _initialize_runtime_lifecycle() 专门负责最终 C++ extension 初始化屏障和进程退出阶段的 shutdown hook 注册。该阶段主要包括: * extension finalize:调用 torch_npu._C._initExtension() 完成最终 C++ extension 绑定。该阶段放在核心模块加载、框架注册、API 导出和 patch 执行之后,保证 Python 侧初始化准备完成后再进入最终 extension barrier。 * shutdown hook 注册:负责注册进程退出阶段的 NPU 资源清理逻辑,包括设备同步、distributed 资源析构、异常处理和其他 runtime 清理流程。 --- ## 三、重构目的和收益 本次重构的目标是把 torch_npu 初始化从“单文件集中式副作用堆叠”调整为“阶段化、组件化、可维护”的初始化框架。主要收益包括: 1. **顶层入口更清晰** torch_npu/__init__.py 只保留初始化编排,不再堆叠大量具体 import、注册、patch 和 shutdown 逻辑。 2. **初始化顺序更稳定** _C 子模块和基础 runtime 支撑能力统一由 _load_core_modules 准备,降低循环导入和 _C 未就绪时提前访问的风险。 3. **组件职责更清楚** 模块加载、框架注册、API 导出、patch、可选功能、runtime 生命周期分别由不同接口承接。 4. **patch 更易维护** 各组件 patch 可以在自己的文件中维护,由 PatchManager 自动发现和统一执行,减少顶层冲突。 5. **支持后续扩展** 新增初始化能力时,只需放到对应处理的接口 或 patch group 中,不需要继续膨胀 __init__.py。 6. **便于问题定位** 初始化链路被拆成明确阶段,出现问题时可以快速判断是模块加载、注册、导出、patch、optional feature 还是 runtime lifecycle 阶段异常。 --- ## 四、兼容性说明 本次重构保持以下兼容性: 1. import torch_npu 行为保持兼容; 2. 顶层公开 API 保持兼容; 3. __version__ 仍从 torch_npu.version 导出。 --- ## 五、PatchManager 机制说明 本 PR 引入 PatchManager,用于统一管理 torch_npu 初始化阶段的 patch 注册与执行。原先 patch 逻辑集中在 torch_npu/__init__.py 中,和初始化流程、模块导入、框架注册逻辑混在一起,导致顶层文件过重,也不利于各组件独立维护。本次重构后,patch 逻辑从顶层入口中解耦,由 _apply_patches() 作为顶层入口触发执行,具体注册、发现、排序、幂等保护由 PatchManager 管理。 PatchManager 主要支持以下能力: 1. patch 按 group 分组注册; 2. 内置 patch 模块自动发现; 3. patch 按固定顺序执行; 4. patch 执行具备幂等保护; 5. 支持组件自行维护 patch module; 6. 支持按 group 执行,为后续按需使能 patch 打基础; 7. 支持自定义 patch 顺序,便于测试和问题定位。 整体机制如下: text 组件 patch 文件自注册 ↓ PatchManager 自动发现/加载 ↓ 按 group 统一管理 ↓ 按固定顺序执行 ↓ 幂等保护,避免重复 patch --- ### 场景一:新增 torch_npu 内置 patch 如果新增的是 torch_npu 内置 patch,例如 distributed patch、profiler patch、NPU API patch、warning patch、ASD patch 等,可以直接放到:torch_npu/_init/patches/ 目录下,并按 group 注册。 示例: python from torch_npu._init.patches.patch_manager import PatchManager @PatchManager.register_patch("profiler") def apply_profiler_patch(): ... 使用方式: text 1. 在 _init/patches 下新增或修改对应 *_patches.py 文件; 2. 在文件中通过 @PatchManager.register_patch(group) 注册 patch; 3. import torch_npu 时,由 _apply_patches() 统一触发; 4. PatchManager 自动发现并按 group 顺序执行。 --- ### 场景二:组件自行维护 patch module 如果某个组件自己的目录下新加了patch 文件,通过 patch module 注册机制接入。 示例: python PatchManager.register_patch_module("torch_npu.some_component.some_patches") 组件自己的 patch 文件中仍然使用 group 注册: python from torch_npu._init.patches.patch_manager import PatchManager @PatchManager.register_patch("some_component") def apply_some_component_patch(): ... 使用方式: text 1. 组件在自己的目录中维护 patch 文件; 2. 通过 register_patch_module 注册该 patch module; 3. module 被导入后,内部 patch 自动注册到 PatchManager; 4. 后续仍由 PatchManager 统一排序和执行。 适用场景: text 组件有独立维护边界; patch 逻辑不适合放到中心化 patches 目录; 后续组件可能独立演进、迁移或删除。 --- ### 场景三:按 group 执行 patch,用于测试或后续按需使能 PatchManager 支持按 group 执行 patch。当前默认初始化路径仍执行全部注册 patch,后续也可按需使能。 示例: python PatchManager.apply_registered_patches("distributed") 使用方式: text 1. 指定需要执行的 patch group; 2. PatchManager 只执行该 group 下已注册的 patch; 3. 已执行过的 patch 不会重复执行; 4. 可用于单独验证某一类 patch 的行为。 适用场景: text 只验证 distributed patch; 只执行 profiler patch; 排查某一类 patch 对初始化流程的影响; 后续通过环境变量控制某个 patch group 是否启用。 如果需要调整 patch group 顺序,也可以使用: python PatchManager.set_patch_order([ "monkey", "api", "distributed", ]) 适用场景: text 测试 patch 顺序; 排查 patch 依赖问题; 特殊构建或实验场景调整 patch 执行顺序。 # 【资料变更】 > 不涉及 # 【接口变更】 > 不涉及 # 【功能验证】 新增 TestTorchNpuBootstrap 初始化专项测试,覆盖以下场景: 1. test_01_import_order_compatibility 验证 import torch_npu、import torch; import torch_npu、import torch_npu; import torch、重复 import torch_npu 等不同导入顺序保持兼容。 2. test_02_import_state_snapshot 验证 import torch_npu 后的初始化状态,包括 torch.npu 注册、Tensor/Module.npu 方法生成、_C child submodules 准备、旧版初始化副作用模块加载、非预期模块不 eager import、顶层关键属性可访问等。 3. test_03_public_exports_snapshot 验证顶层 public API 导出行为,包括 lazy Python APIs、torch.ops.npu public ops、deprecated torch.<op> alias、dtype symbols 等导出保持兼容。 4. test_04_framework_registration_snapshot 验证框架集成注册行为,包括 Dynamo NPU device interface、Dynamo backend、Inductor lightweight device op override、distributed backend、RPC backend 等注册保持生效。 5. test_05_runtime_lazy_init_semantics 验证 import 阶段不触发 NPU runtime lazy init,查询类 API 不触发完整 runtime 初始化,真实 runtime API 和显式 torch_npu.npu.init() 能正常触发 lazy init。 6. test_06_component_behavior_snapshot 验证关键组件行为保持兼容,包括 patch_getenv 生效、ASD detector 兼容 API、AFD 通过 torch_npu._afd 暴露、torch_npu._C._afd 不暴露、AFD ops 可访问等。 7. test_07_distributed_patch_behavior 验证 distributed patch 行为保持兼容,包括 distributed 内部函数替换、public API alias、rendezvous/launcher patch、FSDP 相关 patch 等。 新增测试用例本地验证通过。 # 【CheckList】 > PR提交人对以下CheckList自检项进行全量自检,自检通过或不涉及,均修改 [ ] 为 [x] - [x] 代码注释完备,正确记录错误日志 - [x] 代码实现进行了返回值、空指针等校验 - [x] PR标题正确使用类型标签,如:feat、fix、refactor、docs、test等 - [x] PR持续集成流水线(CI)执行通过,代码检查无异常 See merge request: Ascend/pytorch!35338 | 4 个月前 |