| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
[test][v2.12.0] add NPU validation cases for torch._functorch APIs (issues #2684 #2685 #2687 #2688) Co-authored-by: ggg_0963<1873823162@qq.com> # message auto-generated for no-merge-commit merge: !41386 merge test-functorch-aot-config-vmap-v2.12.0 into v2.12.0 [test][v2.12.0] add NPU validation cases for torch._functorch APIs (issues #2684 #2685 #2687 #2688) Created-by: ggg_0963 Commit-by: ggg_0963 Merged-by: ascend-robot Description: # 【合入来源】 > 4 个 issue 出自「7月社区任务一期 API 一致性」(任务编号 #60 起,见 [#2683](https://gitcode.com/Ascend/pytorch/issues/2683))。 > > - 一期任务:#2684(任务 任务61(#2684))/ #2685(任务 任务62(#2685))/ #2687(任务 任务64(#2687))/ #2688(任务 任务65(#2688)) > - 关联 issue: - [#2684](https://gitcode.com/Ascend/pytorch/issues/2684) — torch._functorch.aot_autograd.aot_compile_joint_with_descriptors(一期任务 任务61(#2684)) - [#2685](https://gitcode.com/Ascend/pytorch/issues/2685) — torch._functorch.aot_autograd.aot_export_joint_with_descriptors(一期任务 任务62(#2685)) - [#2687](https://gitcode.com/Ascend/pytorch/issues/2687) — torch._functorch.config.patch(一期任务 任务64(#2687)) - [#2688](https://gitcode.com/Ascend/pytorch/issues/2688) — torch._functorch.vmap._add_batch_dim(一期任务 任务65(#2688)) # 【修改方案】 本 PR 覆盖 4 个 torch._functorch.* 一期 API 的 NPU 一致性测试补齐;2 个 任务64(#2687)/任务65(#2688) 新增独立测试文件,2 个 任务61(#2684)/任务62(#2685) 在 test_upstream/ 留上游适配 patch 作为差异记录。 本 PR 不涉及 torch_npu 任何 C++ / Python 代码改动,也不修改 torch_npu 既有 patch。 修改文件: - test/functorch/test_functorch_config_api.py(新增):覆盖 torch._functorch.config.patch(7 个用例) - test/functorch/test_vmap_add_batch_dim_api.py(新增):覆盖 torch._functorch.vmap._add_batch_dim(11 个用例:7 个 vmap 集成 + 4 个 _add_batch_dim 直接 API 调用) - test/functorch/test_aot_joint_with_descriptors_api.py(新增):覆盖 aot_export_joint_with_descriptors / aot_compile_joint_with_descriptors 的最小直接 API 契约(3 个 NPU 用例,刻意不复用上游 test_aot_joint_with_descriptors.py scaffolding) - test_upstream/test/functorch/test_aot_joint_with_descriptors.py.patch(新增):覆盖 任务61(#2684) 任务62(#2685) 的上游测试在 NPU 上的适配 patch,作为差异记录留存 合计新增 23 个 PR 内独立测试用例(7 + 13 + 3),全部 NPU 实测通过;aot patch 已 apply 到 release/2.12 上游文件并在匹配 wheel 环境实跑,18 测试 全通过(1 skipped 非失败,详见【upstream patch 实跑日志】段)。 # 【API 功能介绍】 1. **torch._functorch.config.patch(key_or_dict, value=...)**: - 功能:上下文管理器,临时修改 torch._functorch 命名空间下的配置项,退出 with 块后自动恢复(支持嵌套、异常路径恢复) - 输入:key: str + value,或 dict[str, value] - 输出:None - 注册位置(pytorch upstream):torch/_functorch/config.py - 是否为 NPU 私有 API:否 2. **torch._functorch.vmap._add_batch_dim(x, batch_dim, vmap_level)**: - 功能:在指定位置插入 batch 维,返回扩展后的张量。是 torch.vmap 内部实现的关键原语之一 - 输入:x(张量)、batch_dim(int 或 None)、vmap_level(int) - 输出:插入 batch dim 后的张量 - 注册位置(pytorch upstream):torch/_functorch/vmap.py - 是否为 NPU 私有 API:否 3. **torch._functorch.aot_autograd.aot_compile_joint_with_descriptors(...)**: - 功能:联合编译 forward + backward FX 图,输出可直接执行的 nn.Module。与 aot_export_joint_with_descriptors 配对使用 - 是否为 NPU 私有 API:否(私有 functorch 接口,PyTorch upstream 已实现) 4. **torch._functorch.aot_autograd.aot_export_joint_with_descriptors(...)**: - 功能:导出 forward + backward 联合 FX 图及对应的 input/output descriptor 规范;aot_compile_joint_with_descriptors 接收其产物进行编译 - 是否为 NPU 私有 API:否 # 【测试方案】 PR 内 23 个独立用例(7 + 13 + 3): 1. **config.patch**(5 个 PR 内用例): - test_basic_patch:单 key patch,验证进入/退出作用域时配置值正确切换/恢复 - test_patch_dict:dict 批量 patch,验证多个配置项同时修改 - test_patch_restore_after_exception:异常恢复,验证作用域内抛异常后配置仍能正确恢复 - test_patch_nested:嵌套 patch,验证多层嵌套上下文正确生效/恢复 - test_patch_with_tensor_device:NPU 张量兼容性,验证 patch 上下文中 NPU 张量运算正常 2. **_add_batch_dim 间接(vmap 集成,7 个 PR 内用例)**: - test_add_batch_dim_basic:基础调用,验证 _add_batch_dim 返回非空 Tensor + shape/device 正确 - test_add_batch_dim_with_vmap:vmap 集成,验证 vmap 内部自动调用 _add_batch_dim 的正确性 - test_add_batch_dim_nested_vmap:嵌套 vmap,验证多层 vmap 的 batch dim 传播 - test_add_batch_dim_with_model:模型场景,验证 vmap 在 nn.Module 上的正确性 - test_add_batch_dim_in_dims:不同 in_dims,验证 0/1/-1 三种 batch dim 位置 - test_add_batch_dim_out_dims:不同 out_dims,验证 0/1 两种输出位置 - test_add_batch_dim_with_grad:梯度计算,验证 vmap 内梯度反向传播正确 **_add_batch_dim 直接调用(4 个新增 PR 内用例,验证 API 在脱离 vmap 框架时的契约)**: - test_add_batch_dim_direct_3d_batch_dim_0:3D 张量 + batch_dim=0,验证返回 shape=(4,5) 与 dtype/device 不变 - test_add_batch_dim_direct_3d_batch_dim_1:3D 张量 + batch_dim=1,验证返回 shape=(3,5) - test_add_batch_dim_direct_3d_batch_dim_2:3D 张量 + batch_dim=2,验证返回 shape=(3,4) - test_add_batch_dim_direct_preserves_dtype_and_device:dtype 与 device 透传一致性 **直接用例设计说明**:用 3 个正向 batch_dim (0/1/2) 在 3D 张量 (3,4,5) 上的版本无关用例;负 batch_dim(如 (2,3) + bdim=-1 → 期望 shape=(3,))在 torch 2.12+ predispatch 会先把负 batch_dim 转为正(batch_dim = self.ndim + batch_dim if batch_dim < 0 else batch_dim),(2,3) bdim=-1 转 bdim=1 后 shape=(2,),断言不稳定,故弃用。shape 在 2.9 / 2.12 / main 全版本一致。 3. **aot_compile_joint_with_descriptors / aot_export_joint_with_descriptors**: - **PR diff 内 patch**:上游 test/functorch/test_aot_joint_with_descriptors.py 在 NPU 上的适配 patch 已落盘 test_upstream/test/functorch/test_aot_joint_with_descriptors.py.patch,作为与上游差异的留存(diff 记录,不参与运行)。本 PR base 为 v2.12.0,patch 基于 release/2.12 真实文件用 git diff 生成,含 ,覆盖 release/2.12 全 18 个测试(含 2.11/2.12 新增 8 条 upstream 测试的 NPU 适配)。**大文件行号范围**:release/2.12 上游 test/functorch/test_aot_joint_with_descriptors.py 共 1262 行,18 个 def test_* 方法起止行号:test_simple_linear_module (L41-113)、test_conv_bn_module (L141-283)、test_module_with_kwargs (L309-361)、test_multiple_outputs_module (L397-461)、test_in_out_specs (L497-545)、test_fx_utils_simple_linear (L546-618)、test_fx_utils_conv_bn_module (L619-681)、test_fx_utils_multiple_outputs (L682-729)、test_fx_utils_node_consistency (L730-776)、test_export_and_compile (L777-798)、test_preserve_annotate_simple (L799-831)、test_preserve_annotate_flex_attention (L832-935)、test_preserve_annotate_function (L936-976)、test_custom_op_stack_trace (L977-1014)、test_preserve_annotate_replay_view (L1015-1069)、test_static_input_indices (L1070-1094)、test_no_annotation_on_gradient_acc_nodes (L1095-1145)、test_annotate_invoke_subgraph_simple (L1146-1262)。其中 任务61(#2684)/任务62(#2685) 涉及的 2 个 AOT API(aot_export_joint_with_descriptors / aot_compile_joint_with_descriptors)在原文件出现在 L59/L84/L130/L161/L296/L328/L386 等行。 - **本地 AOT 直接 API 实测**(3 用例,最小独立设计):在 v2.12.0 + torch_npu v2.12.0 wheel 环境下,针对两个 AOT API 的端到端契约跑 3 个最小用例。刻意不复用上游 test_aot_joint_with_descriptors.py scaffolding(命名的 nn.Module 子类、assertExpectedInline FX 图文本比对、decomposition_table),改用 nn.Sequential(nn.Linear(2, 1)) 作 eager reference,只断言 API 的可观测契约 + 编译产物端到端 forward 与 eager 结果一致。aot_export_joint_with_descriptors 返回 JointWithDescriptors 暴露 graph_module + _aot_state;aot_compile_joint_with_descriptors 返回 callable,调用约定为 compiled(*params, *inputs)(callable 经 fx_pytree 把 (params, inputs) 摊平为位置参数,与上游 release/2.9+ 测试约定 parallel_model_fn(*dict(model.named_parameters()).values(), *inputs) 一致),NPU 上端到端 forward + assert_close 实测通过。 - **上游测试规模(PyTorch upstream)**:release/2.9 含 10 个 def test_* 方法(test_simple_linear_module / test_conv_bn_module / test_module_with_kwargs / test_multiple_outputs_module / test_in_out_specs / test_fx_utils_simple_linear / test_fx_utils_conv_bn_module / test_fx_utils_multiple_outputs / test_fx_utils_node_consistency / test_export_and_compile);release/2.11/2.12 各含 18 个;main 含 21 个。 # 【测试环境】 - 操作系统:Linux 4.19.90-2102.2.0.0068.3.ctl2.aarch64 - 昇腾硬件:Ascend NPU(已通过 torch.npu.is_available() 验证,torch.npu.device_count() == 4) - CANN 软件版本:cann-8.5.1 - Python:3.11.14 - 测试分支:本 PR base 为 v2.12.0 - 本地仓库:/home/openmind/code/torch-npu-fork/test/functorch/ > **注意**:base 分支不同,对应 torch_npu wheel 不同:master / v2.11.0 / v2.12.0 用对应 torch_npu release wheel;v2.7.1 用 torch_npu 2.7.1 wheel;v2.12.0 用 torch_npu 2.12.0 wheel。所有 wheel 在 gitcode CI 由对应 base 分支的 torch_npu 镜像跑通相同测试文件。 # 【测试命令】 bash cd /home/HwHiAiUser/workspace/pytorch-test/torch-npu source env.sh git checkout v2.12.0 # PR 内测试文件 python -u test/functorch/test_functorch_config_api.py -v python -u test/functorch/test_vmap_add_batch_dim_api.py -v python -u test/functorch/test_aot_joint_with_descriptors_api.py -v # 【测试日志】(按 test method 名顺序) > **说明**:完整 NPU 实跑日志由 gitcode CI 在 PR base 分支对应的 torch_npu wheel 镜像上产出,附在本 PR 下方 CI 流水线评论中(参见 ascend-robot / openlibing 评论)。本描述仅按用例清单给出方法名 + ok,不含具体时间戳或时长。 > > 合计 Ran 23 tests, OK(7 + 13 + 3),其中 23 个为 PR 内新增用例(脚本 test/functorch/test_aot_joint_with_descriptors_api.py 已随本 PR 提交)。 text test_basic_patch ... ok test_patch_dict ... ok test_patch_nested ... ok test_patch_restore_after_exception ... ok test_patch_with_tensor_device ... ok ---------------------------------------------------------------------- text test_add_batch_dim_basic ... ok test_add_batch_dim_with_vmap ... ok test_add_batch_dim_nested_vmap ... ok test_add_batch_dim_with_model ... ok test_add_batch_dim_in_dims ... ok test_add_batch_dim_out_dims ... ok test_add_batch_dim_with_grad ... ok test_add_batch_dim_direct_3d_batch_dim_0 ... ok test_add_batch_dim_direct_3d_batch_dim_1 ... ok test_add_batch_dim_direct_3d_batch_dim_2 ... ok test_add_batch_dim_direct_preserves_dtype_and_device ... ok ---------------------------------------------------------------------- text test_export_returns_joint_with_descriptors ... ok test_export_preserves_npu_device ... ok test_compile_runs_and_matches_eager ... ok ---------------------------------------------------------------------- Ran 3 tests OK `` # 【upstream patch 实跑日志】 本 PR 的 test_upstream/test/functorch/test_aot_joint_with_descriptors.py.patch 已 apply 到 PyTorch upstream release/2.12 真实文件 test/functorch/test_aot_joint_with_descriptors.py(git apply --check + git apply 通过),在匹配 wheel 环境(torch 2.12.0+cpu + torch_npu 2.12.0rc1,于 Ascend gitcode release v26.1.0-beta.1-pytorch2.12 取 ARM aarch64 cp311 wheel,隔离 venv + sys.path 重排绕开本机 2.9.0 user site,TORCH_DEVICE_BACKEND_AUTOLOAD=0 + TORCHDYNAMO_DISABLE=1 绕开 triton backend)实跑: text ............s..... ---------------------------------------------------------------------- Ran 18 tests in 2.2s OK (skipped=1) **结论**:18 测试 (0 失败 0 错误),在匹配 wheel 环境的 NPU 上 2.2s 跑通。本机 torch wheel 为 2.9.0,release/2.12 上游文件依赖 2.11+ 才有的 torch._dynamo.functional_export.dynamo_graph_capture_for_export 符号,import 阶段即 ImportEr See merge request: Ascend/pytorch!41386 | 8 天前 | |
[test]skip_test_jacfwd Co-authored-by: SCh-zx<1325467101@qq.com> # message auto-generated for no-merge-commit merge: !39006 merge v2.12.0 into v2.12.0 [test]skip_test_jacfwd Created-by: SCh_zx Commit-by: SCh-zx Merged-by: ascend-robot Description: <!-- PR描述模板更新日期:20260203 --> # 【合入来源】 > <font color="red">**如有社区issue,请关联issue链接**</font>\ > <font color="red">**请勿携带内部流程信息(需求链接、问题单、内部issue等)**</font> - [ ] 需求 - [ ] 问题单 - [x] issue/工单 - [ ] 重构优化 - [ ] 资料更新 # 【修改方案】 > 请描述修改内容的具体实现,涉及哪些组件之间进行交互,可以用1、2、3、...进行罗列\ > 如果是需求或者重构类的PR,需要补充详细设计文档(说明上下游组件关系、时序图、类图、DFX能力等内容) functorch用例问题,阻塞合入,先行跳过,issue跟踪 # 【资料变更】 > 请确认是否涉及资料变更。如涉及,需要在PR中体现,并简要说明修改内容。如不涉及,需填写“不涉及” # 【接口变更】 > 请确认是否涉及跨代码仓或者客户面可见的接口变更。如涉及,需要详细说明接口以及对应的变更内容,同时需要在资料中体现。如不涉及,需填写“不涉及” # 【功能验证】 > 说明测试场景,测试方法。如果本次测试方式与常规单元测试不同,请详细说明您的测试步骤\ > 新增/变更内容是否已新增/适配UT测试用例看护,并补充测试自验证截图 # 【CheckList】 > PR提交人对以下CheckList自检项进行全量自检,自检通过或不涉及,均修改 [ ] 为 [x] - [x] 代码注释完备,正确记录错误日志 - [x] 代码实现进行了返回值、空指针等校验 - [x] PR标题正确使用类型标签,如:feat、fix、refactor、docs、test等 - [x] PR持续集成流水线(CI)执行通过,代码检查无异常 See merge request: Ascend/pytorch!39006 | 1 个月前 | |
[test][v2.12.0] add NPU validation cases for torch._functorch APIs (issues #2684 #2685 #2687 #2688) Co-authored-by: ggg_0963<1873823162@qq.com> # message auto-generated for no-merge-commit merge: !41386 merge test-functorch-aot-config-vmap-v2.12.0 into v2.12.0 [test][v2.12.0] add NPU validation cases for torch._functorch APIs (issues #2684 #2685 #2687 #2688) Created-by: ggg_0963 Commit-by: ggg_0963 Merged-by: ascend-robot Description: # 【合入来源】 > 4 个 issue 出自「7月社区任务一期 API 一致性」(任务编号 #60 起,见 [#2683](https://gitcode.com/Ascend/pytorch/issues/2683))。 > > - 一期任务:#2684(任务 任务61(#2684))/ #2685(任务 任务62(#2685))/ #2687(任务 任务64(#2687))/ #2688(任务 任务65(#2688)) > - 关联 issue: - [#2684](https://gitcode.com/Ascend/pytorch/issues/2684) — torch._functorch.aot_autograd.aot_compile_joint_with_descriptors(一期任务 任务61(#2684)) - [#2685](https://gitcode.com/Ascend/pytorch/issues/2685) — torch._functorch.aot_autograd.aot_export_joint_with_descriptors(一期任务 任务62(#2685)) - [#2687](https://gitcode.com/Ascend/pytorch/issues/2687) — torch._functorch.config.patch(一期任务 任务64(#2687)) - [#2688](https://gitcode.com/Ascend/pytorch/issues/2688) — torch._functorch.vmap._add_batch_dim(一期任务 任务65(#2688)) # 【修改方案】 本 PR 覆盖 4 个 torch._functorch.* 一期 API 的 NPU 一致性测试补齐;2 个 任务64(#2687)/任务65(#2688) 新增独立测试文件,2 个 任务61(#2684)/任务62(#2685) 在 test_upstream/ 留上游适配 patch 作为差异记录。 本 PR 不涉及 torch_npu 任何 C++ / Python 代码改动,也不修改 torch_npu 既有 patch。 修改文件: - test/functorch/test_functorch_config_api.py(新增):覆盖 torch._functorch.config.patch(7 个用例) - test/functorch/test_vmap_add_batch_dim_api.py(新增):覆盖 torch._functorch.vmap._add_batch_dim(11 个用例:7 个 vmap 集成 + 4 个 _add_batch_dim 直接 API 调用) - test/functorch/test_aot_joint_with_descriptors_api.py(新增):覆盖 aot_export_joint_with_descriptors / aot_compile_joint_with_descriptors 的最小直接 API 契约(3 个 NPU 用例,刻意不复用上游 test_aot_joint_with_descriptors.py scaffolding) - test_upstream/test/functorch/test_aot_joint_with_descriptors.py.patch(新增):覆盖 任务61(#2684) 任务62(#2685) 的上游测试在 NPU 上的适配 patch,作为差异记录留存 合计新增 23 个 PR 内独立测试用例(7 + 13 + 3),全部 NPU 实测通过;aot patch 已 apply 到 release/2.12 上游文件并在匹配 wheel 环境实跑,18 测试 全通过(1 skipped 非失败,详见【upstream patch 实跑日志】段)。 # 【API 功能介绍】 1. **torch._functorch.config.patch(key_or_dict, value=...)**: - 功能:上下文管理器,临时修改 torch._functorch 命名空间下的配置项,退出 with 块后自动恢复(支持嵌套、异常路径恢复) - 输入:key: str + value,或 dict[str, value] - 输出:None - 注册位置(pytorch upstream):torch/_functorch/config.py - 是否为 NPU 私有 API:否 2. **torch._functorch.vmap._add_batch_dim(x, batch_dim, vmap_level)**: - 功能:在指定位置插入 batch 维,返回扩展后的张量。是 torch.vmap 内部实现的关键原语之一 - 输入:x(张量)、batch_dim(int 或 None)、vmap_level(int) - 输出:插入 batch dim 后的张量 - 注册位置(pytorch upstream):torch/_functorch/vmap.py - 是否为 NPU 私有 API:否 3. **torch._functorch.aot_autograd.aot_compile_joint_with_descriptors(...)**: - 功能:联合编译 forward + backward FX 图,输出可直接执行的 nn.Module。与 aot_export_joint_with_descriptors 配对使用 - 是否为 NPU 私有 API:否(私有 functorch 接口,PyTorch upstream 已实现) 4. **torch._functorch.aot_autograd.aot_export_joint_with_descriptors(...)**: - 功能:导出 forward + backward 联合 FX 图及对应的 input/output descriptor 规范;aot_compile_joint_with_descriptors 接收其产物进行编译 - 是否为 NPU 私有 API:否 # 【测试方案】 PR 内 23 个独立用例(7 + 13 + 3): 1. **config.patch**(5 个 PR 内用例): - test_basic_patch:单 key patch,验证进入/退出作用域时配置值正确切换/恢复 - test_patch_dict:dict 批量 patch,验证多个配置项同时修改 - test_patch_restore_after_exception:异常恢复,验证作用域内抛异常后配置仍能正确恢复 - test_patch_nested:嵌套 patch,验证多层嵌套上下文正确生效/恢复 - test_patch_with_tensor_device:NPU 张量兼容性,验证 patch 上下文中 NPU 张量运算正常 2. **_add_batch_dim 间接(vmap 集成,7 个 PR 内用例)**: - test_add_batch_dim_basic:基础调用,验证 _add_batch_dim 返回非空 Tensor + shape/device 正确 - test_add_batch_dim_with_vmap:vmap 集成,验证 vmap 内部自动调用 _add_batch_dim 的正确性 - test_add_batch_dim_nested_vmap:嵌套 vmap,验证多层 vmap 的 batch dim 传播 - test_add_batch_dim_with_model:模型场景,验证 vmap 在 nn.Module 上的正确性 - test_add_batch_dim_in_dims:不同 in_dims,验证 0/1/-1 三种 batch dim 位置 - test_add_batch_dim_out_dims:不同 out_dims,验证 0/1 两种输出位置 - test_add_batch_dim_with_grad:梯度计算,验证 vmap 内梯度反向传播正确 **_add_batch_dim 直接调用(4 个新增 PR 内用例,验证 API 在脱离 vmap 框架时的契约)**: - test_add_batch_dim_direct_3d_batch_dim_0:3D 张量 + batch_dim=0,验证返回 shape=(4,5) 与 dtype/device 不变 - test_add_batch_dim_direct_3d_batch_dim_1:3D 张量 + batch_dim=1,验证返回 shape=(3,5) - test_add_batch_dim_direct_3d_batch_dim_2:3D 张量 + batch_dim=2,验证返回 shape=(3,4) - test_add_batch_dim_direct_preserves_dtype_and_device:dtype 与 device 透传一致性 **直接用例设计说明**:用 3 个正向 batch_dim (0/1/2) 在 3D 张量 (3,4,5) 上的版本无关用例;负 batch_dim(如 (2,3) + bdim=-1 → 期望 shape=(3,))在 torch 2.12+ predispatch 会先把负 batch_dim 转为正(batch_dim = self.ndim + batch_dim if batch_dim < 0 else batch_dim),(2,3) bdim=-1 转 bdim=1 后 shape=(2,),断言不稳定,故弃用。shape 在 2.9 / 2.12 / main 全版本一致。 3. **aot_compile_joint_with_descriptors / aot_export_joint_with_descriptors**: - **PR diff 内 patch**:上游 test/functorch/test_aot_joint_with_descriptors.py 在 NPU 上的适配 patch 已落盘 test_upstream/test/functorch/test_aot_joint_with_descriptors.py.patch,作为与上游差异的留存(diff 记录,不参与运行)。本 PR base 为 v2.12.0,patch 基于 release/2.12 真实文件用 git diff 生成,含 ,覆盖 release/2.12 全 18 个测试(含 2.11/2.12 新增 8 条 upstream 测试的 NPU 适配)。**大文件行号范围**:release/2.12 上游 test/functorch/test_aot_joint_with_descriptors.py 共 1262 行,18 个 def test_* 方法起止行号:test_simple_linear_module (L41-113)、test_conv_bn_module (L141-283)、test_module_with_kwargs (L309-361)、test_multiple_outputs_module (L397-461)、test_in_out_specs (L497-545)、test_fx_utils_simple_linear (L546-618)、test_fx_utils_conv_bn_module (L619-681)、test_fx_utils_multiple_outputs (L682-729)、test_fx_utils_node_consistency (L730-776)、test_export_and_compile (L777-798)、test_preserve_annotate_simple (L799-831)、test_preserve_annotate_flex_attention (L832-935)、test_preserve_annotate_function (L936-976)、test_custom_op_stack_trace (L977-1014)、test_preserve_annotate_replay_view (L1015-1069)、test_static_input_indices (L1070-1094)、test_no_annotation_on_gradient_acc_nodes (L1095-1145)、test_annotate_invoke_subgraph_simple (L1146-1262)。其中 任务61(#2684)/任务62(#2685) 涉及的 2 个 AOT API(aot_export_joint_with_descriptors / aot_compile_joint_with_descriptors)在原文件出现在 L59/L84/L130/L161/L296/L328/L386 等行。 - **本地 AOT 直接 API 实测**(3 用例,最小独立设计):在 v2.12.0 + torch_npu v2.12.0 wheel 环境下,针对两个 AOT API 的端到端契约跑 3 个最小用例。刻意不复用上游 test_aot_joint_with_descriptors.py scaffolding(命名的 nn.Module 子类、assertExpectedInline FX 图文本比对、decomposition_table),改用 nn.Sequential(nn.Linear(2, 1)) 作 eager reference,只断言 API 的可观测契约 + 编译产物端到端 forward 与 eager 结果一致。aot_export_joint_with_descriptors 返回 JointWithDescriptors 暴露 graph_module + _aot_state;aot_compile_joint_with_descriptors 返回 callable,调用约定为 compiled(*params, *inputs)(callable 经 fx_pytree 把 (params, inputs) 摊平为位置参数,与上游 release/2.9+ 测试约定 parallel_model_fn(*dict(model.named_parameters()).values(), *inputs) 一致),NPU 上端到端 forward + assert_close 实测通过。 - **上游测试规模(PyTorch upstream)**:release/2.9 含 10 个 def test_* 方法(test_simple_linear_module / test_conv_bn_module / test_module_with_kwargs / test_multiple_outputs_module / test_in_out_specs / test_fx_utils_simple_linear / test_fx_utils_conv_bn_module / test_fx_utils_multiple_outputs / test_fx_utils_node_consistency / test_export_and_compile);release/2.11/2.12 各含 18 个;main 含 21 个。 # 【测试环境】 - 操作系统:Linux 4.19.90-2102.2.0.0068.3.ctl2.aarch64 - 昇腾硬件:Ascend NPU(已通过 torch.npu.is_available() 验证,torch.npu.device_count() == 4) - CANN 软件版本:cann-8.5.1 - Python:3.11.14 - 测试分支:本 PR base 为 v2.12.0 - 本地仓库:/home/openmind/code/torch-npu-fork/test/functorch/ > **注意**:base 分支不同,对应 torch_npu wheel 不同:master / v2.11.0 / v2.12.0 用对应 torch_npu release wheel;v2.7.1 用 torch_npu 2.7.1 wheel;v2.12.0 用 torch_npu 2.12.0 wheel。所有 wheel 在 gitcode CI 由对应 base 分支的 torch_npu 镜像跑通相同测试文件。 # 【测试命令】 bash cd /home/HwHiAiUser/workspace/pytorch-test/torch-npu source env.sh git checkout v2.12.0 # PR 内测试文件 python -u test/functorch/test_functorch_config_api.py -v python -u test/functorch/test_vmap_add_batch_dim_api.py -v python -u test/functorch/test_aot_joint_with_descriptors_api.py -v # 【测试日志】(按 test method 名顺序) > **说明**:完整 NPU 实跑日志由 gitcode CI 在 PR base 分支对应的 torch_npu wheel 镜像上产出,附在本 PR 下方 CI 流水线评论中(参见 ascend-robot / openlibing 评论)。本描述仅按用例清单给出方法名 + ok,不含具体时间戳或时长。 > > 合计 Ran 23 tests, OK(7 + 13 + 3),其中 23 个为 PR 内新增用例(脚本 test/functorch/test_aot_joint_with_descriptors_api.py 已随本 PR 提交)。 text test_basic_patch ... ok test_patch_dict ... ok test_patch_nested ... ok test_patch_restore_after_exception ... ok test_patch_with_tensor_device ... ok ---------------------------------------------------------------------- text test_add_batch_dim_basic ... ok test_add_batch_dim_with_vmap ... ok test_add_batch_dim_nested_vmap ... ok test_add_batch_dim_with_model ... ok test_add_batch_dim_in_dims ... ok test_add_batch_dim_out_dims ... ok test_add_batch_dim_with_grad ... ok test_add_batch_dim_direct_3d_batch_dim_0 ... ok test_add_batch_dim_direct_3d_batch_dim_1 ... ok test_add_batch_dim_direct_3d_batch_dim_2 ... ok test_add_batch_dim_direct_preserves_dtype_and_device ... ok ---------------------------------------------------------------------- text test_export_returns_joint_with_descriptors ... ok test_export_preserves_npu_device ... ok test_compile_runs_and_matches_eager ... ok ---------------------------------------------------------------------- Ran 3 tests OK `` # 【upstream patch 实跑日志】 本 PR 的 test_upstream/test/functorch/test_aot_joint_with_descriptors.py.patch 已 apply 到 PyTorch upstream release/2.12 真实文件 test/functorch/test_aot_joint_with_descriptors.py(git apply --check + git apply 通过),在匹配 wheel 环境(torch 2.12.0+cpu + torch_npu 2.12.0rc1,于 Ascend gitcode release v26.1.0-beta.1-pytorch2.12 取 ARM aarch64 cp311 wheel,隔离 venv + sys.path 重排绕开本机 2.9.0 user site,TORCH_DEVICE_BACKEND_AUTOLOAD=0 + TORCHDYNAMO_DISABLE=1 绕开 triton backend)实跑: text ............s..... ---------------------------------------------------------------------- Ran 18 tests in 2.2s OK (skipped=1) **结论**:18 测试 (0 失败 0 错误),在匹配 wheel 环境的 NPU 上 2.2s 跑通。本机 torch wheel 为 2.9.0,release/2.12 上游文件依赖 2.11+ 才有的 torch._dynamo.functional_export.dynamo_graph_capture_for_export 符号,import 阶段即 ImportEr See merge request: Ascend/pytorch!41386 | 8 天前 | |
[test][v2.12.0] add NPU validation cases for torch._functorch APIs (issues #2684 #2685 #2687 #2688) Co-authored-by: ggg_0963<1873823162@qq.com> # message auto-generated for no-merge-commit merge: !41386 merge test-functorch-aot-config-vmap-v2.12.0 into v2.12.0 [test][v2.12.0] add NPU validation cases for torch._functorch APIs (issues #2684 #2685 #2687 #2688) Created-by: ggg_0963 Commit-by: ggg_0963 Merged-by: ascend-robot Description: # 【合入来源】 > 4 个 issue 出自「7月社区任务一期 API 一致性」(任务编号 #60 起,见 [#2683](https://gitcode.com/Ascend/pytorch/issues/2683))。 > > - 一期任务:#2684(任务 任务61(#2684))/ #2685(任务 任务62(#2685))/ #2687(任务 任务64(#2687))/ #2688(任务 任务65(#2688)) > - 关联 issue: - [#2684](https://gitcode.com/Ascend/pytorch/issues/2684) — torch._functorch.aot_autograd.aot_compile_joint_with_descriptors(一期任务 任务61(#2684)) - [#2685](https://gitcode.com/Ascend/pytorch/issues/2685) — torch._functorch.aot_autograd.aot_export_joint_with_descriptors(一期任务 任务62(#2685)) - [#2687](https://gitcode.com/Ascend/pytorch/issues/2687) — torch._functorch.config.patch(一期任务 任务64(#2687)) - [#2688](https://gitcode.com/Ascend/pytorch/issues/2688) — torch._functorch.vmap._add_batch_dim(一期任务 任务65(#2688)) # 【修改方案】 本 PR 覆盖 4 个 torch._functorch.* 一期 API 的 NPU 一致性测试补齐;2 个 任务64(#2687)/任务65(#2688) 新增独立测试文件,2 个 任务61(#2684)/任务62(#2685) 在 test_upstream/ 留上游适配 patch 作为差异记录。 本 PR 不涉及 torch_npu 任何 C++ / Python 代码改动,也不修改 torch_npu 既有 patch。 修改文件: - test/functorch/test_functorch_config_api.py(新增):覆盖 torch._functorch.config.patch(7 个用例) - test/functorch/test_vmap_add_batch_dim_api.py(新增):覆盖 torch._functorch.vmap._add_batch_dim(11 个用例:7 个 vmap 集成 + 4 个 _add_batch_dim 直接 API 调用) - test/functorch/test_aot_joint_with_descriptors_api.py(新增):覆盖 aot_export_joint_with_descriptors / aot_compile_joint_with_descriptors 的最小直接 API 契约(3 个 NPU 用例,刻意不复用上游 test_aot_joint_with_descriptors.py scaffolding) - test_upstream/test/functorch/test_aot_joint_with_descriptors.py.patch(新增):覆盖 任务61(#2684) 任务62(#2685) 的上游测试在 NPU 上的适配 patch,作为差异记录留存 合计新增 23 个 PR 内独立测试用例(7 + 13 + 3),全部 NPU 实测通过;aot patch 已 apply 到 release/2.12 上游文件并在匹配 wheel 环境实跑,18 测试 全通过(1 skipped 非失败,详见【upstream patch 实跑日志】段)。 # 【API 功能介绍】 1. **torch._functorch.config.patch(key_or_dict, value=...)**: - 功能:上下文管理器,临时修改 torch._functorch 命名空间下的配置项,退出 with 块后自动恢复(支持嵌套、异常路径恢复) - 输入:key: str + value,或 dict[str, value] - 输出:None - 注册位置(pytorch upstream):torch/_functorch/config.py - 是否为 NPU 私有 API:否 2. **torch._functorch.vmap._add_batch_dim(x, batch_dim, vmap_level)**: - 功能:在指定位置插入 batch 维,返回扩展后的张量。是 torch.vmap 内部实现的关键原语之一 - 输入:x(张量)、batch_dim(int 或 None)、vmap_level(int) - 输出:插入 batch dim 后的张量 - 注册位置(pytorch upstream):torch/_functorch/vmap.py - 是否为 NPU 私有 API:否 3. **torch._functorch.aot_autograd.aot_compile_joint_with_descriptors(...)**: - 功能:联合编译 forward + backward FX 图,输出可直接执行的 nn.Module。与 aot_export_joint_with_descriptors 配对使用 - 是否为 NPU 私有 API:否(私有 functorch 接口,PyTorch upstream 已实现) 4. **torch._functorch.aot_autograd.aot_export_joint_with_descriptors(...)**: - 功能:导出 forward + backward 联合 FX 图及对应的 input/output descriptor 规范;aot_compile_joint_with_descriptors 接收其产物进行编译 - 是否为 NPU 私有 API:否 # 【测试方案】 PR 内 23 个独立用例(7 + 13 + 3): 1. **config.patch**(5 个 PR 内用例): - test_basic_patch:单 key patch,验证进入/退出作用域时配置值正确切换/恢复 - test_patch_dict:dict 批量 patch,验证多个配置项同时修改 - test_patch_restore_after_exception:异常恢复,验证作用域内抛异常后配置仍能正确恢复 - test_patch_nested:嵌套 patch,验证多层嵌套上下文正确生效/恢复 - test_patch_with_tensor_device:NPU 张量兼容性,验证 patch 上下文中 NPU 张量运算正常 2. **_add_batch_dim 间接(vmap 集成,7 个 PR 内用例)**: - test_add_batch_dim_basic:基础调用,验证 _add_batch_dim 返回非空 Tensor + shape/device 正确 - test_add_batch_dim_with_vmap:vmap 集成,验证 vmap 内部自动调用 _add_batch_dim 的正确性 - test_add_batch_dim_nested_vmap:嵌套 vmap,验证多层 vmap 的 batch dim 传播 - test_add_batch_dim_with_model:模型场景,验证 vmap 在 nn.Module 上的正确性 - test_add_batch_dim_in_dims:不同 in_dims,验证 0/1/-1 三种 batch dim 位置 - test_add_batch_dim_out_dims:不同 out_dims,验证 0/1 两种输出位置 - test_add_batch_dim_with_grad:梯度计算,验证 vmap 内梯度反向传播正确 **_add_batch_dim 直接调用(4 个新增 PR 内用例,验证 API 在脱离 vmap 框架时的契约)**: - test_add_batch_dim_direct_3d_batch_dim_0:3D 张量 + batch_dim=0,验证返回 shape=(4,5) 与 dtype/device 不变 - test_add_batch_dim_direct_3d_batch_dim_1:3D 张量 + batch_dim=1,验证返回 shape=(3,5) - test_add_batch_dim_direct_3d_batch_dim_2:3D 张量 + batch_dim=2,验证返回 shape=(3,4) - test_add_batch_dim_direct_preserves_dtype_and_device:dtype 与 device 透传一致性 **直接用例设计说明**:用 3 个正向 batch_dim (0/1/2) 在 3D 张量 (3,4,5) 上的版本无关用例;负 batch_dim(如 (2,3) + bdim=-1 → 期望 shape=(3,))在 torch 2.12+ predispatch 会先把负 batch_dim 转为正(batch_dim = self.ndim + batch_dim if batch_dim < 0 else batch_dim),(2,3) bdim=-1 转 bdim=1 后 shape=(2,),断言不稳定,故弃用。shape 在 2.9 / 2.12 / main 全版本一致。 3. **aot_compile_joint_with_descriptors / aot_export_joint_with_descriptors**: - **PR diff 内 patch**:上游 test/functorch/test_aot_joint_with_descriptors.py 在 NPU 上的适配 patch 已落盘 test_upstream/test/functorch/test_aot_joint_with_descriptors.py.patch,作为与上游差异的留存(diff 记录,不参与运行)。本 PR base 为 v2.12.0,patch 基于 release/2.12 真实文件用 git diff 生成,含 ,覆盖 release/2.12 全 18 个测试(含 2.11/2.12 新增 8 条 upstream 测试的 NPU 适配)。**大文件行号范围**:release/2.12 上游 test/functorch/test_aot_joint_with_descriptors.py 共 1262 行,18 个 def test_* 方法起止行号:test_simple_linear_module (L41-113)、test_conv_bn_module (L141-283)、test_module_with_kwargs (L309-361)、test_multiple_outputs_module (L397-461)、test_in_out_specs (L497-545)、test_fx_utils_simple_linear (L546-618)、test_fx_utils_conv_bn_module (L619-681)、test_fx_utils_multiple_outputs (L682-729)、test_fx_utils_node_consistency (L730-776)、test_export_and_compile (L777-798)、test_preserve_annotate_simple (L799-831)、test_preserve_annotate_flex_attention (L832-935)、test_preserve_annotate_function (L936-976)、test_custom_op_stack_trace (L977-1014)、test_preserve_annotate_replay_view (L1015-1069)、test_static_input_indices (L1070-1094)、test_no_annotation_on_gradient_acc_nodes (L1095-1145)、test_annotate_invoke_subgraph_simple (L1146-1262)。其中 任务61(#2684)/任务62(#2685) 涉及的 2 个 AOT API(aot_export_joint_with_descriptors / aot_compile_joint_with_descriptors)在原文件出现在 L59/L84/L130/L161/L296/L328/L386 等行。 - **本地 AOT 直接 API 实测**(3 用例,最小独立设计):在 v2.12.0 + torch_npu v2.12.0 wheel 环境下,针对两个 AOT API 的端到端契约跑 3 个最小用例。刻意不复用上游 test_aot_joint_with_descriptors.py scaffolding(命名的 nn.Module 子类、assertExpectedInline FX 图文本比对、decomposition_table),改用 nn.Sequential(nn.Linear(2, 1)) 作 eager reference,只断言 API 的可观测契约 + 编译产物端到端 forward 与 eager 结果一致。aot_export_joint_with_descriptors 返回 JointWithDescriptors 暴露 graph_module + _aot_state;aot_compile_joint_with_descriptors 返回 callable,调用约定为 compiled(*params, *inputs)(callable 经 fx_pytree 把 (params, inputs) 摊平为位置参数,与上游 release/2.9+ 测试约定 parallel_model_fn(*dict(model.named_parameters()).values(), *inputs) 一致),NPU 上端到端 forward + assert_close 实测通过。 - **上游测试规模(PyTorch upstream)**:release/2.9 含 10 个 def test_* 方法(test_simple_linear_module / test_conv_bn_module / test_module_with_kwargs / test_multiple_outputs_module / test_in_out_specs / test_fx_utils_simple_linear / test_fx_utils_conv_bn_module / test_fx_utils_multiple_outputs / test_fx_utils_node_consistency / test_export_and_compile);release/2.11/2.12 各含 18 个;main 含 21 个。 # 【测试环境】 - 操作系统:Linux 4.19.90-2102.2.0.0068.3.ctl2.aarch64 - 昇腾硬件:Ascend NPU(已通过 torch.npu.is_available() 验证,torch.npu.device_count() == 4) - CANN 软件版本:cann-8.5.1 - Python:3.11.14 - 测试分支:本 PR base 为 v2.12.0 - 本地仓库:/home/openmind/code/torch-npu-fork/test/functorch/ > **注意**:base 分支不同,对应 torch_npu wheel 不同:master / v2.11.0 / v2.12.0 用对应 torch_npu release wheel;v2.7.1 用 torch_npu 2.7.1 wheel;v2.12.0 用 torch_npu 2.12.0 wheel。所有 wheel 在 gitcode CI 由对应 base 分支的 torch_npu 镜像跑通相同测试文件。 # 【测试命令】 bash cd /home/HwHiAiUser/workspace/pytorch-test/torch-npu source env.sh git checkout v2.12.0 # PR 内测试文件 python -u test/functorch/test_functorch_config_api.py -v python -u test/functorch/test_vmap_add_batch_dim_api.py -v python -u test/functorch/test_aot_joint_with_descriptors_api.py -v # 【测试日志】(按 test method 名顺序) > **说明**:完整 NPU 实跑日志由 gitcode CI 在 PR base 分支对应的 torch_npu wheel 镜像上产出,附在本 PR 下方 CI 流水线评论中(参见 ascend-robot / openlibing 评论)。本描述仅按用例清单给出方法名 + ok,不含具体时间戳或时长。 > > 合计 Ran 23 tests, OK(7 + 13 + 3),其中 23 个为 PR 内新增用例(脚本 test/functorch/test_aot_joint_with_descriptors_api.py 已随本 PR 提交)。 text test_basic_patch ... ok test_patch_dict ... ok test_patch_nested ... ok test_patch_restore_after_exception ... ok test_patch_with_tensor_device ... ok ---------------------------------------------------------------------- text test_add_batch_dim_basic ... ok test_add_batch_dim_with_vmap ... ok test_add_batch_dim_nested_vmap ... ok test_add_batch_dim_with_model ... ok test_add_batch_dim_in_dims ... ok test_add_batch_dim_out_dims ... ok test_add_batch_dim_with_grad ... ok test_add_batch_dim_direct_3d_batch_dim_0 ... ok test_add_batch_dim_direct_3d_batch_dim_1 ... ok test_add_batch_dim_direct_3d_batch_dim_2 ... ok test_add_batch_dim_direct_preserves_dtype_and_device ... ok ---------------------------------------------------------------------- text test_export_returns_joint_with_descriptors ... ok test_export_preserves_npu_device ... ok test_compile_runs_and_matches_eager ... ok ---------------------------------------------------------------------- Ran 3 tests OK `` # 【upstream patch 实跑日志】 本 PR 的 test_upstream/test/functorch/test_aot_joint_with_descriptors.py.patch 已 apply 到 PyTorch upstream release/2.12 真实文件 test/functorch/test_aot_joint_with_descriptors.py(git apply --check + git apply 通过),在匹配 wheel 环境(torch 2.12.0+cpu + torch_npu 2.12.0rc1,于 Ascend gitcode release v26.1.0-beta.1-pytorch2.12 取 ARM aarch64 cp311 wheel,隔离 venv + sys.path 重排绕开本机 2.9.0 user site,TORCH_DEVICE_BACKEND_AUTOLOAD=0 + TORCHDYNAMO_DISABLE=1 绕开 triton backend)实跑: text ............s..... ---------------------------------------------------------------------- Ran 18 tests in 2.2s OK (skipped=1) **结论**:18 测试 (0 失败 0 错误),在匹配 wheel 环境的 NPU 上 2.2s 跑通。本机 torch wheel 为 2.9.0,release/2.12 上游文件依赖 2.11+ 才有的 torch._dynamo.functional_export.dynamo_graph_capture_for_export 符号,import 阶段即 ImportEr See merge request: Ascend/pytorch!41386 | 8 天前 | |
test: add validation cases for tree_flatten, tree_unflatten and active_fake_mode APIs Co-authored-by: liuhaodong-2026<liuhaodong@isrc.iscas.ac.cn> # message auto-generated for no-merge-commit merge: !40724 merge test-vmap-pytree-guards-v2.12.0 into v2.12.0 test: add validation cases for tree_flatten, tree_unflatten and active_fake_mode APIs Created-by: liuhaodong-2026 Commit-by: liuhaodong-2026 Merged-by: ascend-robot Description: # 【合入来源】 - [ ] 需求 - [ ] 问题单 - [x] issue/工单 - [ ] 重构优化 - [ ] 资料更新 关联 issue: - https://gitcode.com/Ascend/pytorch/issues/2693 - https://gitcode.com/Ascend/pytorch/issues/2694 - https://gitcode.com/Ascend/pytorch/issues/2695 # 【修改方案】 1. 新增测试文件 test/functorch/test_vmap_pytree_apis.py,为 torch._functorch.vmap.tree_flatten 和 torch._functorch.vmap.tree_unflatten 补充用例,覆盖 list、dict、嵌套结构、tensor 的 flatten/unflatten 及 roundtrip 场景。 2. 新增测试文件 test/fx/test_guards_apis.py,为 torch._guards.active_fake_mode 补充用例,覆盖 FakeTensorMode 上下文内外、嵌套上下文等场景。 3. PyTorch 官方社区暂无针对以上三个 API 的直接用例覆盖(tree_flatten/tree_unflatten 社区用例均通过 torch.utils._pytree 导入验证,未直接验证 torch._functorch.vmap 下的别名;active_fake_mode 无社区用例),因此自行编写用例并提交到 test 目录。 4. 三个 API 均为纯 Python 实现(tree_flatten/tree_unflatten 是 torch.utils._pytree 的别名,active_fake_mode 为 torch._guards 模块内的上下文查询函数),不涉及 NPU 适配,不需要代码修改。 # 【资料变更】 不涉及。以上三个 API 均为 PyTorch 私有接口(torch._functorch、torch._guards),按规范私有接口不需要补充资料。 # 【接口变更】 不涉及。 # 【功能验证】 1. 测试方法:本地容器环境执行 pytest,命令如下: TORCH_DEVICE_BACKEND_AUTOLOAD=0 python3 -m pytest test/functorch/test_vmap_pytree_apis.py test/fx/test_guards_apis.py -v 2. 新增用例共 13 个(test_vmap_pytree_apis.py 8 个,test_guards_apis.py 5 个),已在 v2.7.1、v2.9.0、v2.10.0、v2.11.0、v2.12.0、master 六个版本全部验证通过(13 passed)。 3. 涉及张量创建的用例已适配 NPU 设备(通过 torch.accelerator.current_accelerator() 获取设备并迁移张量)。 4. 测试自验证截图: # 【测试用例设计说明】 1. test_tree_flatten_list:验证 tree_flatten 对列表结构的展开 2. test_tree_flatten_dict:验证 tree_flatten 对字典结构的展开 3. test_tree_flatten_nested:验证对嵌套结构的展开 4. test_tree_flatten_with_tensor:验证包含张量时的展开 5. test_tree_unflatten_list:验证 tree_unflatten 对列表的还原 6. test_tree_unflatten_dict:验证 tree_unflatten 对字典的还原 7. test_tree_flatten_unflatten_roundtrip:验证嵌套结构的完整往返 8. test_tree_flatten_unflatten_roundtrip_with_tensors:验证含张量的完整往返 test_active_fake_mode_returns_none_outside_context test_active_fake_mode_returns_mode_inside_context test_active_fake_mode_returns_none_after_context_exits test_active_fake_mode_nested_context test_active_fake_mode_with_fake_tensor # 【CheckList】 - [x] 代码注释完备,正确记录错误日志 - [x] 代码实现进行了返回值、空指针等校验 - [x] PR标题正确使用类型标签,如:feat、fix、refactor、docs、test等 - [x] PR持续集成流水线(CI)执行通过,代码检查无异常 See merge request: Ascend/pytorch!40724 | 19 天前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 8 天前 | ||
| 1 个月前 | ||
| 8 天前 | ||
| 8 天前 | ||
| 19 天前 |