已关闭
【API一致性任务】torch.UntypedStorage.untyped API一致性分析结论 #4049
Wo150创建于 25 天前关闭于 7 天前
23 天前 添加了label:help-wantedevent: api-consistencybot-triaged
TorchNPU-Bot
23 天前 评论:
23 天前 评论:
检测到社区任务相关 issue,自动添加标签:event: api-consistency、help-wanted


群青世界
9 天前 评论:
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 跟踪或功能申请,验证闭环完成。


7 天前 添加了label:resolved
3 天前 关联了pull request:docs:Complete the documentation for the three APIs: torch.UntypedStorage.to, torch.UntypedStorage.untyped, torch.distributed.tensor.DTensor.placements
torch.UntypedStorage.untyped 一致性补齐说明
一、API 功能说明
适用版本:v2.7.1、v2.11.0、v2.12.0、master
当前状态: 有效。
可见性: 公开。
UntypedStorage由torch/storage.py顶部导出为torch.UntypedStorage,untyped是其公开实例方法(继承自_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.type、is_cuda、torch.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。self引用,不依赖 CPU、GPU 或 NPU 内核。return self一行,属于 Python 控制流返回,不涉及设备分配、数据迁移、后端 Dispatcher 或设备运行时。分硬件结论:
API 功能: 无位置参数、无关键字参数。对任一
torch.UntypedStorage实例调用untyped()返回该实例自身(self),用于在统一接口下获取底层的无类型存储视图:UntypedStorage本身就是无类型存储,因此返回值与原对象是同一对象,s.untyped() is s恒成立,device、nbytes()、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.py的TestStorage.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.10/0/1:UntypedStorage命中 37 处;.untyped(命中 17 处(test/test_torch.py15 处、test/test_serialization.py2 处);from torch.storage import0 处。17 处调用点人工复核后全部排除:test_torch.py:175/205/269/286接收者为Tensor.storage()返回的TypedStorage;:315位于_check_storage_meta的isinstance(s, torch.TypedStorage)分支内;:7810/7828/7832/7835/7838/7841的s为_LegacyStorage(TypedStorage子类)实例;:8024/8054/8099/8111的s0/s1为torch.FloatStorage/torch.cuda.FloatStorage;test_serialization.py:857/889为a.storage().untyped()。均调用torch.TypedStorage.untyped,非本 API。v2.11.00/0/1:UntypedStorage命中 38 处(新增test/cpp_extensions/open_registration_extension/torch_openreg/tests/下 6 处 openreg 设备用例);.untyped(命中 17 处(test/test_torch.py15 处、test/test_serialization.py2 处);from torch.storage import0 处。17 处调用点结构与 v2.7.1 相同(行号偏移为test_torch.py:179/212/290/308/337/7605/7623/7627/7630/7633/7636/7819/7849/7894/7906、test_serialization.py:911/943),人工复核结论一致:全部为TypedStorage及其子类接收者,排除。v2.12.00/0/1:UntypedStorage命中 38 处;.untyped(命中 17 处(test/test_torch.py15 处、test/test_serialization.py2 处);from torch.storage import0 处。17 处调用点(test_torch.py:132/165/243/261/290/7679/7697/7701/7704/7707/7710/7893/7923/7968/7980、test_serialization.py:911/943)人工复核结论与 v2.7.1 一致:全部为TypedStorage及其子类接收者,排除。master0/0/0:UntypedStorage命中 41 处(较 v2.12.0 新增test_mps.py:8970、test_serialization.py:4968/4993等);.untyped(命中 17 处(test/test_torch.py15 处、test/test_serialization.py2 处);from torch.storage import1 处(test_serialization.py:4964,导入TypedStorage,与本 API 无关)。17 处调用点(test_torch.py:134/167/245/263/292/7803/7821/7825/7828/7831/7834/8017/8047/8092/8104、test_serialization.py:911/943)人工复核结论与 v2.7.1 一致:全部为TypedStorage及其子类接收者,排除。社区测试用例: 未找到任何测试用例文件。针对
torch.UntypedStorage.untyped()的直接调用,四个目标引用的test/目录均未命中:全量调用形态检索到的 17 处.untyped()经逐个人工复核,接收者全部是TypedStorage或其_LegacyStorage子类(如torch.FloatStorage、torch.cuda.FloatStorage),属于另一个 APItorch.TypedStorage.untyped的用例;test_torch.py中test_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.md的torch.UntypedStorage章节内,untyped()小节标注支持 Atlas A2/A3 训练系列产品),本地已有记录,但是文档标注不支持A5服务器,因此需要调整。文档路径: 与 行号范围:
v2.7.1docs/zh/api/native_api/pytorch_2-7-1/torch-Storage.md721-737v2.11.0docs/zh/api/native_api/pytorch_2-11-0/torch-Storage.md721-737v2.12.0docs/zh/api/native_api/pytorch_2-12-0/torch-Storage.md721-737v2.13.0docs/zh/api/native_api/pytorch_2-13-0/torch-Storage.md721-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:
v2.11.0:
v2.12.0:
master:
以下是A5服务器验证结果:
获取芯片型号命令:
执行结果:
参考截图:

v2.7.1:
v2.11.0:
v2.12.0:
master: