评价此页

torch.Storage#

创建日期:2016年12月30日 | 最后更新日期:2025年4月14日

在 PyTorch 中,常规张量是一个多维数组,由以下组件定义:

  • 存储:张量的实际数据,存储为连续的一维字节数组。

  • dtype:张量中元素的数据类型,例如 torch.float32torch.int64

  • shape:一个元组,指示张量在每个维度上的大小。

  • 步长:在每个维度上从一个元素移动到下一个元素所需的步长。

  • 偏移:存储中张量数据开始的起始点。对于新创建的张量,这通常为 0。

这些组件共同定义了张量的结构和数据,其中存储保存实际数据,其余作为元数据。

无类型存储 API#

torch.UntypedStorage 是一个连续的一维元素数组。其长度等于张量的字节数。存储作为张量的底层数据容器。通常,在 PyTorch 中使用常规构造函数(例如 zeros()zeros_like()new_zeros())创建的张量将生成张量存储与张量本身一一对应的张量。

但是,一个存储允许被多个张量共享。例如,张量的任何视图(通过 view() 或某些(但并非所有)类型的索引(如整数和切片)获得)将指向与原始张量相同的底层存储。当序列化和反序列化共享公共存储的张量时,这种关系会得到保留,并且张量会继续指向相同的存储。有趣的是,反序列化指向单个存储的多个张量比反序列化多个独立张量更快。

可以通过 untyped_storage() 方法访问张量存储。这将返回一个 torch.UntypedStorage 类型的对象。幸运的是,存储具有通过 torch.UntypedStorage.data_ptr() 方法访问的唯一标识符。在常规设置中,具有相同数据存储的两个张量将具有相同的存储 data_ptr。但是,张量本身可以指向两个独立的存储,一个用于其数据属性,另一个用于其 grad 属性。每个都将需要自己的 data_ptr()。通常,不能保证 torch.Tensor.data_ptr()torch.UntypedStorage.data_ptr() 匹配,并且不应假定为真。

无类型存储在某种程度上独立于在其上构建的张量。实际上,这意味着具有不同 dtype 或 shape 的张量可以指向相同的存储。它还意味着可以更改张量存储,如下例所示

>>> t = torch.ones(3)
>>> s0 = t.untyped_storage()
>>> s0
 0
 0
 128
 63
 0
 0
 128
 63
 0
 0
 128
 63
[torch.storage.UntypedStorage(device=cpu) of size 12]
>>> s1 = s0.clone()
>>> s1.fill_(0)
 0
 0
 0
 0
 0
 0
 0
 0
 0
 0
 0
 0
[torch.storage.UntypedStorage(device=cpu) of size 12]
>>> # Fill the tensor with a zeroed storage
>>> t.set_(s1, storage_offset=t.storage_offset(), stride=t.stride(), size=t.size())
tensor([0., 0., 0.])

警告

请注意,不建议直接修改张量的存储,如本示例所示。此低级操作仅用于教育目的,以演示张量与其底层存储之间的关系。通常,使用标准 torch.Tensor 方法(例如 clone()fill_())实现相同的结果更有效、更安全。

除了 data_ptr,无类型存储还具有其他属性,例如 filename(如果存储指向磁盘上的文件)、deviceis_cuda 用于设备检查。存储还可以通过 copy_fill_pin_memory 等方法进行就地或非就地操作。有关更多信息,请查看下面的 API 参考。请记住,修改存储是低级 API,并且存在风险!大多数这些 API 也存在于张量级别:如果存在,它们应优先于其存储对应项。

特殊情况#

我们提到,一个具有非 None grad 属性的张量实际上包含两部分数据。在这种情况下,untyped_storage() 将返回 data 属性的存储,而梯度的存储可以通过 tensor.grad.untyped_storage() 获得。

>>> t = torch.zeros(3, requires_grad=True)
>>> t.sum().backward()
>>> assert list(t.untyped_storage()) == [0] * 12  # the storage of the tensor is just 0s
>>> assert list(t.grad.untyped_storage()) != [0] * 12  # the storage of the gradient isn't
还有一些特殊情况,张量没有典型的存储,或者根本没有存储
  • "meta" 设备上的张量:"meta" 设备上的张量用于形状推断,不包含实际数据。

  • 伪张量:PyTorch 编译器使用的另一个内部工具是 FakeTensor,它基于类似的想法。

张量子类或类似张量对象也可能表现出异常行为。一般来说,我们不期望许多用例需要操作存储级别!

class torch.UntypedStorage(*args, **kwargs)[source]#
bfloat16()[source]#

将此存储转换为 bfloat16 类型。

bool()[source]#

将此存储转换为 bool 类型。

byte()[source]#

将此存储转换为 byte 类型。

byteswap(dtype)[source]#

交换底层数据中的字节。

char()[source]#

将此存储转换为 char 类型。

clone()[source]#

返回此存储的副本。

complex_double()[source]#

将此存储转换为复双精度类型。

complex_float()[source]#

将此存储转换为复浮点类型。

copy_()#
cpu()[source]#

如果此存储尚未在 CPU 上,则返回此存储的 CPU 副本。

cuda(device=None, non_blocking=False)[source]#

返回此对象在 CUDA 内存中的副本。

如果此对象已在 CUDA 内存中且位于正确的设备上,则不执行复制并返回原始对象。

参数
  • device (int) – 目标 GPU ID。默认为当前设备。

  • non_blocking (bool) – 如果为 True 且源位于固定内存中,则复制将相对于主机异步进行。否则,该参数无效。

返回类型

Union[_StorageBase, TypedStorage]

data_ptr()#
device: device#
double()[source]#

将此存储转换为双精度浮点类型。

element_size()#
属性 filename: 可选[str]#

返回与此存储关联的文件名。

如果存储在 CPU 上,并且是通过 from_file() 创建的,且 shared 设置为 True,则文件名将是一个字符串。否则,此属性为 None

fill_()#
float()[源码]#

将此存储转换为浮点类型。

float8_e4m3fn()[源码]#

将此存储转换为 float8_e4m3fn 类型

float8_e4m3fnuz()[源码]#

将此存储转换为 float8_e4m3fnuz 类型

float8_e5m2()[源码]#

将此存储转换为 float8_e5m2 类型

float8_e5m2fnuz()[源码]#

将此存储转换为 float8_e5m2fnuz 类型

静态 from_buffer()#
静态 from_file(filename, shared=False, nbytes=0) 存储#

创建一个由内存映射文件支持的 CPU 存储。

如果 sharedTrue,则内存将在所有进程之间共享。所有更改都将写入文件。如果 sharedFalse,则存储上的更改不会影响文件。

nbytes 是存储的字节数。如果 sharedFalse,则文件必须至少包含 nbytes 字节。如果 sharedTrue,则在需要时将创建文件。(请注意,对于 UntypedStorage,此参数与 TypedStorage.from_file 的参数不同)

参数
  • filename (str) – 要映射的文件名

  • shared (bool) – 是否共享内存(是将 MAP_SHARED 还是 MAP_PRIVATE 传递给底层的 mmap(2) 调用

  • nbytes (int) – 存储的字节数

get_device()[源码]#
返回类型

整数

half()[源码]#

将此存储转换为半精度浮点类型。

hpu(device=None, non_blocking=False)[源码]#

返回此对象在 HPU 内存中的副本。

如果此对象已在 HPU 内存中并位于正确的设备上,则不执行复制并返回原始对象。

参数
  • device (int) – 目标 HPU ID。默认为当前设备。

  • non_blocking (bool) – 如果为 True 且源位于固定内存中,则复制将相对于主机异步进行。否则,该参数无效。

返回类型

Union[_StorageBase, TypedStorage]

int()[源码]#

将此存储转换为整数类型。

属性 is_cuda#
属性 is_hpu#
is_pinned(device='cuda')[源码]#

确定 CPU 存储是否已固定在设备上。

参数

device (strtorch.device) – 固定内存的设备(默认值:'cuda')。此参数不建议使用,并且可能会被弃用。

返回

一个布尔变量。

is_shared()#
is_sparse: bool = False#
is_sparse_csr: bool = False#
long()[源码]#

将此存储转换为长整数类型。

mps()[源码]#

如果此存储尚未在 MPS 上,则返回此存储的 MPS 副本。

nbytes()#
new()#
pin_memory(device='cuda')[源码]#

如果 CPU 存储尚未固定,则将其复制到固定内存。

参数

device (strtorch.device) – 固定内存的设备(默认值:'cuda')。此参数不建议使用,并且可能会被弃用。

返回

一个固定的 CPU 存储。

resizable()#
resize_()#
share_memory_(*args, **kwargs)[源码]#

将存储移动到共享内存。

对于已在共享内存中的存储以及 CUDA 存储(不需要为跨进程共享而移动),这是一种空操作。共享内存中的存储无法调整大小。

请注意,为了缓解诸如 此问题 之类的问题,在同一个对象上从多个线程调用此函数是线程安全的。但是,在没有适当同步的情况下,在 self 上调用任何其他函数都是非线程安全的。有关更多详细信息,请参阅 多进程最佳实践

注意

当共享内存中存储的所有引用都被删除时,关联的共享内存对象也将被删除。PyTorch 有一个特殊的清理过程,以确保即使当前进程意外退出,也会发生这种情况。

值得注意的是 share_memory_()from_file() 之间设置 shared = True 的区别

  1. share_memory_ 使用 shm_open(3) 创建 POSIX 共享内存对象,而 from_file() 使用 open(2) 打开用户传入的文件名。

  2. 两者都使用 mmap(2) 调用,并使用 MAP_SHARED 将文件/对象映射到当前虚拟地址空间

  3. share_memory_ 会在映射对象后调用 shm_unlink(3),以确保当没有进程打开对象时,共享内存对象会被释放。torch.from_file(shared=True) 不会解除文件的链接。此文件是持久的,将一直存在,直到用户将其删除。

返回

自身

short()[源码]#

将此存储转换为短整数类型。

size()[源码]#
返回类型

整数

to(*, device, non_blocking=False)[源码]#
tolist()[源码]#

返回一个包含此存储元素的列表。

type(dtype=None, non_blocking=False)[源码]#
返回类型

Union[_StorageBase, TypedStorage]

untyped()[源码]#

旧版类型存储#

警告

出于历史原因,PyTorch 之前使用过类型存储类,现在已弃用,应避免使用。以下将详细介绍此 API,以防您遇到它,尽管强烈不建议使用它。除了 torch.UntypedStorage 之外的所有存储类都将在未来移除,并且在所有情况下都将使用 torch.UntypedStorage

torch.Storage 是与默认数据类型(torch.get_default_dtype())相对应的存储类的别名。例如,如果默认数据类型是 torch.float,则 torch.Storage 解析为 torch.FloatStorage

torch.<type>Storagetorch.cuda.<type>Storage 类,如 torch.FloatStoragetorch.IntStorage 等,实际上从未被实例化。调用它们的构造函数会创建一个具有相应 torch.dtypetorch.devicetorch.TypedStoragetorch.<type>Storage 类具有 torch.TypedStorage 的所有类方法。

torch.TypedStorage 是一个连续的一维数组,包含特定 torch.dtype 的元素。它可以指定任何 torch.dtype,内部数据将进行适当的解释。torch.TypedStorage 包含一个 torch.UntypedStorage,它将数据作为无类型字节数组保存。

每个带步长的 torch.Tensor 都包含一个 torch.TypedStorage,它存储了 torch.Tensor 查看的所有数据。

torch.TypedStorage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
bfloat16()[源码]#

将此存储转换为 bfloat16 类型。

bool()[源码]#

将此存储转换为 bool 类型。

byte()[源码]#

将此存储转换为 byte 类型。

char()[源码]#

将此存储转换为 char 类型。

clone()[源码]#

返回此存储的副本。

complex_double()[源码]#

将此存储转换为复双精度类型。

complex_float()[源码]#

将此存储转换为复浮点类型。

copy_(source, non_blocking=None)[源码]#
cpu()[源码]#

如果此存储尚未在 CPU 上,则返回此存储的 CPU 副本。

cuda(device=None, non_blocking=False)[源码]#

返回此对象在 CUDA 内存中的副本。

如果此对象已在 CUDA 内存中且位于正确的设备上,则不执行复制并返回原始对象。

参数
  • device (int) – 目标 GPU ID。默认为当前设备。

  • non_blocking (bool) – 如果为 True 且源位于固定内存中,则复制将相对于主机异步进行。否则,该参数无效。

返回类型

自我

data_ptr()[源码]#
属性 device#
double()[源码]#

将此存储转换为双精度浮点类型。

dtype: dtype#
element_size()[源码]#
属性 filename: 可选[str]#

如果存储是从文件内存映射的,则返回与此存储关联的文件名;如果存储不是通过内存映射文件创建的,则返回 None

fill_(value)[源码]#
float()[源码]#

将此存储转换为浮点类型。

float8_e4m3fn()[源码]#

将此存储转换为 float8_e4m3fn 类型

float8_e4m3fnuz()[源码]#

将此存储转换为 float8_e4m3fnuz 类型

float8_e5m2()[源码]#

将此存储转换为 float8_e5m2 类型

float8_e5m2fnuz()[源码]#

将此存储转换为 float8_e5m2fnuz 类型

类方法 from_buffer(*args, **kwargs)[源码]#
类方法 from_file(filename, shared=False, size=0) 存储[源码]#

创建一个由内存映射文件支持的 CPU 存储。

如果 sharedTrue,则内存将在所有进程之间共享。所有更改都将写入文件。如果 sharedFalse,则存储上的更改不会影响文件。

size 是存储中元素的数量。如果 sharedFalse,则文件必须至少包含 size * sizeof(Type) 字节(Type 是存储的类型)。如果 sharedTrue,则在需要时将创建文件。

参数
  • filename (str) – 要映射的文件名

  • shared (bool) –

    是否共享内存(是将 MAP_SHARED 还是 MAP_PRIVATE 传递给底层的 mmap(2) 调用

  • size (int) – 存储中的元素数量

get_device()[源码]#
返回类型

整数

half()[源码]#

将此存储转换为半精度浮点类型。

hpu(device=None, non_blocking=False)[源码]#

返回此对象在 HPU 内存中的副本。

如果此对象已在 HPU 内存中并位于正确的设备上,则不执行复制并返回原始对象。

参数
  • device (int) – 目标 HPU ID。默认为当前设备。

  • non_blocking (bool) – 如果为 True 且源位于固定内存中,则复制将相对于主机异步进行。否则,该参数无效。

返回类型

自我

int()[源码]#

将此存储转换为整数类型。

属性 is_cuda#
属性 is_hpu#
is_pinned(device='cuda')[源码]#

确定 CPU 类型存储是否已固定在设备上。

参数

device (strtorch.device) – 固定内存的设备(默认值:'cuda')。此参数不建议使用,并且可能会被弃用。

返回

一个布尔变量。

is_shared()[源码]#
is_sparse: bool = False#
long()[源码]#

将此存储转换为长整数类型。

nbytes()[源码]#
pickle_storage_type()[源码]#
pin_memory(device='cuda')[源码]#

如果 CPU TypedStorage 尚未固定,则将其复制到固定内存。

参数

device (strtorch.device) – 固定内存的设备(默认值:'cuda')。此参数不建议使用,并且可能会被弃用。

返回

一个固定的 CPU 存储。

resizable()[源码]#
resize_(size)[源码]#
share_memory_()[源码]#

请参阅 torch.UntypedStorage.share_memory_()

short()[源码]#

将此存储转换为短整数类型。

size()[源码]#
to(*, device, non_blocking=False)[源码]#

返回此对象在设备内存中的副本。

如果此对象已在正确的设备上,则不执行复制并返回原始对象。

参数
  • device (int) – 目标设备。

  • non_blocking (bool) – 如果为 True 且源位于固定内存中,则复制将相对于主机异步进行。否则,该参数无效。

返回类型

自我

tolist()[源码]#

返回一个包含此存储元素的列表。

type(dtype=None, non_blocking=False)[源码]#

如果未提供 dtype,则返回类型,否则将此对象转换为指定类型。

如果这已经是正确的类型,则不执行复制并返回原始对象。

参数
  • dtype (类型字符串) – 所需的类型

  • non_blocking (bool) – 如果为 True,并且源在固定内存中,目标在 GPU 上,反之亦然,则复制操作相对于主机异步执行。否则,此参数无效。

  • **kwargs – 为了兼容性,可能包含键 async 以替代 non_blocking 参数。async 参数已弃用。

返回类型

联合[_存储基础, TypedStorage, str]

untyped()[源码]#

返回内部 torch.UntypedStorage

torch.DoubleStorage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.float64#
torch.FloatStorage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.float32#
torch.HalfStorage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.float16#
torch.LongStorage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.int64#
torch.IntStorage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.int32#
torch.ShortStorage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.int16#
torch.CharStorage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.int8#
torch.ByteStorage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.uint8#
torch.BoolStorage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.bool#
torch.BFloat16Storage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.bfloat16#
torch.ComplexDoubleStorage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.complex128#
torch.ComplexFloatStorage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.complex64#
torch.QUInt8Storage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.quint8#
torch.QInt8Storage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.qint8#
torch.QInt32Storage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.qint32#
torch.QUInt4x2Storage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.quint4x2#
torch.QUInt2x4Storage(*args, wrap_storage=None, dtype=None, device=None, _internal=False)[源码]#
dtype: torch.dtype = torch.quint2x4#