Closed
[Bug-Report|缺陷反馈]: 读取 LIST_DATA_TYPE 属性返回普通整数,无法作为 DataType 列表回写 #637
廖氏如神Add on  Oct 3Closed at  15 days ago
廖氏如神
廖氏如神
Oct 3 Create

问题描述与影响

原生 GetListDataType 返回的 ctypes int 缓冲直接变成 Python int 列表;set_list_data_type(get_list_data_type()) 抛 TypeError,元素没有 DataType.name。

影响:Node/Graph/Operator 属性读回后不能按类型列表再写入或使用枚举名称;不同于上一批写入分派错误。

基线 cann/ge:develop,提交 ba12e592e8f84bc59709464bd3ad6ca010498d8b。任务直接从刷新后的上游建立。

环境与复现

本地 Windows / Python 3.12.14;测试执行实际生产 Python 实现。实际 enum 类、ctypes 缓冲区和 Python getter/setter/Shape/TensorDesc;只在 graph C API 边界使用局部替身。未验证真实 ABI 或设备,未分配巨大张量。

  1. 使用未修复基线,并仅加入本 PR 对应回归文件,保留原生产实现。
  2. 从仓库根运行下面的测试命令;回归给出实际断言失败。
  3. 应用修复后运行同一用例,并核对正常路径控制项。

触发示例/数据说明(完整构造与边界隔离见回归文件):

# 原生 getter 返回 VT_LIST_DATA_TYPE,buffer 含 DT_FLOAT16、DT_INT32 的 enum number。
# 实际 _AttrValue.get_list_data_type() 原版返回 list[int];
# 再传 set_list_data_type() 因元素不是 DataType 抛 TypeError。
# 预期读回 list[DataType] 并支持该类型保持的写回。
python -m pytest -q -p no:cacheprovider tests/ge/ut/ge/graph/pyge_tests/attr_datatype_readback_cpu_test.py

预期行为

数据类型列表读取返回 DataType 枚举;可通过已有 set_list_data_type 回写,普通 int/float/bool 列表语义不变。

根因与修改范围

实现 api/python/ge/ge/graph/_attr.py。

共用 list getter 没有按 VT_LIST_DATA_TYPE 将原生枚举数字恢复为 Python DataType,标量 getter 已执行此转换。

仅在 LIST_DATA_TYPE 分支转换每项为 DataType,仍在 finally 释放原生数组。

验证证据

5 项:原生列表读回实际 DataType 枚举并可写回;普通 int/float/bool 列表保持原类型;非法枚举转换失败仍释放原生缓冲区。

同一最终回归在未修复生产实现:2 failed, 3 passed in 0.10s;应用修复:5 passed in 0.06s。依赖/收集失败没有计作缺陷复现。

本地组合验证:26 passed in 0.18s;组合对象:!5294: DataType write dispatch。未验证真实 CANN/NPU、全量 C++ UT/ST。远端完整 CI 以当前 PR 提交对应 run 的实际终态为准,本地通过不代表远端门禁通过。

等级建议、重复核查与关联

建议 L2,依据上述实际功能影响提出,最终请维护者/SIG 评定,不预先认定活动奖励等级。

核查全部作者、全部状态 Issue/PR 的标题正文,并读取涉及四个仓库的 443 个开放 PR 实际文件差异。!5294 处理通用 set_attr 对 DataType 列表的写入分派;本项修复 list getter 的读回类型,触发入口和根因不同,已组合验证。

修复 PR:https://gitcode.com/cann/ge/pull/5298,目标 develop。

AI 辅助说明

由 Codex 辅助源码核查、最小复现、修复、回归及文案整理;所有本地结果来自执行记录。未声称人工复核、真实设备或远端 CI 已通过。

likedislike
廖氏如神廖氏如神
Oct 3 Added label: bug-report
廖氏如神廖氏如神
Oct 3 Associated pull request
廖氏如神廖氏如神
Oct 3 Modify description of issue
廖氏如神
廖氏如神
Oct 3 Comments:

/assign

likedislike
CANN-robotCANN-robotCollaborators
Oct 3 Assign gcw_Z57idahf as responsible person
KKenChowCollaborators
23 days ago Assign m0_50621083 as responsible person, remove original responsible person: gcw_Z57idahf
洪跃城
洪跃城Collaborators
22 days ago Comments:

已收到您的反馈,我们将会核实,请关注issue状态。

likedislike
洪跃城
洪跃城Collaborators
17 days ago Comments:

感谢反馈,也感谢附上完整的根因分析、最小复现和回归数据。

我们在包含基线提交 ba12e59 的 master 只读工作树上逐点核对了报告中的论断,问题属实:这是 GE Python API 层的缺陷——_AttrValue 的共用列表 getter 没有对 VT_LIST_DATA_TYPE 做枚举还原,与标量 getter 以及仓内已声明的类型契约都不一致,责任在 GE 侧。

核对确认点

  • 共用列表 getter 直接返回 ctypes 数组元素,没有任何逐项类型转换:_create_list_getter [main/ge/api/python/ge/ge/graph/_attr.py:150]
  • get_list_data_type 由该工厂生成,C 侧 restype 声明为 POINTER(c_int32),因此元素是裸 Python int:[main/ge/api/python/ge/ge/graph/_attr.py:529-534]、[main/ge/api/python/ge/ge/_capi/pygraph_wrapper.py:98]
  • 标量路径已做还原(return DataType(value.value)),标量与列表确实不对称:_AttrValue::get_data_type [main/ge/api/python/ge/ge/graph/_attr.py:468]
  • 回写侧校验元素必须是 DataType,否则抛 TypeError: All values must be DataTypes,所以 set_list_data_type(get_list_data_type()) 必然失败:_validate_list_input [main/ge/api/python/ge/ge/graph/_attr.py:80-81]、[main/ge/api/python/ge/ge/graph/_attr.py:522-527]
  • 仓内对同一属性声明的类型契约本来就是 List[DataType]:[main/ge/api/python/ge/ge/custom_op/_signature.py:50];custom op 的原生 pybind 读路径也确实返回 DataType 枚举对象:BuildDataTypeList [main/ge/api/python/ge/ge/custom_op/native_bindings/runtime_attrs_binding.h:55-65]。也就是说 ctypes 这条路是唯一不一致的一条,报告"标量已转换、列表未转换"的判断准确。

影响面与报告一致:Node / Graph / Operator 的 get_attr 都经 get_value() 分派到该 getter [main/ge/api/python/ge/ge/graph/_attr.py:266-267]、[main/ge/api/python/ge/ge/graph/node.py:218]、[main/ge/api/python/ge/ge/graph/operator.py:102]、[main/ge/api/python/ge/ge/graph/graph.py:231],因此任何 VT_LIST_DATA_TYPE 属性读回都是 list[int],元素拿不到 .name。

我们补充核对到的三点

后续评估都由维护方承担,这里先同步结论,便于你判断是否需要调整 PR:

  1. 现有 UT 掩盖了该缺陷。attr_test.py 的断言是 get_list_data_type() == test_data_type_list [main/ge/tests/ge/ut/ge/graph/pyge_tests/attr_test.py:146-147],而 DataType 继承 IntEnum [main/ge/api/python/ge/ge/graph/types.py:15],[1, 3] == [DataType.DT_FLOAT16, DataType.DT_INT32] 在 Python 中成立,所以"值相等"断言无法暴露类型不对称。回归用例最好直接断言元素类型(isinstance(v, DataType) 或 v.name),我们评审 !5298 时会按这个口径看。
  2. 转换后的异常语义会变化。改为 DataType(x) 之后,若原生侧返回 Python 枚举中不存在的编号会抛 ValueError(当前 Python 枚举上界是 DT_MAX = 44 [main/ge/api/python/ge/ge/graph/types.py:62]),而原实现返回裸 int 不报错。你列的"非法枚举转换失败仍释放原生缓冲区"正好覆盖了资源侧;向前兼容口径由我们在评审时定。
  3. 与 !5294 互补,不重叠。set_value 的列表分派中 int 分支排在 DataType 分支之前 [main/ge/api/python/ge/ge/graph/_attr.py:297-300],而 IntEnum 同时是 int,所以 set_value([DataType...]) 会落到 set_list_int——这正是 !5294 的范围。两者都合入后 set_value(get_value()) 才能完整往返,报告把两项区分开是准确的。

后续

!5298 我们已看到。改动影响性、回归验证范围、以及是否需要与 !5294 协调合入顺序,由维护团队统一评估。返回类型从 list[int] 变为 list[DataType] 属用户可见变更:IntEnum 的值比较、isinstance(v, int)、JSON 序列化行为都不变,只有 type(v) is int 这类严格类型判断会受影响;是否需要同步更新 docs/ 下 ge_python 模块说明,也由我们一并处理。有进展会在本 issue 更新。

再次感谢这份带源码定位和回归证据的报告。

likedislike
CANN-robotCANN-robotCollaborators
15 days ago Close issue
CANN-robotCANN-robotCollaborators
15 days ago Added label: resolved