已合并
docs: update torch.UntypedStorage support status #46583
gcw_CHjSLYhf创建于 9月18日
docs: update torch.UntypedStorage support status #46583
已合并
Pull Request已成功合入, 合并人@ascend-robot
(感谢 gcw_CHjSLYhf 的贡献)9月18日 创建了 pull request,commit d94392e9
Ggcw_CHjSLYhf
9月18日 关联了issue:8月社区任务第一期-Ascend for PyTorch API 一致性开发(78),8月社区任务第一期-Ascend for PyTorch API 一致性开发(89),8月社区任务第一期-Ascend for PyTorch API 一致性开发(99),8月社区任务第一期-Ascend for PyTorch API 一致性开发(100)
9月18日 关联了issue:8月社区任务第一期-Ascend for PyTorch API 一致性开发(78),8月社区任务第一期-Ascend for PyTorch API 一致性开发(89),8月社区任务第一期-Ascend for PyTorch API 一致性开发(99),8月社区任务第一期-Ascend for PyTorch API 一致性开发(100)
atomgit-bot
9月18日 评论:
9月18日 评论:
变更摘要
本 PR 为资料(文档)更新,围绕 torch.UntypedStorage 系列 API 在 torch-npu 平台的支持情况,对多个 PyTorch 版本文档中的 torch-Storage.md 进行修正。涉及修正的 API 包括 torch.UntypedStorage.filename、torch.UntypedStorage.nbytes 和 torch.UntypedStorage.new,主要纠正其中关于 A5 芯片支持情况的描述错误;torch.UntypedStorage.hpu 因与 HPU 平台存在硬编码绑定,其系统支持情况无需修改。PR 说明中同时给出了相应的功能验证场景与测试结论,用于佐证文档修正依据。
主要改动
- 修正
torch.UntypedStorage.filename支持情况: 该项目已有该 API 资料条目,但其中 A5 支持情况有误,本次在文档中予以纠正。 - 修正
torch.UntypedStorage.nbytes资料错误: 针对nbytes()返回底层 Storage 实际字节数的语义,修正文档中存在的描述错误。 - 修正
torch.UntypedStorage.new资料错误: 修正new()在当前 Storage 所在设备上创建大小为 0 的新 UntypedStorage 相关文档描述。 - 保持
torch.UntypedStorage.hpu资料不变: 因该 API 与 HPU 平台存在硬编码绑定,系统支持情况无需补充或修正。 - 同步更新四个版本目录文档: 改动覆盖
pytorch_2-7-1、pytorch_2-11-0、pytorch_2-12-0、pytorch_2-13-0四个版本下的torch-Storage.md。


不准确?
atomgit-bot
9月18日 评论:
9月18日 评论:
🤖 本次改动均为数据 / 生成 / 二进制文件(如测试用例、锁文件、媒体资源),没有可审查的代码逻辑,已跳过 AI 代码审查。


不准确?
9月18日 添加了label:ascend-cla/yes
此处折叠了79条消息 查看更多
14 天前 删除了label:ci-pipeline-running
14 天前 添加了label:ci-pipeline-passed
AtlasAccount
14 天前 评论:
14 天前 评论:
流水线 PR-pipeline_pytorch#71984 [ commitID:1e11092d ] 已完成
>>>代码风格自动修复执行成功(无修复内容)
| 阶段 | 任务名 | 状态 | 详情 |
|---|---|---|---|
| 编译构建 | Build_X86 | ⚪ IGNORED | >>> |
| Build_ARM | ⚪ IGNORED | >>> | |
| Build_X86_torchair | ⚪ IGNORED | >>> | |
| Build_ARM_torchair | ⚪ IGNORED | >>> | |
| patch_test | ⚪ IGNORED | >>> | |
| Build_X86_213 | ⚪ IGNORED | >>> | |
| Build_ARM_213 | ⚪ IGNORED | >>> | |
| 恶意代码检查 | Antipoison | ✅ COMPLETED | >>> |
| 编码安全与规范检查 | check_error | ✅ COMPLETED | >>> |
| lintrunner | ✅ COMPLETED | >>> | |
| 开源片段检查 | SCA | ✅ COMPLETED | >>> |
| 开发者测试 | UT_ARM_A2_Part_01 | ⚪ IGNORED | >>> |
| UT_ARM_A2_Part_02 | ⚪ IGNORED | >>> | |
| UT_ARM_A2_Part_03 | ⚪ IGNORED | >>> | |
| UT_inductor_Part_01 | ⚪ IGNORED | >>> | |
| UT_inductor_Part_02 | ⚪ IGNORED | >>> | |
| UT_inductor_Part_03 | ⚪ IGNORED | >>> | |
| UT_inductor_Part_04 | ⚪ IGNORED | >>> | |
| UT_DIST_ARM_Part_01 | ⚪ IGNORED | >>> | |
| UT_DIST_ARM_Part_02 | ⚪ IGNORED | >>> | |
| UT_DIST_ARM_Part_03 | ⚪ IGNORED | >>> | |
| UT_DIST_ARM_Part_04 | ⚪ IGNORED | >>> | |
| UT_ARM_A2_Select_Part_01 | ⚪ IGNORED | >>> | |
| UT_ARM_A2_Select_Part_02 | ⚪ IGNORED | >>> | |
| UT_inductor_Part1_213 | ⚪ IGNORED | >>> | |
| 流水线 | PR-pipeline_pytorch | ✅ COMPLETED | >>> |
- compile、compile_inductor、compile_torchair : 运行流水线
- retry : 重试流水线所有失败子任务
- retry <任务名> : 仅重试指定失败子任务
- stop : 停止流水线


14 天前 合入了pull request
AtlasAccount
14 天前 评论:
14 天前 评论:
流水线 pytorch_gitcode_PR_multiVersion-onetrack#310 [ commitID:1e11092d ] 运行失败


【合入来源】
【修改方案】
一. API 功能说明:
1. torch.UntypedStorage.filename
filename是torch.UntypedStorage这个类的一个只读属性,用于获取与当前 Storage 关联的内存映射文件路径。因此和平台设备有关联,需要增加一个快速的验证性测试。PyTorch 2.7 中的实现为:
@property def filename(self): return self._get_filename()因此它属于 Python 属性封装,但实际结果由底层 Storage 元数据接口
_get_filename()提供。2. torch.UntypedStorage.hpu
torch.UntypedStorage.hpu()用于 返回一个在 HPU(Habana Gaudi 加速器)上的存储副本,如果该对象已在HPU内存中且位于正确的设备上,则不执行复制,直接返回原始对象。因为该API与HPU平台设备具有强绑定关系。参数说明:
device:目标 HPU 设备编号,默认使用当前 HPU 设备;non_blocking:如果源内存满足异步复制条件,则允许异步复制。PyTorch 2.7 中的核心实现为:
def hpu(self, device=None, non_blocking=False): device2 = ( torch.device("hpu", device) if device else torch.device("hpu") ) return self.to( device=device2, non_blocking=non_blocking, )3. torch.UntypedStorage.nbytes
torch.UntypedStorage.nbytes()返回当前底层 Storage 实际占用的字节数,返回类型为int。但要注意,
nbytes()查询的是整个 Storage 的大小,而不是当前 Tensor View 的逻辑数据量。例如:
base = torch.empty(16, dtype=torch.float32) view = base[::2] base.untyped_storage().nbytes() == 64 view.untyped_storage().nbytes() == 64 # view只有8个逻辑元素 view.numel() * view.element_size() == 32这是因为
view和base共享同一个底层 Storage。接口本身主要读取底层 Storage 元数据,不执行计算算子,但它读取的是 NPU Storage 的实际字节范围,可以验证 NPU Tensor 到 UntypedStorage 的连接是否正确,因此需要增加 NPU 功能测试。
4. torch.UntypedStorage.new
torch.UntypedStorage.new在当前 Storage 所在设备上,创建一个新的、大小为 0 的 UntypedStorage。torch.UntypedStorage.new() 由底层 Storage 实现提供。NPU Storage 调用该接口时,需要正确处理 PrivateUse1/NPU 设备信息。因此需要补充这个API在torch-npu平台上的测试用例。二. 上游用例检查情况:
检查 PyTorch 上游 Storage 相关测试后,结果如下:
torch.UntypedStorage.filenametest/test_torch.py中未发现直接读取.filename的独立用例torch.UntypedStorage.hpu.hpu()的独立用例torch.UntypedStorage.nbytess.nbytes()并比较不同Storage的字节数torch.UntypedStorage.news.nbytes()并比较不同Storage的字节数三. 资料情况检查:
torch.UntypedStorage.filename:在torch上游社区存在独立条目,同时在当前项目中该API资料已经存在,但是A5支持情况有误,因此需要进行资料修正。torch.UntypedStorage.hpu:在torch上游社区存在独立条目,同时在当前项目中该API资料已经存在,由于该API与hpu平台存在硬编码,系统支持情况,因此不需要进行资料补充和修正。torch.UntypedStorage.nbytes在torch上游社区存在独立条目,同时在当前项目中该API资料有误,因此需要进行资料修正。torch.UntypedStorage.newtorch上游社区存在独立条目,同时在当前项目中该API资料有误,因此需要进行资料修正。【资料变更】
修改以下文件:
docs/zh/api/native_api/pytorch_2-7-1/torch-Storage.mddocs/zh/api/native_api/pytorch_2-11-0/torch-Storage.mddocs/zh/api/native_api/pytorch_2-12-0/torch-Storage.mddocs/zh/api/native_api/pytorch_2-13-0/torch-Storage.md【接口变更】
不涉及
【功能验证】
1. 测试场景
torch.UntypedStorage API 功能性验证
1. 测试场景
torch.UntypedStorage.filenamefilenameNonetorch.UntypedStorage.filenamefrom_file(shared=True)创建共享文件映射 Storagefilename返回字符串,并且规范化路径与映射文件路径一致torch.UntypedStorage.filenamefrom_file(shared=False)创建私有文件映射 Storagefilename返回Nonetorch.UntypedStorage.filenamefilenameNonetorch.UntypedStorage.hpuhpu()HPU device module is not loaded的AssertionErrortorch.UntypedStorage.hpudevice=1, non_blocking=True调用hpu()AssertionErrortorch.UntypedStorage.nbytesfloat16Tensor 的 CPU/NPU Storage 字节数numel × element_sizetorch.UntypedStorage.nbytesfloat32Tensor 的 CPU/NPU Storage 字节数numel × element_sizetorch.UntypedStorage.nbytesint32Tensor 的 CPU/NPU Storage 字节数numel × element_sizetorch.UntypedStorage.nbytesint64Tensor 的 CPU/NPU Storage 字节数numel × element_sizetorch.UntypedStorage.nbytesnbytes()、size()和len()均返回构造时指定的字节数torch.UntypedStorage.nbytesnbytes()、size()和len()均返回 0torch.UntypedStorage.nbytestorch.UntypedStorage.newnew()torch.UntypedStorage.newnew()torch.UntypedStorage.newnew()返回的 Storage 执行resize_()torch.UntypedStorage.newnew()2. 测试核心代码
class TestUntypedStorageAPIs(TestCase): def test_untyped_storage_filename(self): # 场景1:普通CPU Storage不关联内存映射文件 cpu_storage = torch.empty( 8, dtype=torch.float32, device="cpu", ).untyped_storage() self.assertEqual(cpu_storage.device.type, "cpu") self.assertIsNone(cpu_storage.filename) # 场景2和3:共享文件映射与私有文件映射Storage with tempfile.TemporaryDirectory() as temp_dir: file_path = os.path.join( temp_dir, "untyped_storage.bin", ) shared_storage = torch.UntypedStorage.from_file( file_path, shared=True, nbytes=32, ) self.assertEqual(shared_storage.device.type, "cpu") self.assertEqual(shared_storage.nbytes(), 32) self.assertIsInstance( shared_storage.filename, str, ) self.assertEqual( os.path.realpath(shared_storage.filename), os.path.realpath(file_path), ) # 释放共享映射后再创建私有映射 del shared_storage private_storage = torch.UntypedStorage.from_file( file_path, shared=False, nbytes=32, ) self.assertEqual(private_storage.device.type, "cpu") self.assertEqual(private_storage.nbytes(), 32) self.assertIsNone(private_storage.filename) del private_storage # 场景4:NPU Storage不关联CPU内存映射文件 npu_storage = torch.empty( 8, dtype=torch.float32, device="npu", ).untyped_storage() self.assertEqual(npu_storage.device.type, "npu") self.assertIsNone(npu_storage.filename) def test_untyped_storage_hpu(self): npu_storage = torch.empty( 8, dtype=torch.float32, device="npu", ).untyped_storage() self.assertEqual( npu_storage.device.type, "npu", ) # 场景5:在torch-npu平台使用默认参数调用hpu() with self.assertRaisesRegex( AssertionError, r"HPU device module is not loaded", ): npu_storage.hpu() # 场景6:在torch-npu平台指定device和non_blocking参数 with self.assertRaisesRegex( AssertionError, r"HPU device module is not loaded", ): npu_storage.hpu( device=1, non_blocking=True, ) def test_untyped_storage_nbytes_for_tensor_dtypes(self): test_cases = [ (torch.float16, 6), (torch.float32, 6), (torch.int32, 6), (torch.int64, 6), ] # 场景7至10:不同dtype的CPU/NPU Storage字节数 for dtype, numel in test_cases: with self.subTest(dtype=dtype): cpu_tensor = torch.empty( numel, dtype=dtype, device="cpu", ) npu_tensor = torch.empty( numel, dtype=dtype, device="npu", ) cpu_storage = cpu_tensor.untyped_storage() npu_storage = npu_tensor.untyped_storage() expected_nbytes = ( numel * cpu_tensor.element_size() ) self.assertEqual( cpu_storage.nbytes(), expected_nbytes, ) self.assertEqual( npu_storage.nbytes(), expected_nbytes, ) self.assertEqual( cpu_storage.nbytes(), npu_storage.nbytes(), ) # UntypedStorage的长度单位也是字节 self.assertEqual( len(cpu_storage), expected_nbytes, ) self.assertEqual( len(npu_storage), expected_nbytes, ) def test_untyped_storage_nbytes_for_direct_storage(self): # 场景11:直接构造指定字节数的CPU/NPU Storage for device in ["cpu", "npu"]: with self.subTest(device=device): storage = torch.UntypedStorage( 37, device=device, ) self.assertEqual( storage.device.type, device, ) self.assertEqual(storage.nbytes(), 37) self.assertEqual(storage.size(), 37) self.assertEqual(len(storage), 37) def test_untyped_storage_nbytes_for_empty_storage(self): # 场景12:空NPU Storage的字节数为0 empty_npu_storage = torch.UntypedStorage( 0, device="npu", ) self.assertEqual( empty_npu_storage.nbytes(), 0, ) self.assertEqual( empty_npu_storage.size(), 0, ) self.assertEqual( len(empty_npu_storage), 0, ) def test_untyped_storage_nbytes_for_tensor_view(self): # 场景13:Tensor View返回整个底层Storage的字节数 base_tensor = torch.empty( (4, 4), dtype=torch.float32, device="npu", ) view_tensor = base_tensor[:, ::2] base_storage = base_tensor.untyped_storage() view_storage = view_tensor.untyped_storage() base_expected_nbytes = ( base_tensor.numel() * base_tensor.element_size() ) view_logical_nbytes = ( view_tensor.numel() * view_tensor.element_size() ) self.assertEqual( base_storage.nbytes(), base_expected_nbytes, ) self.assertEqual( view_storage.data_ptr(), base_storage.data_ptr(), ) self.assertEqual( view_storage.nbytes(), base_storage.nbytes(), ) self.assertGreater( view_storage.nbytes(), view_logical_nbytes, ) def test_untyped_storage_new_for_cpu_and_npu(self): # 验证普通CPU/NPU Storage调用new()后的基本属性 for device in ["cpu", "npu"]: with self.subTest(device=device): source_storage = torch.empty( 8, dtype=torch.float32, device=device, ).untyped_storage() source_nbytes = source_storage.nbytes() new_storage = source_storage.new() self.assertIsInstance( new_storage, torch.UntypedStorage, ) self.assertIsNot( new_storage, source_storage, ) self.assertEqual( new_storage.device.type, source_storage.device.type, ) self.assertEqual( new_storage.nbytes(), 0, ) self.assertEqual( len(new_storage), 0, ) # 调用new()不能改变原Storage self.assertEqual( source_storage.nbytes(), source_nbytes, ) def test_untyped_storage_new_invalid_argument(self): # new()不接受size等位置参数 source_storage = torch.empty( 8, dtype=torch.float32, device="npu", ).untyped_storage() with self.assertRaises(TypeError): source_storage.new(1)3. 测试命令
source /usr/local/Ascend/ascend-toolkit/set_env.sh TORCH_DEVICE_BACKEND_AUTOLOAD=1 python pytorch-zjs/test/untypedStorage/test_untypedstorage_filename_hpu_nbytes_new.py -v测试结果
A2/A3芯片
A5芯片
v2.7.1
v2.11.0
v2.12.0
测试结论
torch.UntypedStorage.filename、torch.UntypedStorage.nbytes、torch.UntypedStorage.new在torch-npu平台均完整支持。torch.UntypedStorage.hpu在torch-npu平台不支持,AssertionError断言符合预期。【CheckList】