已关闭
[Usage]: API一致性说明:torch.fx.experimental.symbolic_shapes.DimConstraints.solve 与 torch.fx.experimental.symbolic_shapes.DimDynamic 在 NPU 环境无需额外适配 #2431
Goko创建于  6月18日关闭于  7月7日
Goko
Goko
6月18日 创建

在提交新问题之前,请确保您已经在社区中搜索过相关问题,并使用了社区中提供的资源/工具后,仍未找到满意的解决方式。

环境信息

操作系统:Linux aarch64(openEuler 22.03 SP4 内核环境)
昇腾硬件信息:Ascend910_9382
Python:3.12.13
torch:2.10.0+cpu
torch_npu:2.10.0
torch.npu.is_available():True

使用场景及问题

一、验证环境

/workspace/user_data/venvs/torch-npu-py312

公开任务:

https://gitcode.com/Ascend/pytorch/issues/1613

本说明不包含内部需求链接、内部问题单或其他非公开流程信息。

二、本说明覆盖范围

本任务涉及以下 5 个 API:

torch.fx.experimental.symbolic_shapes.DimConstraints.forced_specializations
torch.fx.experimental.symbolic_shapes.DimConstraints.prettify_results
torch.fx.experimental.symbolic_shapes.DimConstraints.rewrite_with_congruences
torch.fx.experimental.symbolic_shapes.DimConstraints.solve
torch.fx.experimental.symbolic_shapes.DimDynamic

其中,符合“PyTorch upstream 已有直接使用,且无需 NPU 专用用例适配 patch”的 API 为:

torch.fx.experimental.symbolic_shapes.DimConstraints.solve
torch.fx.experimental.symbolic_shapes.DimDynamic

两者的最终处理方式不同:

  1. DimConstraints.solve 的 upstream 直接用例无需 NPU 迁移,不生成 test_upstream patch;为了在 Torch-NPU API 测试文件中形成聚焦、稳定的直接看护,本任务仍新增了轻量自写 UT。
  2. DimDynamic 在 PyTorch upstream 和 Torch-NPU 现有测试中均已有直接覆盖,因此不生成 test_upstream patch,也不重复新增独立 UT。

其余三个 DimConstraints 方法在 upstream 中未发现目标方法的直接调用,已通过配套测试 PR 新增自写 UT,不属于本说明中的“无需新增用例适配”范围。

三、API 功能说明

1. DimConstraints.solve

API:

torch.fx.experimental.symbolic_shapes.DimConstraints.solve

功能:

DimConstraints.solve 用于汇总已添加的符号等式、不等式、替换关系和 congruence 信息,执行符号约束求解,并将结论分类写入静态结果、动态结果、替换关系等内部集合。

该方法主要处理:

SymPy 符号与表达式
Source 元信息
符号变量的 hint 值
等式与不等式约束
静态特化与动态约束结果

它属于 FX / Dynamo symbolic shapes 的 Python 层编译前端逻辑,不直接执行 Tensor 数值计算,不调用 NPU 算子或 kernel,也不涉及 NPU 内存、stream、event 或通信逻辑。

各目标版本中的方法签名均为:

DimConstraints.solve(self) -> None

2. DimDynamic

API:

torch.fx.experimental.symbolic_shapes.DimDynamic

功能:

DimDynamic 是 symbolic shapes 使用的枚举类型,用于描述符号维度采用的动态策略。当前验证环境中包含:

DimDynamic.DYNAMIC
DimDynamic.DUCK
DimDynamic.STATIC
DimDynamic.SIZE_LIKE_UNBACKED
DimDynamic.INFER_STRIDE
DimDynamic.OBLIVIOUS_SIZE

这些枚举值供 StatelessSymbolicContextStatefulSymbolicContext 等符号上下文决定尺寸和步长的动态性。该 API 本身只提供 Python 枚举语义,不创建 Tensor,不执行设备计算,也不包含 NPU 专用逻辑。

四、PyTorch upstream 源码存在性检查

使用 Gitee PyTorch 官方镜像,在以下版本中检查:

/workspace/user_data/pytorch_official_versions/pytorch-v2.7.1
/workspace/user_data/pytorch_official_versions/pytorch-v2.9.0
/workspace/user_data/pytorch_official_versions/pytorch-v2.10.0
/workspace/user_data/pytorch_official_versions/pytorch-v2.11.0
/workspace/user_data/pytorch_official_versions/pytorch-v2.12.0

目标源码文件:

torch/fx/experimental/symbolic_shapes.py

各版本均检索到:

class DimDynamic(Enum)
class DimConstraints
def solve(self) -> None

源码位置复查结果:

v2.7.1:  DimDynamic 1512, DimConstraints 2361, solve 2627
v2.9.0:  DimDynamic 1762, DimConstraints 2791, solve 3061
v2.10.0: DimDynamic 1844, DimConstraints 2888, solve 3164
v2.11.0: DimDynamic 1899, DimConstraints 2938, solve 3217
v2.12.0: DimDynamic 1938, DimConstraints 2990, solve 3269

因此,这两个 API 在任务覆盖的 PyTorch 官方版本中均为已有原生接口,不需要在 Torch-NPU 中新增同名实现。

五、PyTorch upstream 测试覆盖情况

1. DimConstraints.solve

对各版本官方测试执行直接调用检索:

grep -rn "dim_constraints\.solve()" test --include="*.py"

各版本均在 test/test_dynamic_shapes.py 中存在直接调用:

v2.7.1:  test/test_dynamic_shapes.py:2765
v2.9.0:  test/test_dynamic_shapes.py:2900
v2.10.0: test/test_dynamic_shapes.py:3028
v2.11.0: test/test_dynamic_shapes.py:3040
v2.12.0: test/test_dynamic_shapes.py:3170

已进一步查看 v2.7.1 对应调用上下文。该用例构造:

SymPy 表达式
DimConstraints
TensorPropertySource / LocalSource 等 Source 元信息

并断言:

dim_constraints._static_results
dim_constraints._dynamic_results

对该上下文进行设备和 Tensor 创建关键字检查,未发现:

.cuda()
.npu()
.to(device)
device=
torch.randn
torch.ones
torch.zeros
torch.tensor
NPU 算子或 CPU/NPU 精度比较

因此,upstream 中的 DimConstraints.solve 直接调用不需要将 CPU Tensor 迁移到 NPU,也没有需要修改为 NPU 专用逻辑的代码。

2. DimDynamic

对各版本官方测试执行直接使用检索:

grep -rn "DimDynamic\." test --include="*.py"

直接命中数量:

v2.7.1:  38
v2.9.0:  43
v2.10.0: 43
v2.11.0: 43
v2.12.0: 45

相关使用分布在 dynamic shapes、Dynamo、export、symbolic context 等测试场景中。其核心行为是把 DimDynamic.DUCKDimDynamic.INFER_STRIDE 等枚举值传入符号上下文,用于描述尺寸和步长的动态策略。

DimDynamic 本身不是设备计算接口。其枚举值不会触发 CUDA/NPU Tensor 创建、设备迁移或数值计算,因此不存在将该枚举“适配到 NPU”的实现改写点。

六、Torch-NPU 已有测试、patch 与资料复查

复查分支:

upstream/master
upstream/v2.7.1
upstream/v2.9.0
upstream/v2.10.0
upstream/v2.11.0
upstream/v2.12.0

v2.8.0 已结束维护,不纳入本任务。

复查路径:

test
test_upstream
docs/zh/native_apis

1. DimConstraints.solve

复查时各目标分支的有效命中计数为:

test=0
test_upstream=0
docs=0

粗检索曾在 test/unsupported_test_cases/.pytorch-disabled-tests*.json 中命中 test_dim_constraints_solve_full,但该内容只是禁用记录,并非测试实现。最终复查已排除 disabled JSON,避免把测试名称误判为已有覆盖。

因此:

  1. 没有已有 DimConstraints.solve patch 需要修改;
  2. upstream 直接调用无需设备迁移,不需要新增 test_upstream patch;
  3. 为形成聚焦看护,本任务在 test/fx/test_symbolic_shapes_api.py 中新增轻量自写测试。

新增测试:

test_dim_constraints_solve_records_dynamic_results

该方法还会在 forced_specializationsprettify_results 测试中被调用,因此在四个新增测试中的实际调用次数为 3 次,覆盖动态约束结果与静态特化相关路径。

2. DimDynamic

各目标分支复查结果:

test > 0
test_upstream=0
docs=0

具体 test 命中计数:

upstream/master:  15
upstream/v2.7.1:  20
upstream/v2.9.0:  20
upstream/v2.10.0: 20
upstream/v2.11.0: 20
upstream/v2.12.0: 20

命中主要来自:

test/dynamo/test_export.py
test/dynamo/test_subclasses.py
test/fx/experimental/test_symbolic_shapes.py
test/fx/test_symbolic_shapes_api.py
test/fx/test_unspecified_symbols.py

其中,test/fx/test_symbolic_shapes_api.py 已有以下直接测试:

test_stateless_symbolic_context
test_stateful_symbolic_context

这些测试直接使用:

symbolic_shapes.DimDynamic.DUCK
symbolic_shapes.DimDynamic.INFER_STRIDE

因此 DimDynamic 已满足 Torch-NPU 侧基础直接看护需求。新增同类枚举测试只会重复已有覆盖,没有必要。

七、API 源码设备依赖分析

1. DimConstraints.solve

solve 的输入和内部状态由符号变量、SymPy 表达式、Source 元信息、替换关系及约束集合组成。其输出通过更新约束对象内部集合体现,不返回设备 Tensor。

源码实现和直接测试上下文中均未发现:

torch_npu
npu
cuda
xpu
device
.to(
.npu(
.cuda(

因此该方法不需要 API 功能层面的 NPU 分支实现,也不需要 CPU/NPU 数值精度对比。

2. DimDynamic

DimDynamic 是 Python Enum。枚举成员本身不包含设备分发、Tensor 运算或 NPU 状态,不存在 kernel、精度、dtype、layout、stream 或内存相关适配逻辑。

因此,该 API 不需要修改 Torch-NPU 产品源码。

八、当前环境最小行为验证

验证环境:

torch: 2.10.0+cpu
torch_npu: 2.10.0
torch.npu.is_available(): True

1. DimDynamic

执行枚举检查后得到:

DimDynamic.DYNAMIC
DimDynamic.DUCK
DimDynamic.STATIC
DimDynamic.SIZE_LIKE_UNBACKED
DimDynamic.INFER_STRIDE
DimDynamic.OBLIVIOUS_SIZE

说明当前 Torch-NPU 环境可以正常导入并枚举 DimDynamic

2. DimConstraints.solve

构造简单约束:

constraints.add(s0 >= 2)
constraints.solve()

求解后得到动态约束结果:

2 <= x

配套测试断言:

self.assertEqual(constraints._static_results, set())
self.assertEqual(constraints._dynamic_results, {"2 <= x"})

说明当前 Torch-NPU 环境可以正常构造、调用 DimConstraints.solve,结果与 PyTorch 预期一致。

九、NPU 适配判断

基于源码、upstream 测试、Torch-NPU 仓库和当前运行环境的多轮复查,判断如下。

1. DimConstraints.solve

  1. PyTorch v2.7.1、v2.9.0、v2.10.0、v2.11.0、v2.12.0 中均存在该 API;
  2. 各版本 upstream 测试均存在 dim_constraints.solve() 直接调用;
  3. 直接调用上下文只处理 SymPy、DimConstraints 和 Source 元信息;
  4. 未发现设备迁移、NPU 算子或 CPU/NPU 精度比较;
  5. Torch-NPU 中没有已有有效 patch 需要修改;
  6. 当前环境行为验证通过;
  7. 不需要新增 test_upstream NPU patch;
  8. 不需要修改 API 产品源码;
  9. 已通过轻量自写 UT 补充聚焦、稳定的 Torch-NPU 侧看护。

2. DimDynamic

  1. 所有目标 PyTorch 版本均存在该枚举;
  2. upstream 测试中存在大量 DimDynamic.* 直接使用;
  3. Torch-NPU 现有测试已直接使用 DUCKINFER_STRIDE
  4. 该 API 是设备无关的 Python 枚举,不涉及 Tensor 计算;
  5. 当前环境枚举验证通过;
  6. 不需要新增 test_upstream patch;
  7. 不需要修改 API 产品源码;
  8. 不需要重复新增独立 UT。

十、其他三个 API 的处理边界

以下三个方法虽然同样不需要修改产品源码,但 upstream 未发现目标方法的直接调用,因此不能按“已有 upstream 用例,issue 说明即可”的路线处理:

torch.fx.experimental.symbolic_shapes.DimConstraints.forced_specializations
torch.fx.experimental.symbolic_shapes.DimConstraints.prettify_results
torch.fx.experimental.symbolic_shapes.DimConstraints.rewrite_with_congruences

本任务已在 test/fx/test_symbolic_shapes_api.py 中分别新增直接测试:

test_dim_constraints_forced_specializations_reports_marked_dynamic_equalities
test_dim_constraints_prettify_results_reports_forced_specialization
test_dim_constraints_rewrite_with_congruences_records_mod_guard

因此,本说明不会把这三个方法误写为“无需新增测试处理”。

十一、相关交付 PR

测试 PR:

master:  https://gitcode.com/Ascend/pytorch/pull/38822
v2.7.1:  https://gitcode.com/Ascend/pytorch/pull/38823
v2.9.0:  https://gitcode.com/Ascend/pytorch/pull/38824
v2.10.0: https://gitcode.com/Ascend/pytorch/pull/38825
v2.11.0: https://gitcode.com/Ascend/pytorch/pull/38826
v2.12.0: https://gitcode.com/Ascend/pytorch/pull/38827

资料 PR:

v2.7.1: https://gitcode.com/Ascend/pytorch/pull/38848

上述 6 个测试 PR 和 1 个资料 PR 的 CI 均已通过。

十二、处理结论

DimConstraints.solve

  1. 不新增 test_upstream patch;
  2. 不修改 API 源码实现;
  3. 不进行 CPU/NPU 数值精度对比;
  4. 使用配套测试 PR 中的轻量直接 UT 进行持续看护;
  5. 在 issue 中说明 upstream 直接调用无需 NPU 专用适配。

DimDynamic

  1. 不新增 test_upstream patch;
  2. 不新增重复的 Torch-NPU 自写测试;
  3. 不修改 API 源码实现;
  4. 不进行 CPU/NPU 数值精度对比;
  5. 复用 upstream 与 Torch-NPU 现有直接测试覆盖;
  6. 在 issue 中说明无需 NPU 专用适配。

综上,DimConstraints.solveDimDynamic 均不需要 NPU 专用 API 实现或 upstream 用例 patch;其中 solve 已通过轻量自写 UT 补充聚焦看护,DimDynamic 则直接复用现有测试覆盖。

欢迎加入社区,感谢您对社区的贡献 🎉!

likedislike
ascend-robotascend-robot成员
6月18日 添加了label:usage
GokoGoko
7月7日 issue状态由 TODO 改变为 DONE
GokoGoko
7月7日 关闭了 issue
ascend-robotascend-robot成员
7月7日 添加了label:resolved