| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
test(utils): adapt checkpoint and dataloader upstream tests on NPU Co-authored-by: Jinfan Liu<1300083451@qq.com> # message auto-generated for no-merge-commit merge: !36416 merge test-utils-checkpoint-data-npu-v2.11.0 into v2.11.0 test(utils): adapt checkpoint and dataloader upstream tests on NPU Created-by: JfanLiu Commit-by: Jinfan Liu Merged-by: ascend-robot Description: <!-- PR描述模板更新日期:20260203 --> # 【合入来源】 > <font color="red">**https://gitcode.com/Ascend/pytorch/issues/2026**</font> > <font color="red">**https://gitcode.com/Ascend/pytorch/issues/2027**</font> > <font color="red">**请勿携带内部流程信息(需求链接、问题单、内部issue等)**</font> [x] issue/工单 # 【修改方案】 一、API功能说明 本 PR 覆盖两组 torch.utils API 的 NPU 测试适配: 1. torch.utils.checkpoint 相关 API - torch.utils.checkpoint.CheckpointPolicy - torch.utils.checkpoint.create_selective_checkpoint_contexts - torch.utils.checkpoint.SelectiveCheckpointContext - torch.utils.checkpoint.detach_variable - torch.utils.checkpoint.set_checkpoint_debug_enabled 这些 API 用于 activation checkpoint 的 selective checkpoint 策略控制、forward/recompute 上下文创建、reentrant checkpoint 输入 detach 处理,以及 checkpoint debug 全局开关。 2. torch.utils.data DataLoader / collate / worker 相关 API - torch.utils.data.DataLoader - torch.utils.data._utils.collate.collate - torch.utils.data.dataloader._BaseDataLoaderIter - torch.utils.data.dataloader._SingleProcessDataLoaderIter - torch.utils.data.dataloader._MultiProcessingDataLoaderIter - torch.utils.data.dataloader._DatasetKind.create_fetcher - torch.utils.data.dataloader._InfiniteConstantSampler - torch.utils.data._utils.worker.WorkerInfo - torch.utils.data._utils.worker.ManagerWatchdog - torch.utils.data._utils.worker._IterableDatasetStopIteration - torch.utils.data._utils.worker._ResumeIteration - torch.utils.data._utils.signal_handling._set_worker_signal_handlers - torch.utils.data._utils.signal_handling._remove_worker_pids 这些 API 覆盖 DataLoader 入口、单进程/多进程 iterator、Dataset fetcher 创建、IterableDataset 无限采样、batch collate、worker 信息、worker 存活检查、persistent worker 恢复、IterableDataset worker 结束通知以及 worker 信号处理和 pid 清理。 二、测试用例完备性说明 ``` PyTorch 官方社区 test/test_autograd.py 和 test/test_dataloader.py 已有可复用用例。本 PR 不新增 torch-npu 自定义测试文件,只对官方用例中目标 API 相关 Tensor 做 NPU 设备适配,提交 test_upstream patch。 checkpoint API 覆盖情况: 1. torch.utils.checkpoint.set_checkpoint_debug_enabled 覆盖类型:直接覆盖,强覆盖。 覆盖用例:TestAutograd.test_checkpoint_detects_non_determinism。 覆盖路径:测试代码显式执行 with torch.utils.checkpoint.set_checkpoint_debug_enabled(True/False),再调用 checkpoint(..., debug=False/True),验证全局 debug 上下文能覆盖 checkpoint 入参 debug,并验证非确定性重计算错误信息是否切换到 debug trace 分支。 NPU 状态:参与 checkpoint forward/recompute 的输入 a 已迁移到 device="npu",非确定性重计算检测在 NPU Tensor 上执行。 2. torch.utils.checkpoint.create_selective_checkpoint_contexts 覆盖类型:直接覆盖,强覆盖。 覆盖用例:TestSelectiveActivationCheckpoint.test_bad_inputs、test_output_already_has_autograd_meta、test_subclass_dispatching_sizes、test_policy_with_state、test_storage_lifetime、test_version_counter、test_function_with_more_than_one_output、test_function_with_non_tensor_output、test_can_only_trigger_recompute_once 等。 覆盖路径:测试代码通过 create_selective_checkpoint_contexts 构造 context_fn,并传入 checkpoint(..., use_reentrant=False, context_fn=context_fn),覆盖 OpOverload list、自定义 policy function、状态型 policy、allow_cache_entry_mutation、非法 op list、非法 OpOverloadPacket 和非法入参类型。 NPU 状态:selective checkpoint 相关用例中的 x / y 等 Tensor 已迁移到 device="npu",policy 触发的 forward、cache、recompute、backward 路径在 NPU Tensor 上执行。 3. torch.utils.checkpoint.CheckpointPolicy 覆盖类型:直接覆盖,强覆盖。 覆盖用例:TestSelectiveActivationCheckpoint 中多个 policy_fn 返回 CheckpointPolicy.MUST_SAVE / CheckpointPolicy.PREFER_RECOMPUTE 等枚举值。 覆盖路径:policy function 返回 CheckpointPolicy 后,checkpoint 内部根据策略决定保存 forward 输出或在 backward 阶段重计算,覆盖保存、重计算、缓存 mutation 检测、版本计数、多输出、非 Tensor 输出和重复 backward 错误路径。 NPU 状态:policy 作用的 aten op 输入/输出来自 NPU Tensor,缓存和重计算路径均在 NPU Tensor 上验证。 4. torch.utils.checkpoint.SelectiveCheckpointContext 覆盖类型:调用链覆盖,当前为弱覆盖。 覆盖用例:TestSelectiveActivationCheckpoint.test_policy_with_state 以及其他 selective checkpoint 用例。 覆盖路径:create_selective_checkpoint_contexts 内部创建 SelectiveCheckpointContext,并在 _CachingTorchDispatchMode / _CachedTorchDispatchMode 中传入 policy function;test_policy_with_state 读取 ctx.is_recompute,验证 forward 与 recompute 阶段上下文状态切换。 当前不足:测试没有直接实例化 SelectiveCheckpointContext,也没有对 context 对象类型进行显式断言;覆盖重点在 checkpoint 调用链中 ctx.is_recompute 的使用。 NPU 状态:触发 ctx 的 policy 路径运行在 NPU Tensor 的 selective checkpoint 过程中。 后续补用例:后续拆分补充 torch-npu test 目录用例,捕获 policy_fn 收到的 ctx,显式断言 isinstance(ctx, torch.utils.checkpoint.SelectiveCheckpointContext)、ctx.is_recompute 在 forward/recompute 阶段分别出现,并在支持 op_output 的版本中验证 ctx.op_output 与 NPU Tensor 输出的关系。 5. torch.utils.checkpoint.detach_variable 覆盖类型:调用链覆盖,当前为弱覆盖。 覆盖用例:TestAutograd.test_checkpoint_valid_reset_on_error。 覆盖路径:测试执行 checkpoint(torch.exp, a, use_reentrant=True),进入 reentrant checkpoint 的 CheckpointFunction.forward,源码中调用 detach_variable(tuple(inputs)) 对输入 Tensor detach 并保持 requires_grad 状态;用例同时验证异常后 checkpoint 状态恢复以及后续 backward 正常执行。 当前不足:测试没有直接调用 torch.utils.checkpoint.detach_variable,也没有逐项断言 detach 后 Tensor 的 requires_grad、grad_fn、device 和非 Tensor passthrough 行为。 NPU 状态:输入 a 已迁移到 device="npu",detach_variable 处理的是 NPU Tensor。 后续补用例:后续拆分补充 torch-npu test 目录用例,直接调用 detach_variable((x, y, marker)),断言返回 Tensor 保持 NPU device、requires_grad 与原输入一致、grad_fn 被断开、非 Tensor 对象保持透传,并覆盖非 tuple 输入的 RuntimeError 分支。 DataLoader / collate / worker API 覆盖情况: 1. torch.utils.data.DataLoader 覆盖类型:直接覆盖,强覆盖。 覆盖用例:TestDataLoader.test_sequential_batch、TestDataLoader.test_sequential_nonbatch、TestDataLoader.test_seqential_batch_workers、TestDataLoader.test_iterable_style_dataset、TestDataLoaderPersistentWorkers.test_dataset_not_reset 等。 覆盖路径:测试直接构造 DataLoader,覆盖 batch_size=None、batch_size>0、num_workers=0、num_workers>0、IterableDataset、persistent_workers 等典型入口参数组合。 NPU 状态:test_sequential_batch / test_sequential_nonbatch 中 TensorDataset 的 data / labels 已迁移到 NPU,验证 DataLoader 返回 NPU Tensor payload;worker 控制流用例主要验证多进程状态机,不强行把 worker 子进程内部数据迁移为 NPU Tensor。 2. torch.utils.data._utils.collate.collate 覆盖类型:函数体覆盖,强覆盖;NPU Tensor 分支已覆盖。 覆盖用例:TestDataLoader.test_default_collate_dtype、test_default_collate_mapping_keep_type、test_default_collate_sequence_keep_type、test_default_collate_bad_numpy_types、test_default_collate_shared_tensor。 覆盖路径:用例调用 dataloader.default_collate,default_collate 内部进入 torch.utils.data._utils.collate.collate,覆盖 Tensor dtype、mapping 类型保持、sequence 类型保持、非法 numpy string/object 异常、shared tensor 分支。 NPU 状态:test_default_collate_dtype 中补充 NPU Tensor batch,验证 collate 后输出仍位于 NPU;mapping/sequence/异常/shared-memory 分支保持官方原有 CPU/控制语义。 3. torch.utils.data.dataloader._BaseDataLoaderIter 覆盖类型:调用链覆盖,强覆盖。 覆盖用例:所有通过 iter(DataLoader) / for batch in DataLoader 执行的目标用例。 覆盖路径:DataLoader.__iter__ 创建具体 iterator 后,执行 _BaseDataLoaderIter.__init__、__iter__、__next__、_next_index、_num_yielded 更新、IterableDataset len warning 相关公共流程。 NPU 状态:单进程顺序迭代用例中该公共 next 流程处理 NPU Tensor payload。 4. torch.utils.data.dataloader._SingleProcessDataLoaderIter 覆盖类型:调用链覆盖,强覆盖。 覆盖用例:TestDataLoader.test_sequential_batch、TestDataLoader.test_sequential_nonbatch。 覆盖路径:num_workers=0 时 DataLoader 创建 _SingleProcessDataLoaderIter,执行 _DatasetKind.create_fetcher、_next_index、fetch、collate 和可选 pin_memory 分支判断。 NPU 状态:本 PR 将 TensorDataset 的 data / labels 迁移到 NPU,因此 _SingleProcessDataLoaderIter 读取和返回的是 NPU Tensor payload。 5. torch.utils.data.dataloader._MultiProcessingDataLoaderIter 覆盖类型:调用链覆盖,当前为弱覆盖。 覆盖用例:TestDataLoader.test_seqential_batch_workers、TestDataLoader.test_iterable_style_dataset、TestDataLoaderPersistentWorkers.test_dataset_not_reset。 覆盖路径:num_workers>0 时创建 _MultiProcessingDataLoaderIter,覆盖 worker 启动、index_queue、worker_result_queue、prefetch、shutdown、persistent worker 复用等控制流。 当前不足:当前用例验证的是多进程 DataLoader 控制面,未把 worker 子进程返回的数据强制改成 NPU Tensor;因此不能把它表述为 NPU Tensor payload 下的完整多进程 IPC 覆盖。 NPU 状态:用例在 NPU 适配环境下运行;多进程控制 API 本身无 Tensor 计算语义。 后续补用例:后续拆分补充更小的 torch-npu test 目录用例,围绕 num_workers=1、极小数据集、明确断言 iterator 类型、worker 生命周期和结果正确性;如确需覆盖 NPU Tensor 跨进程返回,则单独设计 NPU IPC 前置条件和资源约束,避免把 DataLoader 控制面问题与 NPU IPC 问题混在同一个验证点。 6. torch.utils.data.dataloader._DatasetKind.create_fetcher 覆盖类型:调用链覆盖,强覆盖。 覆盖用例:TestDataLoader.test_sequential_batch、test_sequential_nonbatch、test_iterable_style_dataset、test_seqential_batch_workers。 覆盖路径:_SingleProcessDataLoaderIter.__init__ 和 worker_loop 均通过 _DatasetKind.create_fetcher 创建 MapDatasetFetcher 或 IterableDatasetFetcher;目标用例同时覆盖 map-style TensorDataset 和 IterableDataset。 NPU 状态:map-style 单进程 fetcher 处理 NPU TensorDataset;IterableDataset/multi-worker 分支验证 fetcher 控制逻辑。 7. torch.utils.data.dataloader._InfiniteConstantSampler 覆盖类型:调用链覆盖,当前为弱覆盖。 覆盖用例:TestDataLoader.test_iterable_style_dataset。 覆盖路径:IterableDataset 下 DataLoader 使用 _InfiniteConstantSampler 生成无限 None 索引,由 IterableDataset 自身控制 StopIteration。 当前不足:用例通过 IterableDataset 行为间接证明 sampler 工作,没有直接实例化 _InfiniteConstantSampler 并断言连续 yield None。 NPU 状态:该 API 不处理 Tensor,仅提供采样控制流。 后续补用例:后续补充 torch-npu test 目录小用例,直接 iter(_InfiniteConstantSampler()),断言连续返回 None,并结合 IterableDataset DataLoader 验证不会提前终止。 8. torch.utils.data._utils.worker.WorkerInfo 覆盖类型:直接覆盖,强覆盖。 覆盖用例:TestDataLoader.test_get_worker_info。 覆盖路径:子进程用例验证主进程 get_worker_info() 返回 None;worker_init_fn 和 worker dataset 内部 get_worker_info() 返回 WorkerInfo,并校验 id、num_workers、seed、dataset 字段和只读行为。 NPU 状态:WorkerInfo 是 worker 元信息对象,不处理 Tensor;用例在 NPU 适配环境下执行。 9. torch.utils.data._utils.worker.ManagerWatchdog 覆盖类型:调用链覆盖,当前为弱覆盖。 覆盖用例:TestDataLoader.test_seqential_batch_workers、TestDataLoader.test_iterable_style_dataset、TestDataLoaderPersistentWorkers.test_dataset_not_reset。 覆盖路径:worker_loop 中创建 ManagerWatchdog,并在 while watchdog.is_alive() 循环中驱动 worker 持续读取 index_queue。 当前不足:用例覆盖正常 worker loop,但没有直接断言 ManagerWatchdog.is_alive(),也没有模拟父进程死亡场景。 NPU 状态:该 API 是进程存活检查逻辑,不处理 Tensor。 后续补用例:后续补充 torch-npu test 目录小用例,直接构造 ManagerWatchdog 并断言正常父进程场景 is_alive() 为 True;如需要父进程死亡场景,使用独立 subprocess 隔离验证。 10. torch.utils.data._utils.worker._IterableDatasetStopIteration 覆盖类型:调用链覆盖,当前为弱覆盖。 覆盖用例:TestDataLoader.test_iterable_style_dataset。 覆盖路径:IterableDataset 多 worker 某个 worker 先耗尽时,worker_loop 捕获 StopIteration 并向主进程发送 _IterableDatasetStopIteration(worker_id),主进程据此停 See merge request: Ascend/pytorch!36416 | 2 个月前 | |
test(futures): add test case patch for futures Co-authored-by: dinglaiping<1016581171@qq.com> # message auto-generated for no-merge-commit merge: !33280 merge add-testcasepatch-for-futures-2.11.0 into v2.11.0 test(futures): add test case patch for futures Created-by: dinglaiping Commit-by: dinglaiping Merged-by: ascend-robot Description: <!-- PR描述模板更新日期:20260203 --> # 【合入来源】 > <font color="red">**https://gitcode.com/Ascend/pytorch/issues/1670**</font>\ > <font color="red">**请勿携带内部流程信息(需求链接、问题单、内部issue等)**</font> [ ] 问题单 # 【修改方案】 > 请描述修改内容的具体实现,涉及哪些组件之间进行交互,可以用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] - [x] 代码注释完备,正确记录错误日志 - [x] 代码实现进行了返回值、空指针等校验 - [x] PR标题正确使用类型标签,如:feat、fix、refactor、docs、test等 - [x] PR持续集成流水线(CI)执行通过,代码检查无异常 See merge request: Ascend/pytorch!33280 | 4 个月前 | |
test(futures): add test case patch for futures Co-authored-by: dinglaiping<1016581171@qq.com> # message auto-generated for no-merge-commit merge: !33280 merge add-testcasepatch-for-futures-2.11.0 into v2.11.0 test(futures): add test case patch for futures Created-by: dinglaiping Commit-by: dinglaiping Merged-by: ascend-robot Description: <!-- PR描述模板更新日期:20260203 --> # 【合入来源】 > <font color="red">**https://gitcode.com/Ascend/pytorch/issues/1670**</font>\ > <font color="red">**请勿携带内部流程信息(需求链接、问题单、内部issue等)**</font> [ ] 问题单 # 【修改方案】 > 请描述修改内容的具体实现,涉及哪些组件之间进行交互,可以用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] - [x] 代码注释完备,正确记录错误日志 - [x] 代码实现进行了返回值、空指针等校验 - [x] PR标题正确使用类型标签,如:feat、fix、refactor、docs、test等 - [x] PR持续集成流水线(CI)执行通过,代码检查无异常 See merge request: Ascend/pytorch!33280 | 4 个月前 |
Patch 批量应用脚本使用说明
目录结构
- 核心仓库地址
- 官方 PyTorch 仓库(v2.11.0 版本):https://github.com/pytorch/pytorch/tree/v2.11.0,需拉取该仓库并切换至 tags/v2.11.0 标签。
- 补丁仓库(Ascend/pytorch):https://gitcode.com/Ascend/pytorch,仅需提取该仓库中的 patch 目录。
- 核心目录结构
pytorch/ # PyTorch 源码根目录
├─ ...(其他 PyTorch 原生文件/目录)
└─ test_upstream/ # 补丁目录
├─ apply_patches.sh # 批量应用脚本
├─ *.patch # 补丁文件(支持子目录嵌套)
├─ ...(其他补丁子目录)
环境要求
仅需安装git即可
使用方法
-
将本仓库的test_upstream文件夹整体复制到本地的PyTorch官方仓库中
-
运行脚本文件
cd test_upstream
./apply_patches.sh
脚本执行说明:自动定位 PyTorch 根目录,递归扫描所有 .patch文件,按文件名排序强制应用,冲突部分生成 .rej 文件.
注意事项
- 所有补丁仅适配 PyTorch tags/v2.11.0,其他版本将导致应用失败,务必提前校验版本。
- test_upstream 目录需整体复制至 PyTorch 根目录。
- 生成 .rej 冲突文件时,需手动解决冲突后重新执行脚本。