已合并
test: adapt Generator.clone_state test for NPU #43346
test: adapt Generator.clone_state test for NPU #43346
已合并
Flipped创建于 7月30日
Flipped
Flipped
7月30日

【合入来源】

issue:【社区任务】7月社区任务第三期-Ascend for PyTorch API 一致性开发(124) #3235

issue:[Usage]: torch.Generator.clone_state NPU一致性验证 #3476

【修改方案】

1. API基础功能及用例覆盖

torch.Generator.clone_state 用于克隆当前 Generator 的随机数状态,返回一个新的 Generator 对象。克隆后的 Generator 应保持与原 Generator 克隆时一致的 RNG 状态,从而保证后续随机数生成结果可复现。

PyTorch v2.11.0 官方社区中已存在 torch.Generator.clone_state 相关用例,检索结果包括:

test/test_cuda.py:2152
test/test_cuda.py:2255
test/inductor/test_cudagraph_trees.py:4822
test/test_xpu.py:1256

其中本次适配的官方目标用例为:

test/test_cuda.py::TestCuda.test_graphsafe_set_get_rng_state
test/test_cuda.py:L2138-L2215

该用例直接覆盖以下 Generator RNG 状态相关功能:

  • graphsafe_get_state
  • clone_state
  • graphsafe_set_state
  • 默认 Generator 在图场景下的 RNG 状态一致性

因此,本次无需新增自定义测试用例,只需适配现有 PyTorch 官方用例。

2. v2.11.0原有patch情况

v2.11.0 原本不存在:

test_upstream/test/test_cuda.py.patch

因此,本次为 v2.11.0 新增:

test_upstream/test/test_cuda.py.patch

原始官方用例中使用了 CUDA 专属接口和 CUDA 设备:

torch.Generator(device="cuda")
torch.cuda.CUDAGraph()
torch.cuda.Stream()
torch.cuda.default_generators[0]
torch.cuda.stream(s)
torch.cuda.current_stream().wait_stream(s)
torch.rand(..., device="cuda")

在 NPU 环境下直接运行时,该用例会因 CUDA graph 条件不满足而跳过,无法覆盖 torch.Generator.clone_state 在 NPU 上的行为。

此外,在导入测试依赖时,torch.cuda.get_device_capability() 在 NPU 环境下可能返回 None 或触发兼容性告警,因此本次增加兼容处理,避免测试导入阶段受到 CUDA capability 判断逻辑影响。

3. 本次修改内容

本次新增 test_upstream/test/test_cuda.py.patch,对 test_graphsafe_set_get_rng_state 进行 NPU 适配。

主要修改如下:

  1. 增加 NPU 相关导入:
import torch_npu
from torch_npu.contrib import transfer_to_npu
  1. 增加 torch.cuda.get_device_capability() 返回 None 时的兼容处理:
if torch.cuda.get_device_capability() is None:
    torch.cuda.get_device_capability = lambda device=None: (0, 0)  # noqa: E731
  1. 将目标用例中的 CUDA 设备张量替换为 NPU 设备张量:
torch.rand(..., device="npu")
  1. 将 Generator 初始化设备从 CUDA 替换为 NPU:
generator = torch.Generator(device="npu")
  1. 将 CUDA graph 相关接口替换为 NPU graph 对应接口:
g = torch.npu.NPUGraph()
s = torch.npu.Stream()
default_generator = torch.npu.default_generators[0]
  1. 将 CUDA stream 上下文替换为 NPU stream 上下文:
with torch.npu.stream(s):
  1. 将 CUDA stream 同步替换为 NPU stream 同步:
torch.npu.current_stream().wait_stream(s)
  1. 将原 CUDA graph 可用性判断替换为 NPU 可用性判断:
@unittest.skipIf(
    not torch.npu.is_available(), "NPU not available, skipping tests"
)
  1. 增加以下装饰器,避免 CUDA memory leak / non-default stream 检查逻辑影响 NPU 目标用例运行:
@skipCUDAMemoryLeakCheckIf(True)
@skipCUDANonDefaultStreamIf(True)

导入顺序说明

test/test_cuda.pytorch_npu / transfer_to_npu 的导入位置属于初始化依赖例外。

TestCuda 类存在类级跳过条件:

@unittest.skipIf(not TEST_CUDA, "CUDA not available, skipping tests")
class TestCuda(TestCase):

TEST_CUDA 来自 torch.testing._internal.common_cuda,会在模块导入阶段计算。若严格将 torch_npu / transfer_to_npu 放到所有 torch.testing 导入之后,NPU 环境下 TEST_CUDA 会提前计算为 False,导致目标用例 test_graphsafe_set_get_rng_state 被类级 skip,无法覆盖 torch.Generator.clone_state。

因此本 patch 保留 transfer_to_npu 在 common_cuda 导入前初始化。该处理不使用 try-except,不修改 TestCuda 类级 skip 条件,也不新增 NPU 专用测试类,仅用于保证官方目标用例能在 NPU 上真实执行。

本次只适配官方已有用例,不修改 torch.Generator.clone_state 接口实现。
本次适配的 test_graphsafe_set_get_rng_state 已能覆盖 torch.Generator.clone_state 在 NPU Generator RNG 状态克隆场景下的核心行为。

【资料变更】

已检查 master 分支 docs/zh/api/native_api 资料目录,torch.Generator.clone_state 为 PyTorch Generator 公开接口,非私有接口。该 API 属于 Generator 状态类 API,非计算类 API,与具体数据类型无关,限制与说明填写为 -

根据 master 分支最新资料目录规则,pytorch_2-9-0pytorch_2-10-0 目录已删除,本次不再补充;新增 pytorch_2-13-0 目录需要同步检查并刷新。资料补齐以 master 分支 docs/zh/api/native_api 当前实际存在的版本目录为准。

资料补齐已在 master 分支单独提交 PR。本次未新增独立的 torch-Generator.md 文件,而是在各版本已有 torch.md## Generators 章节中补充 clone_state() 条目,位置放在 set_state() 之后,保持 torch.Generator 相关 API 统一维护在 torch.md 中。

【接口变更】

不涉及。

本次仅适配 PyTorch 官方测试用例,不修改客户可见接口,不修改 torch.Generator.clone_state 功能实现。

【功能验证】

运行环境

操作系统:Ubuntu 22.04.5 LTS
机器架构:aarch64
昇腾硬件:Ascend 910B3 NPU
npu-smi版本:25.2.0
CANN版本:9.1.0-beta.1
Python版本:3.11
torch版本:2.11.0+cpu
torch-npu版本:2.11.0rc1

将最终 patch 应用到干净的 PyTorch v2.11.0 工作树后,运行官方目标用例。

cd /workspace

source /workspace/envs/torch-npu-2.11.0/bin/activate
source /usr/local/Ascend/ascend-toolkit/set_env.sh

unset PYTHONPATH
export PYTHONPATH=/workspace/pytorch-v2.11.0/test
export PYTHONNOUSERSITE=1
export PYTORCH_PRINT_REPRO_ON_FAILURE=0

python /workspace/pytorch-v2.11.0/test/test_cuda.py -v -k test_graphsafe_set_get_rng_state

验证结果:

test_graphsafe_set_get_rng_state (__main__.TestCuda.test_graphsafe_set_get_rng_state) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.190s

OK

最终 patch 可以在干净工作树中正常应用,修改后的官方用例已在 NPU 上通过,可以覆盖 torch.Generator.clone_state 的核心功能。

【CheckList】

likedislike
Pull Request已成功合入, 合并人@ascend-robot
(感谢 Flipped 的贡献)
FlippedFlipped
7月30日 创建了 pull request,commit 0fc52edb
atomgit-bot
atomgit-bot
7月30日 评论:

变更摘要

本次变更为 v2.11.0 新增 test_upstream/test/test_cuda.py.patch,将 PyTorch 官方 test_graphsafe_set_get_rng_state 用例(覆盖 torch.Generator.clone_stategraphsafe_get_stategraphsafe_set_state 等功能)从 CUDA 环境适配到 NPU 环境,使该测试可在 NPU 设备上验证随机数生成器状态克隆与图捕获场景下的一致性。

主要改动

  • 新增 NPU 适配的 patch 文件:创建 test_upstream/test/test_cuda.py.patch,对原始 test/test_cuda.py 进行 88 行新增的补丁,将 test_graphsafe_set_get_rng_state 测试用例从 CUDA 专属接口全面替换为 NPU 对应接口。
  • 设备与接口替换(cuda → npu):将所有 device="cuda" 替换为 device="npu",并将 torch.cuda.CUDAGraph()torch.cuda.Stream()torch.cuda.default_generatorstorch.cuda.stream()torch.cuda.current_stream() 等 CUDA API 对应替换为 torch.npu.NPUGraph()torch.npu.Stream()torch.npu.default_generatorstorch.npu.stream()torch.npu.current_stream() 等 NPU API。
  • 导入模块与兼容性处理:新增 import torch_npufrom torch_npu.contrib import transfer_to_npu,并通过 monkey-patch 方式处理 torch.cuda.get_device_capability 返回 None 时的兼容性问题(将其替换为返回 (0, 0) 的 lambda)。
  • 测试条件与装饰器调整:将跳过条件从检查 TEST_CUDA_GRAPH 改为 not torch.npu.is_available(),并新增 @skipCUDAMemoryLeakCheckIf(True)@skipCUDANonDefaultStreamIf(True) 装饰器,确保测试仅在 NPU 可用时执行。
  • NPU Generator 初始化:在获取 torch.npu.default_generators[0] 之前新增 torch.rand(1, device="npu") 调用,确保 NPU 默认随机数生成器在使用前已被正确初始化。
likedislike
不准确?
atomgit-bot
atomgit-bot
7月30日 评论:

代码审查

经过仔细审查整个 patch 文件,我对所有修改行逐一进行了分析:

  1. import torch_npufrom torch_npu.contrib import transfer_to_npu(第 9-10 行):transfer_to_npu 是一个具有 import 时副作用的模块,会 patch torch.cuda 系列函数以重定向到 NPU——这是 Ascend NPU 适配的标准模式,并非无用导入。

  2. get_device_capability 的 monkey-patch(第 15-16 行):在无 CUDA 设备时作为安全兜底,防止文件中其他 CUDA 相关代码因 get_device_capability() 返回 None 而崩溃。由于 transfer_to_npu 已在此前被导入并 patch 了该函数,此 monkey-patch 仅在极端情况下触发,属防御性编程。

  3. @skipCUDAMemoryLeakCheckIf(True)@skipCUDANonDefaultStreamIf(True)(第 24-25 行):这两个装饰器在 NPU 测试中广泛使用(test/test_npu.py 等多处均有相同模式),用于跳过 NPU 上可能产生的误报 leak 检查和非默认流检查。

  4. skip 条件(第 28 行):从 TEST_CUDA_GRAPH 改为 not torch.npu.is_available(),正确适配 NPU 可用性判断。

  5. 所有 device="cuda"device="npu"torch.cuda.*torch.npu.* 的替换:NPU API 完全镜像 CUDA API,NPUGraphStreamdefault_generatorsstream()current_stream() 等均存在于 torch_npu 中,经核实均有对应实现,替换正确。

  6. 新增 torch.rand(1, device="npu")(第 69 行):在访问 default_generators[0] 前初始化 NPU 上下文,是必要的初始化步骤。


审查结论

本次审查共发现 0 个问题。该 patch 是对上游 test/test_cuda.py::TestCuda.test_graphsafe_set_get_rng_state 用例的 NPU 适配,所有修改均遵循仓库中已有的 NPU 适配模式(与 test_futures.py.patchtest/test_npu.py 中的模式一致),代码变更正确、安全。

已审查文件:

  • test_upstream/test/test_cuda.py.patch — 无问题

整体风险评估:低风险。 该 patch 是标准的设备适配变更,不涉及业务逻辑修改,仅将 CUDA 专属 API 替换为 NPU 等价 API,且适配模式与仓库现有实践一致。

⚠️ 已识别出整体风险,但无法提取行内评论,请参考整体评估。

likedislike
不准确?
ascend-robotascend-robot成员
7月30日 添加了label:ascend-cla/yes
此处折叠了54条消息 查看更多
li_jing_hw成员
25 天前 评论:

/approve

likedislike
ascend-robotascend-robot成员
25 天前 添加了label:approvedlgtm
ascend-robotascend-robot成员
25 天前 删除了label:ci-pipeline-passed
ascend-robotascend-robot成员
25 天前 合入了pull request
ascend-robot
ascend-robot成员
25 天前 评论:
流水线 pytorch_gitcode_PR_multiVersion#13940 [ commitID:641cc0a0 ] 已完成
likedislike