已关闭
【API一致性任务】torch.UntypedStorage.untyped API一致性分析结论 #4049
Wo150创建于  25 天前关闭于  7 天前
Wo150
25 天前 创建

torch.UntypedStorage.untyped 一致性补齐说明

一、API 功能说明

适用版本:v2.7.1、v2.11.0、v2.12.0、master

当前状态: 有效。

可见性: 公开。UntypedStoragetorch/storage.py 顶部导出为 torch.UntypedStorageuntyped 是其公开实例方法(继承自 _StorageBase),社区测试与官方文档均按公开 API 对待。

硬件相关性:

  • 显式设备判断:目标方法定义于 torch/storage.py_StorageBase 基类(v2.7.1 第 414-415 行,v2.11.0/v2.12.0/master 第 416-417 行),UntypedStorage 通过 class UntypedStorage(torch._C.StorageBase, _StorageBase)(v2.7.1 第 462 行,v2.11.0/v2.12.0/master 第 467 行)继承该方法。方法体内没有任何 device.typeis_cudatorch.cuda、设备白名单、DispatchKey、后端模块名或 cpu/cuda/gpu/privateuse1/npu 常量判断,不存在 NPU/PrivateUse1 专用分支,也不存在将其他设备导向报错的拒绝分支。同文件相邻的 _new_shared 中存在 device.type in ["cuda", torch._C._get_privateuse1_backend_name(), "hpu"] 判断,但那是共享内存创建逻辑,不属于 untyped 的调用链。
  • 通用设备路径:调用接收者为任意 UntypedStorage 实例,其设备由存储分配时的设备决定,可来自 CPU 张量/存储,也可来自经 PrivateUse1 后端重命名后的 NPU 张量/存储。untyped 本身不读取、不分发设备参数,对任何设备的存储都返回同一对象引用;TorchNPU 注册 NPU 后端后,NPU 上的 UntypedStorage 走同一通用存储路径,untyped() 行为与 CPU 完全一致,即通过通用设备路径支持 NPU。
  • Tensor 计算:调用链不执行任何数值算子、归约、矩阵/卷积、随机生成、数据复制、存储分配或同步操作,不触发任何设备内核或设备运行时调用,仅返回 self 引用,不依赖 CPU、GPU 或 NPU 内核。
  • 纯 Python 判断:满足纯 Python 条件。整个方法体只有 return self 一行,属于 Python 控制流返回,不涉及设备分配、数据迁移、后端 Dispatcher 或设备运行时。

分硬件结论:

硬件 支持结论 直接理由
CPU 支持 纯 Python 返回自身引用,对 CPU 存储无任何设备限制
NPU 支持 方法与设备无关,NPU 存储经通用存储路径同样返回自身;TorchNPU 仓 test/npu/test_storage.py 已在 NPU 设备存储上调用并断言通过

API 功能: 无位置参数、无关键字参数。对任一 torch.UntypedStorage 实例调用 untyped() 返回该实例自身(self),用于在统一接口下获取底层的无类型存储视图:UntypedStorage 本身就是无类型存储,因此返回值与原对象是同一对象,s.untyped() is s 恒成立,devicenbytes()size()data_ptr() 等属性与原对象完全一致。该方法无错误分支与边界异常场景,任意设备、任意 dtype、零长度存储的行为均一致。需与同名方法区分:已弃用的 torch.TypedStorage.untyped()(v2.7.1 第 881-884 行,v2.11.0/v2.12.0 第 890-893 行,master 第 891-894 行)先发出弃用警告再返回内部 _untyped_storage,是另一个 API,不属于本 Issue 分析对象。

核心源码分析: 四个版本实现完全一致,仅定义行号存在 2 行偏移(v2.7.1 为 414-415 行,v2.11.0/v2.12.0/master 为 416-417 行):

# torch/storage.py
class _StorageBase:  # v2.7.1 第 41 行;v2.11.0/v2.12.0/master 第 41 行
    ...
    def untyped(self):  # v2.7.1 第 414-415 行;v2.11.0/v2.12.0/master 第 416-417 行
        return self

class UntypedStorage(torch._C.StorageBase, _StorageBase):  # v2.7.1 第 462 行;v2.11.0/v2.12.0/master 第 467 行
    ...

调用路径为纯 Python 属性查找:storage_obj.untyped() 命中 _StorageBase.untyped 后直接 return self,不经过 Dispatcher、不触发 C++ 扩展调用、不产生任何设备副作用。torch.Tensor.untyped_storage() 返回的 UntypedStorage 与直接构造的 torch.UntypedStorage(...) 使用同一实现,行为完全一致;TorchNPU 仓 test/npu/test_storage.pyTestStorage.test_storage_method 已对 npu_tensor.untyped_storage().untyped() 与 CPU 侧结果做一致性断言,佐证 NPU 路径可用。

二、PyTorch 社区测试用例情况

适用版本:v2.7.1、v2.11.0、v2.12.0、master

核验方式: 在 PyTorch 各目标 Git 引用的 test/ 目录下执行三类检索:完整限定名 UntypedStorage、短方法全量调用形态 .untyped( 与模块导入 from torch.storage import。候选发现由临时 Python 脚本批量执行与下述模板一致的命令并落盘退出码与命中行(脚本仅负责候选召回、去重与计数,不给出接受或排除结论),随后对全部 .untyped( 命中行使用 git show <ref>:test/... 阅读调用点局部上下文,逐个人工确认接收者类型后得出结论。所有命令均在 PyTorch 项目目录执行。

查找命令模板:

# 将命令中的具体版本引用替换为“版本号”
git grep -n -I -F -e 'UntypedStorage' refs/heads/版本号 -- 'test/*.py' 'test/**/*.py'
git grep -n -I -F -e '.untyped(' -e '.untyped (' refs/heads/版本号 -- 'test/*.py' 'test/**/*.py'
git grep -n -I -F -e 'from torch.storage import' refs/heads/版本号 -- 'test/*.py' 'test/**/*.py'
版本 执行结果
v2.7.1 三条命令退出码 0/0/1UntypedStorage 命中 37 处;.untyped( 命中 17 处(test/test_torch.py 15 处、test/test_serialization.py 2 处);from torch.storage import 0 处。17 处调用点人工复核后全部排除:test_torch.py:175/205/269/286 接收者为 Tensor.storage() 返回的 TypedStorage:315 位于 _check_storage_metaisinstance(s, torch.TypedStorage) 分支内;:7810/7828/7832/7835/7838/7841s_LegacyStorageTypedStorage 子类)实例;:8024/8054/8099/8111s0/s1torch.FloatStorage/torch.cuda.FloatStoragetest_serialization.py:857/889a.storage().untyped()。均调用 torch.TypedStorage.untyped,非本 API。
v2.11.0 三条命令退出码 0/0/1UntypedStorage 命中 38 处(新增 test/cpp_extensions/open_registration_extension/torch_openreg/tests/ 下 6 处 openreg 设备用例);.untyped( 命中 17 处(test/test_torch.py 15 处、test/test_serialization.py 2 处);from torch.storage import 0 处。17 处调用点结构与 v2.7.1 相同(行号偏移为 test_torch.py:179/212/290/308/337/7605/7623/7627/7630/7633/7636/7819/7849/7894/7906test_serialization.py:911/943),人工复核结论一致:全部为 TypedStorage 及其子类接收者,排除。
v2.12.0 三条命令退出码 0/0/1UntypedStorage 命中 38 处;.untyped( 命中 17 处(test/test_torch.py 15 处、test/test_serialization.py 2 处);from torch.storage import 0 处。17 处调用点(test_torch.py:132/165/243/261/290/7679/7697/7701/7704/7707/7710/7893/7923/7968/7980test_serialization.py:911/943)人工复核结论与 v2.7.1 一致:全部为 TypedStorage 及其子类接收者,排除。
master 三条命令退出码 0/0/0UntypedStorage 命中 41 处(较 v2.12.0 新增 test_mps.py:8970test_serialization.py:4968/4993 等);.untyped( 命中 17 处(test/test_torch.py 15 处、test/test_serialization.py 2 处);from torch.storage import 1 处(test_serialization.py:4964,导入 TypedStorage,与本 API 无关)。17 处调用点(test_torch.py:134/167/245/263/292/7803/7821/7825/7828/7831/7834/8017/8047/8092/8104test_serialization.py:911/943)人工复核结论与 v2.7.1 一致:全部为 TypedStorage 及其子类接收者,排除。

社区测试用例: 未找到任何测试用例文件。针对 torch.UntypedStorage.untyped() 的直接调用,四个目标引用的 test/ 目录均未命中:全量调用形态检索到的 17 处 .untyped() 经逐个人工复核,接收者全部是 TypedStorage 或其 _LegacyStorage 子类(如 torch.FloatStoragetorch.cuda.FloatStorage),属于另一个 API torch.TypedStorage.untyped 的用例;test_torch.pytest_untyped_storage_meta 等直接构造 torch.UntypedStorage 的用例只做 meta 属性断言,未调用 untyped()。无“无法确认”项:所有调用点的接收者均能从局部上下文(赋值来源、isinstance 分支、类定义)可靠回指。

覆盖结论: 无覆盖。 对照第一章功能场景逐项比较:核心行为(untyped() 返回自身、s.untyped() is s 恒成立)无用例;返回值属性一致性(device/nbytes()/size()/data_ptr() 与原对象一致)无用例;dtype 维度、设备维度(CPU 及 NPU)、零长度存储边界同样无用例。检索到的 .untyped() 调用均服务于 TypedStorage.untyped(取出内部无类型存储)的验证,不能视为本 API 的任何覆盖。TorchNPU 仓 test/npu/test_storage.py 在 NPU 设备存储上对该 API 有间接调用,属于 TorchNPU 自有用例,不计入 PyTorch 社区覆盖。

三、API 测试用例补齐及适配方案

适配方案所属版本:v2.7.1、v2.11.0、v2.12.0、master

用例完整性: 无覆盖。对照第一章功能场景逐项说明缺口:核心行为(返回自身、对象身份不变)无用例;返回值属性一致性断言无用例;dtype、设备(CPU/NPU)、零长度存储等边界场景均无用例。第二章检索到的 17 处 .untyped() 调用全部属于 torch.TypedStorage.untyped 的用例,不构成本 API 覆盖,四个目标引用结论一致。

是否需要NPU适配: 否。第一章硬件相关性判定表明该 API 为纯 Python 逻辑,不经过 Dispatcher、不触发设备内核或运行时,CPU 与 NPU 路径行为由同一份 Python 代码保证一致;第二章未发现社区用例需要设备解耦。TorchNPU 无需为其注册算子或补丁,API 源码与测试用例源代码均不需要修改。

是否纯Python且不涉及硬件: 是。与第一章纯 Python 判断一致:方法体只有 return self,不涉及设备分配、数据迁移、后端分发或运行时调用。

是否与硬件有关: 否。调用链不执行 Tensor/Storage 数据运算、设备分配、数据迁移、同步或后端分发,仅返回对象引用,与第一章、第二章硬件相关性结论一致。

适配方案: 按照规范,本 API 匹配 1.2-1 PyTorch社区无用例或覆盖不完整,纯Python且不涉及硬件。 处理方案:不新增测试文件、不提交 patch,仅提交本 Issue 说明社区用例缺口与纯 Python 依据,并提供快速验证命令(见第六章)作为运行证据或待验证项;后续若 PyTorch 社区为 UntypedStorage.untyped 补充官方用例,可在社区硬件解耦任务中一并跟踪,TorchNPU 侧无需新增任何适配代码。

仅提Issue理由: 该 API 为纯 Python 且与硬件无关,CPU 与 NPU 行为由同一份两行 Python 实现保证一致,不存在需要 NPU 适配、硬件解耦或源码修改的代码路径;按照 1.2-1 场景规范,仅交付 Issue 即满足要求,新增测试文件无必要性——社区用例缺口属于 PyTorch 上游测试职责,且 TorchNPU 仓 test/npu/test_storage.py 已有在 NPU 设备存储上间接调用该 API 并断言 CPU/NPU 一致性的既有用例可作旁证,因此仅提 Issue、不提交测试文件。

四、资料变更

适用版本:v2.7.1、v2.11.0、v2.12.0、v2.13.0

结论:涉及。

四个已配置资料版本在 TorchNPU master 分支 docs/zh/api/native_api 对应目录下均已记录 torch.UntypedStorage.untyped(位于 torch-Storage.mdtorch.UntypedStorage 章节内,untyped() 小节标注支持 Atlas A2/A3 训练系列产品),本地已有记录,但是文档标注不支持A5服务器,因此需要调整

文档路径:行号范围:

API版本 文档路径 行号范围
v2.7.1 docs/zh/api/native_api/pytorch_2-7-1/torch-Storage.md 721-737
v2.11.0 docs/zh/api/native_api/pytorch_2-11-0/torch-Storage.md 721-737
v2.12.0 docs/zh/api/native_api/pytorch_2-12-0/torch-Storage.md 721-737
v2.13.0 docs/zh/api/native_api/pytorch_2-13-0/torch-Storage.md 721-737

五、接口变更

适用版本:v2.7.1、v2.11.0、v2.12.0、master

结论:不涉及。

依据第一章 API 功能源码分析:torch.UntypedStorage.untyped 在四个目标 PyTorch 版本中的实现均为 _StorageBase 中的两行纯 Python 代码(def untyped(self): return self),无 native 算子注册、无 Dispatcher 依赖、无 TorchNPU 侧补丁或后端注册需求,客户可见行为在各版本间完全一致,不需要任何接口变更。该 API 属于按照 1.2-1 场景处理的纯 Python 接口,不新增 patch、仅提交 Issue 说明,后续如需跟踪实现变化,由 PyTorch 社区用例硬件解耦任务统一承接,TorchNPU 无需修改 torch/torch_npu/ 源码。

六、功能验证

执行命令:

python - <<'PY'
import torch
from torch.testing._internal.common_utils import TestCase, run_tests


device_type = acc.type if (acc := torch.accelerator.current_accelerator()) else "cpu"


class TestUntypedStorageUntyped(TestCase):

    def test_untyped_returns_self_for_storage_sizes(self):
        for size in (0, 1, 16):
            storage = torch.UntypedStorage(size, device=device_type)
            result = storage.untyped()

            self.assertIs(result, storage)
            self.assertEqual(result.nbytes(), size)
            self.assertEqual(result.device.type, device_type)

    def test_untyped_returns_tensor_storage(self):
        tensor = torch.arange(8, dtype=torch.float32).to(device_type)
        storage = tensor.untyped_storage()
        result = storage.untyped()

        self.assertIs(result, storage)
        self.assertEqual(result.data_ptr(), storage.data_ptr())
        self.assertEqual(result.nbytes(), tensor.numel() * tensor.element_size())

    def test_untyped_repeated_calls_return_self(self):
        storage = torch.UntypedStorage(8, device=device_type)

        self.assertIs(storage.untyped().untyped(), storage)

    def test_untyped_invalid_arguments(self):
        storage = torch.UntypedStorage(4, device=device_type)

        with self.assertRaises(TypeError):
            storage.untyped(None)
        with self.assertRaises(TypeError):
            storage.untyped(value=None)


if __name__ == "__main__":
    run_tests()
PY

结果

v2.7.1:

[W816 02:34:37.445298018 NPUCachingAllocator.cpp:198] Warning: The current CANN and Soc Version require processing for 32 padding size, with memory allocation. (function operator())
....
----------------------------------------------------------------------
Ran 4 tests in 1.149s

OK

v2.11.0:

[W816 02:36:57.557054972 NPUCachingAllocator.cpp:201] Warning: The current CANN and Soc versions require processing for 32 padding size, with memory allocation. (function operator())
....
----------------------------------------------------------------------
Ran 4 tests in 1.158s

OK

v2.12.0:

[W816 02:37:57.608532553 NPUCachingAllocator.cpp:201] Warning: The current CANN and Soc versions require processing for 32 padding size, with memory allocation. (function operator())
....
----------------------------------------------------------------------
Ran 4 tests in 1.155s

OK

master:

[W817 12:28:47.665508510 NPUCachingAllocator.cpp:201] Warning: The current CANN and Soc versions require processing for 32 padding size, with memory allocation. (function operator())
....
----------------------------------------------------------------------
Ran 4 tests in 0.872s

OK

以下是A5服务器验证结果
获取芯片型号命令:

python3 -c "import acl;print(acl.get_soc_name())"

执行结果:

Ascend950PR_9579

参考截图:
image.png

v2.7.1:

[W901 10:58:37.061107208 NPUCachingAllocator.cpp:198] Warning: The current CANN and Soc Version require processing for 32 padding size, with memory allocation. (function operator())
....
----------------------------------------------------------------------
Ran 4 tests in 1.667s

OK

v2.11.0:

[W901 10:59:35.434079795 NPUCachingAllocator.cpp:201] Warning: The current CANN and Soc versions require processing for 32 padding size, with memory allocation. (function operator())
....
----------------------------------------------------------------------
Ran 4 tests in 1.773s

OK

v2.12.0:

[W901 11:00:06.680600785 NPUCachingAllocator.cpp:201] Warning: The current CANN and Soc versions require processing for 32 padding size, with memory allocation. (function operator())
....
----------------------------------------------------------------------
Ran 4 tests in 1.676s

OK

master:

[W901 11:00:32.589735042 NPUCachingAllocator.cpp:201] Warning: The current CANN and Soc versions require processing for 32 padding size, with memory allocation. (function operator())
....
----------------------------------------------------------------------
Ran 4 tests in 1.586s

OK
likedislike
WWo150
25 天前 关联了看板:FrameworkPTAdapter 版本issue看板
WWo150
24 天前 修改了issue 的描述
WWo150
24 天前 修改了issue 的描述
WWo150
24 天前 修改了issue 的描述
WWo150
24 天前 修改了issue 的描述
TorchNPU-BotTorchNPU-Bot成员
23 天前 添加了label:help-wantedevent: api-consistencybot-triaged
TorchNPU-Bot
TorchNPU-Bot成员
23 天前 评论:

检测到社区任务相关 issue,自动添加标签:event: api-consistencyhelp-wanted

likedislike
WWo150
23 天前 修改了issue 的描述
WWo150
23 天前 修改了issue 的描述
WWo150
23 天前 修改了issue 的描述
WWo150
22 天前 修改标题为 “【API一致性任务】torch.UntypedStorage.untyped API一致性分析结论”,原标题为“torch.UntypedStorage.untyped API一致性分析结论”
群青世界成员
9 天前 评论:

社区任务交付件初审结论:✔

1. API 功能说明

  • API 语义torch.UntypedStorage.untyped() 是一个恒等方法,直接返回调用者自身(return self)。
  • 设备约束:该方法为纯 Python 实现,不涉及任何硬件特定逻辑、算子调度或内存分配,因此与设备类型(CPU/CUDA/NPU)完全解耦。
  • TorchNPU 适配状态:TorchNPU 未覆盖此方法,NPU 存储对象直接沿用 PyTorch 共享基类的实现,语义保持一致。

2. 测试覆盖情况

  • 上游覆盖:PyTorch 官方社区测试中未找到针对 UntypedStorage.untyped() 的直接测试用例(现有测试多针对 TypedStorage)。
  • 自定义验证:已补充针对 UntypedStorage 的自定义测试用例,覆盖以下场景:
    • 不同 Size 的存储对象(0, 1, 16);
    • 从 Tensor 获取的 UntypedStorage;
    • 链式调用(Repeated Calls);
    • 非法参数检查(Invalid Arguments)。

3. 多版本兼容性验证结果

在以下环境执行自定义测试用例,结果均通过:

  • 环境 1:PyTorch 2.7.1 + torch-npu 2.7.1
  • 环境 2:PyTorch 2.11.0 + torch-npu 2.11.0
  • 环境 3:PyTorch 2.12.0 + torch-npu 2.12.0
  • 环境 4:PyTorch Master (2.12.0 dev) + torch-npu 2.12.0

验证结论

  • 全部通过:所有版本的 Ran 4 tests ... OK
  • 警告说明
    • NPUCachingAllocator.cpp 关于 32 padding size 的警告为 NPU 内存分配器正常行为提示,不影响测试功能。
    • CuTeDSL 依赖缺失警告仅出现在 v2.12.0+ 环境中,属于 NVIDIA 相关可选依赖缺失,与 NPU 测试无关,不影响断言结果。
  • 行为一致性:NPU 环境下 untyped() 返回对象与 self 同一标识,且设备属性正确保留,与预期完全一致。

4. 资料与交付方式

  • 文档处理:TorchNPU 原生 API 文档已包含该接口入口,且无 NPU 专用差异,无需修改文档。
  • 代码修改:无需新增 TorchNPU 测试文件、Patch 或适配代码。
  • 交付方式:基于验证通过且无代码变更需求,以 Issue-only 方式交付验证结论。

5. 最终验收结论

  • 功能验证:PASSED
  • NPU 适配:无硬件特有语义,行为与 CPU/CUDA 一致。
  • 实现差异:无(沿用 PyTorch 共享实现)。
  • 后续行动:无需提交 Issue 进行 Bug 跟踪或功能申请,验证闭环完成。
likedislike
WWo150
9 天前 修改了issue 的描述
WWo150
9 天前 修改了issue 的描述
WWo150
8 天前 修改了issue 的描述
WWo150
8 天前 修改了issue 的描述
linhan37
7 天前 评论:

审核结论:该API属于纯python接口,无需修改TorchNPU代码。该任务已按照要求提供分析验证结论和交付件,同意关闭。

likedislike
群青世界成员
7 天前 issue状态由 TODO 改变为 DONE
群青世界成员
7 天前 关闭了 issue
ascend-robotascend-robot成员
7 天前 添加了label:resolved
WWo150
3 天前 关联了pull request:docs:Complete the documentation for the three APIs: torch.UntypedStorage.to, torch.UntypedStorage.untyped, torch.distributed.tensor.DTensor.placements