已合并
test(futures): add test case patch for futures #33279
dinglaiping创建于 4月8日
test(futures): add test case patch for futures #33279
已合并
dinglaiping创建于 4月8日
已删除 :add-testcasepatch-for-futures-2.10.0合入到Ascend/pytorchv2.10.0
dinglaiping成员
4月8日

【合入来源】

https://gitcode.com/Ascend/pytorch/issues/1670
请勿携带内部流程信息(需求链接、问题单、内部issue等)

[ ] 问题单

【修改方案】

请描述修改内容的具体实现,涉及哪些组件之间进行交互,可以用1、2、3、...进行罗列
如果是需求或者重构类的PR,需要补充详细设计文档(说明上下游组件关系、时序图、类图、DFX能力等内容)

一、API功能

Future.value():该方法用于获取 Future 对象的结果值。当 Future 已经完成时,它会直接返回设置的结果;但如果 Future 是通过 set_exception 标记为完成的,调用 value() 会抛出对应的异常。这个 API 和 wait() 的区别在于它不会阻塞等待,只适用于已经完成的 Future。
Future.set_result(value):用于将 Future 标记为完成状态并设置结果值。一旦调用,Future 立即进入完成状态,所有等待该 Future 的线程都会被唤醒并收到这个结果。每个 Future 只能被标记完成一次,重复调用会触发 RuntimeError。
Future.set_exception(err):将 Future 标记为完成状态但携带一个异常。调用后 Future 被视为已完成,但任何尝试通过 wait() 或 value() 获取结果的调用都会抛出这个设置的异常。这在异步错误传播中非常有用。
Future.wait():阻塞当前线程直到 Future 完成,然后返回结果值。如果 Future 是通过 set_exception 完成的,wait() 会抛出设置的异常。这是最基础的获取 Future 结果的方式。
Future.done():返回一个布尔值指示 Future 是否已经完成。如果 Future 已经被 set_result 或 set_exception 标记过,返回 True;否则返回 False。可以用于非阻塞地检查状态。
Future.then(cb):注册一个回调函数,当 Future 完成时自动执行。回调函数接收完成的 Future 作为参数,可以调用 wait() 获取结果进行处理。then 返回一个新的 Future 对象,代表回调执行的结果,支持链式调用形成 Future 链条。如果回调本身抛出异常,新 Future 会携带这个异常。
Future.add_done_callback(cb):添加一个完成时的回调函数,与 then 不同,它不返回新的 Future,回调的错误会被静默忽略(仅记录日志)。多个回调按添加顺序执行,适合用于副作用操作(如状态标记、清理工作)。
torch.futures.collect_all(futs):接受一个 Future 列表,返回一个新的 Future,该 Future 在所有输入 Future 完成时完成,其结果是一个包含所有原始 Future 的列表,每个都可以通过 wait() 获取各自的结果。
torch.futures.wait_all(futs):接受一个 Future 列表,阻塞等待所有 Future 完成,直接返回一个包含所有结果的列表。如果任何一个 Future 携带异常,wait_all 会抛出 RuntimeError 包裹的异常信息。

二、测试用例完备性说明

PyTorch 社区原生测试用例(test_futures.py)对上述 9 个 API 实现全维度场景覆盖,核心验证内容如下:
Future.set_exception 的验证:test_set_exception 测试用例创建了 Future 并调用 set_exception 设置 ValueError,然后验证 wait() 会抛出带有"Intentional"消息的 ValueError,同时也验证 value() 同样会抛出该异常。test_set_exception_multithreading 进一步在一个线程等待的同时,另一个线程设置异常,验证跨线程的错误传播。
多线程场景验证:test_set_exception_multithreading 使用 threading.Thread 在一个线程中调用 wait(),主线程中设置异常,验证异常能正确传播到等待线程。test_wait_multi_thread 则测试了在后台线程延迟设置结果,主线程调用 wait() 能正确阻塞并获取结果。
Future.done() 的验证:test_done 测试创建一个 Future,初始状态验证 done() 返回 False,调用 set_result 后验证 done() 返回 True。test_done_exception 则验证通过 then 链接触发异常的 Future,其 done() 状态也为 True,但 wait() 会抛出异常。
单次完成限制验证:test_mark_future_twice 专门测试多次调用 set_result 会触发 RuntimeError,提示"Future can only be marked completed once"。
序列化限制验证:test_pickle_future 验证 Future 对象不能被 pickle 序列化,尝试保存时会抛出 RuntimeError。
then 方法的验证:test_then 测试基本回调,验证回调能正确获取结果并返回新 Future。test_chained_then 创建了 20 个 then 链,每个回调给结果加 1,验证链式调用的计算顺序正确。test_then_error 系列包括三个子测试:test_then_wrong_arg 验证回调参数类型错误,test_then_no_arg 验证回调不接受参数的错误,test_then_raise 验证回调内部抛出异常的情况,都验证错误正确传播到新 Future。
add_done_callback 的验证:test_add_done_callback_simple 验证回调在 set_result 后被调用,并能正确获取结果。test_add_done_callback_maintains_callback_order 添加两个回调修改同一变量,验证执行顺序与添加顺序一致。test_add_done_callback_error_is_ignored 验证回调中的 ValueError 不会传播,只是被记录。test_add_done_callback_no_arg_error_is_ignored 验证参数不匹配的错误同样被忽略。
then 与 add_done_callback 交互验证:test_interleaving_then_and_add_done_callback_maintains_callback_order 交替添加 then 和 add_done_callback,验证回调执行顺序保持插入顺序。test_interleaving_then_and_add_done_callback_propagates_error 验证 then 的错误会传播到结果 Future,而 add_done_callback 的错误被忽略。
collect_all 的验证:test_collect_all 创建两个 Future,在一个后台线程中延迟设置第一个 Future 的结果,主线程立即设置第二个,然后验证 collect_all 返回的 Future 能正确收集两个结果,且等待时间由最慢的决定。
wait_all 的验证:test_wait_all(Windows 除外)先测试两个已完成的 Future,验证返回列表包含正确结果。然后测试包含异常的链条,验证 wait_all 会抛出 RuntimeError 包含"Expected error"消息。
空值处理验证:test_wait_none 验证向 torch.jit.wait、torch.futures.wait_all 和 torch.futures.collect_all 传递 None 时,都会抛出 RuntimeError 提示"Future can't be None"。

三、npu适配
3.1 api适配
torch.futures 模块 API 底层无硬件相关逻辑,所有异步结果管理、回调触发、异常传播等核心功能均为框架层通用实现,torch_npu 已完成 NPU 设备的底层适配,无需修改 API 源码,仅通过测试用例的设备相关调整即可实现 NPU 兼容。

3.2 测试用例适配
• 基础环境适配:新增 import torch_npu,让 PyTorch 框架识别 NPU 设备,支持 NPU 张量的创建与操作;
• 张量设备调整:将原测试用例中默认的 CPU 张量(torch.ones(2,2))修改为 NPU 张量(torch.ones(2,2).npu()),确保异步计算的结果载体(张量)运行在 NPU 上,贴合 NPU 场景使用需求。

【资料变更】

不涉及

【接口变更】

不涉及

【功能验证】

说明测试场景,测试方法。如果本次测试方式与常规单元测试不同,请详细说明您的测试步骤
新增/变更内容是否已新增/适配UT测试用例看护,并补充测试自验证截图

2.6版本

[root@hostname-fqv42 ~]# docker exec -it test26 bash
root@hostname-fqv42:/home# python /root/torchnpuapi/test_futures_gai.py
Fail to import hypothesis in common_utils, tests are not derandomized
[E226 11:44:33.636064398 pybind_utils.h:209] Got the following error when running the callback: ValueError: Expected error

At:
  /root/torchnpuapi/test_futures_gai.py(243): raise_value_error
  /usr/local/python/lib/python3.11/site-packages/torch/futures/__init__.py(245): set_result
  /root/torchnpuapi/test_futures_gai.py(236): _test_add_done_callback_error_ignored
  /root/torchnpuapi/test_futures_gai.py(245): test_add_done_callback_error_is_ignored
  /usr/local/python/lib/python3.11/site-packages/torch/testing/_internal/common_utils.py(3108): wrapper
  /usr/local/python/lib/python3.11/unittest/case.py(579): _callTestMethod
  /usr/local/python/lib/python3.11/unittest/case.py(623): run
  /usr/local/python/lib/python3.11/site-packages/torch/testing/_internal/common_utils.py(3215): _run_custom
  /usr/local/python/lib/python3.11/site-packages/torch/testing/_internal/common_utils.py(3243): run
  /usr/local/python/lib/python3.11/unittest/case.py(678): __call__
  /usr/local/python/lib/python3.11/unittest/suite.py(122): run
  /usr/local/python/lib/python3.11/unittest/suite.py(84): __call__
  /usr/local/python/lib/python3.11/unittest/suite.py(122): run
  /usr/local/python/lib/python3.11/unittest/suite.py(84): __call__
  /usr/local/python/lib/python3.11/unittest/runner.py(217): run
  /usr/local/python/lib/python3.11/unittest/main.py(274): runTests
  /usr/local/python/lib/python3.11/unittest/main.py(102): __init__
  /usr/local/python/lib/python3.11/site-packages/torch/testing/_internal/common_utils.py(1353): run_tests
  /root/torchnpuapi/test_futures_gai.py(347): <module>

..[E226 11:44:38.999984481 pybind_utils.h:209] Got the following error when running the callback: TypeError: TestFuture.test_add_done_callback_no_arg_error_is_ignored.<locals>.no_arg() takes 0 positional arguments but 1 was given
.......[E226 11:44:38.132336345 pybind_utils.h:209] Got the following error when running the callback: ValueError: Expected error

At:
  /root/torchnpuapi/test_futures_gai.py(287): raise_value_error
  /usr/local/python/lib/python3.11/site-packages/torch/futures/__init__.py(245): set_result
  /root/torchnpuapi/test_futures_gai.py(292): test_interleaving_then_and_add_done_callback_propagates_error
  /usr/local/python/lib/python3.11/site-packages/torch/testing/_internal/common_utils.py(3108): wrapper
  /usr/local/python/lib/python3.11/unittest/case.py(579): _callTestMethod
  /usr/local/python/lib/python3.11/unittest/case.py(623): run
  /usr/local/python/lib/python3.11/site-packages/torch/testing/_internal/common_utils.py(3215): _run_custom
  /usr/local/python/lib/python3.11/site-packages/torch/testing/_internal/common_utils.py(3243): run
  /usr/local/python/lib/python3.11/unittest/case.py(678): __call__
  /usr/local/python/lib/python3.11/unittest/suite.py(122): run
  /usr/local/python/lib/python3.11/unittest/suite.py(84): __call__
  /usr/local/python/lib/python3.11/unittest/suite.py(122): run
  /usr/local/python/lib/python3.11/unittest/suite.py(84): __call__
  /usr/local/python/lib/python3.11/unittest/runner.py(217): run
  /usr/local/python/lib/python3.11/unittest/main.py(274): runTests
  /usr/local/python/lib/python3.11/unittest/main.py(102): __init__
  /usr/local/python/lib/python3.11/site-packages/torch/testing/_internal/common_utils.py(1353): run_tests
  /root/torchnpuapi/test_futures_gai.py(347): <module>

..........[1, 2]
...
----------------------------------------------------------------------
Ran 22 tests in 6.038s

OK
root@hostname-fqv42:/home# 

结果说明

执行test_futures.py测试用例后,终端输出包含若干[E226]级别的错误日志,但最终显示Ran 22 tests in 6.038s且OK,表明所有测试用例执行通过,日志中出现的报错属于测试用例设计的预期行为,非代码 Bug 或 NPU 适配问题。

【CheckList】

PR提交人对以下CheckList自检项进行全量自检,自检通过或不涉及,均修改 [ ] 为 [x]

likedislike
Pull Request已成功合入, 合并人@ascend-robot
(感谢 dinglaiping 的贡献)
Ddinglaiping成员
4月8日 创建了 pull request,commit f068e40c
Ddinglaiping成员
4月8日 关联了issue:[Usage]: torch-npu的test_futures.py patch继承自pytorch社区,其中from torch_npu.contrib import transfer_to_npu并不会把CPU张量运行到NPU上,因此NPU适配不完整;其他版本则没有提供patch
ascend-robot
ascend-robot成员
4月8日 评论:

Thanks for your pull-request.
The full list of commands accepted by me can be found at here
You can get sig-info at here


PR Approval Progress

Congratulations! All modules have met the lgtm and approve requirements.

Module Approval Details

module lgtm status approve status
repo-Ascend/pytorch 李伟, renyujin (2/2) 李伟 (1/1)

💡 Tip:

  • Committer can comment /approve or /lgtm
  • Commenting /approve implies both code review (lgtm) and intent to merge (approve)

CLA Signature Pass

dinglaiping, thanks for your pull request. All authors of the commits have signed the CLA. 👍

likedislike
ascend-robotascend-robot成员
4月8日 添加了label:ascend-cla/yes
dinglaiping成员
4月8日 评论:

compile

likedislike
ascend-robotascend-robot成员
4月8日 添加了label:ci-pipeline-running
ascend-robotascend-robot成员
4月8日 删除了label:ci-pipeline-running
ascend-robotascend-robot成员
4月8日 添加了label:ci-pipeline-passed
ascend-robot
ascend-robot成员
4月8日 评论:
流水线 PR-pipeline_pytorch#14594 已完成
阶段 任务名 状态 详情
编译构建 Build_X86 >>>
Build_ARM >>>
Build_LibTorch_x86 >>>
Build_X86_torchair 🛑 >>>
Build_ARM_torchair 🛑 >>>
Build_ARM_inductor 🛑 >>>
恶意代码检查 Antipoison >>>
编码安全与规范检查 CodeCheck >>>
check_error >>>
开源片段检查 SCA >>>
开发者测试 UT_X86_Part_01 🛑 >>>
UT_X86_Part_02 🛑 >>>
UT_ARM_A3_Part_01 🛑 >>>
UT_ARM_A3_Part_02 🛑 >>>
UT_DIST_X86_Part_01 🛑 >>>
UT_DIST_X86_Part_02 🛑 >>>
UT_DIST_X86_Part_03 🛑 >>>
UT_DIST_X86_Part_04 🛑 >>>
UT_inductor_Part_01 🛑 >>>
UT_inductor_Part_02 🛑 >>>
UT_inductor_Part_03 🛑 >>>
UT_inductor_Part_04 🛑 >>>
UT_ARM_A2_Part_01 >>>
UT_ARM_A2_Part_02 >>>
流水线 PR-pipeline_pytorch >>>
likedislike
liwei386成员
4月8日 评论:

/approve

likedislike
ascend-robotascend-robot成员
4月8日 添加了label:approved
renyujin成员
4月9日 评论:

/lgtm

likedislike
ascend-robotascend-robot成员
4月9日 添加了label:lgtm
ascend-robot
ascend-robot成员
4月9日 评论:

Review Guide

This pull-request passes review.
Committers who wrote a comment of /approve are: 李伟.
Reviewers who wrote a comment of /lgtm are: renyujin, 李伟.

likedislike
ascend-robotascend-robot成员
4月9日 合入了pull request