MemoryMappedTensor#
- class tensordict.MemoryMappedTensor(source, *, dtype=None, shape=None, index=None, device=None, handler=None, filename=None)#
Bases:
TensorA CPU tensor whose storage is a file on disk, or anonymous shared memory when no filename is given.
Use it to share a tensor between processes, or to work with data that is larger than RAM: the operating system reads from the file only the pages that you access. When a MemoryMappedTensor is sent through a multiprocessing queue or an RPC call, only its file or shared-memory reference is sent, not the data.
memmap()turns every leaf of a tensordict into a MemoryMappedTensor. See Save and load tensordicts and Load data and share it between processes.Build one with a class method rather than with the constructor:
from_tensor()copies a tensor;empty(),zeros(),ones()andfull()make a new tensor of a given shape, andempty_like(),zeros_like(),ones_like()andfull_like()one with the shape and dtype of another tensor;from_filename()maps an existing file, andfrom_storage()wraps an existing storage.
The methods that write new data take a
filename: with one, the data is in that file; without one, it is in anonymous shared memory, andfilenameraises an error. Indexing a MemoryMappedTensor,unbind(),chunk()andsplit()give MemoryMappedTensors on the same storage. Other operations (x + 1, for example) give a regulartorch.Tensor.A MemoryMappedTensor has these constraints:
It must be on CPU, and it cannot require gradients.
With RPC, every node must have read access to the file path. If it does not, the result of sending the tensor is undefined.
Warning
A caller that supplies
filenamemust control its parent directory. Existing symbolic links are rejected, but path-based memory mapping cannot prevent another process with directory write access from replacing a path after it has been validated.The
handlerargument is internal.- Parameters:
source (Tensor, TypedStorage, UntypedStorage or str) – the data. A str is the name of an existing file, mapped as
from_filename()does withdtype,shapeandindex. Withfilename, the tensor is copied to that file, asfrom_tensor()does. A storage is passed tofrom_storage()with the other arguments. A tensor withoutfilenameis wrapped as it is: the result shares its memory but has no file or shared-memory handle, so it cannot be pickled.- Keyword Arguments:
dtype (dtype, optional) – with a str
source, the dtype of the data in the file (required). With a storage, the dtype of the tensor, as infrom_storage(). Not accepted with thefilenamekeyword. Defaults toNone.shape (Size, optional) – the shape of the result, as in
from_filename(),from_tensor()orfrom_storage(); required with a strsource. Ignored for a tensor withoutfilename. Defaults toNone, which keeps the shape ofsource.index (index, optional) – an index applied to the result, as in
tensor[index]. With a str or storagesource,shapeis the shape of the data beforeindexis applied. Defaults toNone.device (device, str or int, optional) –
Noneor"cpu"; another device raises aValueError. Defaults toNone.filename (str or Path, optional) – the file to copy
sourceto. Defaults toNone.
Examples
>>> import os >>> import tempfile >>> import torch >>> from tensordict import MemoryMappedTensor >>> with tempfile.TemporaryDirectory() as tmpdir: ... filename = os.path.join(tmpdir, "x.memmap") ... x = MemoryMappedTensor.from_tensor(torch.arange(4.0), filename=filename) ... x[0] = 10.0 # writes to the file ... print(MemoryMappedTensor.from_filename(filename, dtype=torch.float32, shape=(4,))) MemoryMappedTensor([10., 1., 2., 3.])
Without a filename, the data is in anonymous shared memory:
>>> z = MemoryMappedTensor.zeros(2, 3) >>> z.shape, z.dtype (torch.Size([2, 3]), torch.float32) >>> type(z[0]).__name__, type(z + 1).__name__ ('MemoryMappedTensor', 'Tensor')
- chunk(chunks, dim=0)#
Splits the tensor into
chunksviews, astorch.Tensor.chunk()does.The chunks are MemoryMappedTensors on the same storage, so they keep the file and can be pickled. Under
torch.compile(), they are regular tensors.
- classmethod empty(*size, dtype=None, device=None, filename=None, existsok: bool = False)#
- classmethod empty(shape, *, dtype=None, device=None, filename=None, existsok: bool = False)
Returns an uninitialized MemoryMappedTensor of the given shape.
- Parameters:
*size (int, sequence of int, Size or Tensor) – the shape, as ints (
2, 3) or as one sequence ((2, 3)). It can also be passed as theshapekeyword. A 2-D tensor gives a nested tensor, with the shape of each element in one row.- Keyword Arguments:
dtype (dtype, optional) – the dtype of the tensor. Defaults to
None, which uses the default dtype (torch.get_default_dtype()).device (device, str or int, optional) –
Noneor"cpu"; another device raises aRuntimeError. Defaults toNone.filename (str or Path, optional) – the file to write the data to. Defaults to
None, which keeps the data in anonymous shared memory.existsok (bool, optional) – if
True, an existing file atfilenameis overwritten. IfFalse, it raises aRuntimeError. Defaults toFalse.
Examples
>>> import os >>> import tempfile >>> import torch >>> from tensordict import MemoryMappedTensor >>> with tempfile.TemporaryDirectory() as tmpdir: ... filename = os.path.join(tmpdir, "x.memmap") ... x = MemoryMappedTensor.empty((2, 3), dtype=torch.int64, filename=filename) ... print(x.shape, os.path.getsize(filename)) torch.Size([2, 3]) 48
- classmethod empty_like(input, *, filename=None)#
Returns an uninitialized MemoryMappedTensor with the shape and dtype of
input.- Parameters:
input (Tensor) – the tensor whose shape and dtype the result takes.
- Keyword Arguments:
filename (str or Path, optional) – the file to write the data to. It must not exist. Defaults to
None, which keeps the data in anonymous shared memory.
Examples
>>> import torch >>> from tensordict import MemoryMappedTensor >>> x = MemoryMappedTensor.empty_like(torch.zeros(2, 3, dtype=torch.int64)) >>> x.shape, x.dtype (torch.Size([2, 3]), torch.int64)
- property filename#
The absolute path of the file that holds the data.
Raises a
RuntimeErrorif the data is in anonymous shared memory.
- classmethod from_filename(filename, dtype, shape, index=None, mode: str | None = None)#
Returns a MemoryMappedTensor that maps an existing file.
The file holds raw data with no header, so the dtype and the shape must be given.
memmap()records them in themeta.jsonfile of the directory it writes.- Parameters:
filename (str or Path) – the path to the file.
dtype (dtype) – the dtype of the data.
shape (Size, sequence of int or Tensor) – the shape of the tensor. A 2-D tensor gives a nested tensor, with the shape of each element in one row.
index (index, optional) – an index applied to the result, as in
tensor[index]. Defaults toNone.mode (str, optional) –
"r"maps the file copy-on-write: in-place writes stay in memory."r+"maps it shared: in-place writes reach the file, and aPermissionErroris raised if the file is not writable. Defaults toNone, which maps the file shared if it is writable and copy-on-write otherwise.
- Raises:
ValueError – if
modeis notNone,"r"or"r+".PermissionError – if
mode="r+"and the file is not writable.
Examples
>>> import os >>> import tempfile >>> import torch >>> from tensordict import MemoryMappedTensor >>> with tempfile.TemporaryDirectory() as tmpdir: ... filename = os.path.join(tmpdir, "x.memmap") ... _ = MemoryMappedTensor.from_tensor(torch.arange(6), filename=filename) ... x = MemoryMappedTensor.from_filename(filename, torch.int64, (2, 3), mode="r") ... x[0, 0] = 100 # copy-on-write: the file is unchanged ... print(MemoryMappedTensor.from_filename(filename, torch.int64, (2, 3))) MemoryMappedTensor([[0, 1, 2], [3, 4, 5]])
- classmethod from_handler(handler, dtype, shape, index=None)#
Rebuilds a MemoryMappedTensor from a shared-memory handler.
Deprecated since version 0.15: The handler is private, and this method has no replacement.
- classmethod from_storage(storage, *, shape: Size | None = None, dtype: dtype | None = None, device: device | None = None, index: IndexType | None = None, filename: Path | str = None, handler: _handler = None)#
Returns a MemoryMappedTensor that views an existing storage.
The data is not copied: writes to the result change the storage. If the storage was mapped from a file (for example with
torch.UntypedStorage.from_file()), the result keeps that file and can be pickled; other storages give a tensor that cannot be pickled.- Parameters:
storage (UntypedStorage or TypedStorage) – the storage to view.
- Keyword Arguments:
shape (Size or Tensor, optional) – the shape of the result. A tensor gives a nested tensor with one shape per row. Defaults to
None, which gives a 1-D tensor.dtype (dtype, optional) – the dtype to read the storage with. Defaults to
None, which reads an untyped storage astorch.int64and accepts a typed storage only if its dtype is the default dtype (torch.get_default_dtype()). Passdtypeto read another dtype.device (device, str or int, optional) –
Noneor"cpu". Defaults toNone.index (index, optional) – an index applied to the result. Defaults to
None.filename (str or Path, optional) – the file of the storage, if it has one and does not record it. Defaults to
None.handler – internal.
- Raises:
RuntimeError – if the storage has a file and
filenamenames another one.
Examples
>>> import os >>> import tempfile >>> import torch >>> from tensordict import MemoryMappedTensor >>> with tempfile.TemporaryDirectory() as tmpdir: ... filename = os.path.join(tmpdir, "x.memmap") ... _ = MemoryMappedTensor.from_tensor(torch.arange(6.0), filename=filename) ... storage = torch.UntypedStorage.from_file(filename, shared=True, nbytes=24) ... x = MemoryMappedTensor.from_storage(storage, dtype=torch.float32, shape=(2, 3)) ... print(x, x.filename == filename) MemoryMappedTensor([[0., 1., 2.], [3., 4., 5.]]) True
- classmethod from_tensor(input, *, filename: Path | str = None, existsok: bool = False, copy_existing: bool = False, copy_data: bool = True, shape: Size | None = None)#
Returns a MemoryMappedTensor with a copy of the content of
input.If
inputis a MemoryMappedTensor, it is returned unchanged in two cases:filenameisNoneandinputhas no file, orfilenameis the file ofinput(andinputwas not opened withmode="r"). A file-backedinputwithfilename=Noneis copied to anonymous shared memory. In all other cases, a newMemoryMappedTensoris produced.- Parameters:
input (Tensor) – the tensor to copy. A nested tensor must have the
torch.stridedlayout.- Keyword Arguments:
filename (str or Path, optional) – the file to write the data to. Defaults to
None, which keeps the data in anonymous shared memory.existsok (bool, optional) – if
True, an existing file atfilenameis overwritten. IfFalse, it raises an error. Defaults toFalse.copy_existing (bool, optional) – if
True, a MemoryMappedTensor with a file can be copied to another file. IfFalse, this raises an error, so that data is not duplicated on disk by mistake. Defaults toFalse.copy_data (bool, optional) – if
False, the result has the shape and dtype ofinputbut its content is not written. Defaults toTrue.shape (Size or Tensor, optional) – the shape of the result, when it differs from that of
input;inputis broadcast to it. For a nested tensor, a tensor with the shape of each element, one per row. Defaults toNone, which keeps the shape ofinput.
- Returns:
A MemoryMappedTensor, which is
inputitself in the two cases above.- Raises:
RuntimeError – if
inputrequires gradients, ifinputhas a file,filenameis another file andcopy_existingisFalse, or iffilenameexists andexistsokisFalse.TypeError – if
inputis a NumPy array.
Examples
>>> import os >>> import tempfile >>> import torch >>> from tensordict import MemoryMappedTensor >>> with tempfile.TemporaryDirectory() as tmpdir: ... filename = os.path.join(tmpdir, "tensor.memmap") ... mmap = MemoryMappedTensor.from_tensor(torch.arange(3.0), filename=filename) ... print(mmap) ... print(MemoryMappedTensor.from_tensor(mmap, filename=filename) is mmap) MemoryMappedTensor([0., 1., 2.]) True
- classmethod full(*size, fill_value, dtype=None, device=None, filename=None, existsok: bool = False)#
- classmethod full(shape, *, fill_value, dtype=None, device=None, filename=None, existsok: bool = False)
Returns a MemoryMappedTensor of the given shape filled with
fill_value.- Parameters:
*size (int, sequence of int or Size) – the shape, as ints (
2, 3) or as one sequence ((2, 3)). It can also be passed as theshapekeyword.- Keyword Arguments:
fill_value (number or bool) – the value of every element.
dtype (dtype, optional) – the dtype of the tensor. Defaults to
None, which uses the default dtype (torch.get_default_dtype()).device (device, str or int, optional) –
Noneor"cpu"; another device raises aRuntimeError. Defaults toNone.filename (str or Path, optional) – the file to write the data to. Defaults to
None, which keeps the data in anonymous shared memory.existsok (bool, optional) – if
True, an existing file atfilenameis overwritten. IfFalse, it raises aRuntimeError. Defaults toFalse.
Examples
>>> import torch >>> from tensordict import MemoryMappedTensor >>> MemoryMappedTensor.full(3, fill_value=2, dtype=torch.int64) MemoryMappedTensor([2, 2, 2])
- classmethod full_like(input, fill_value, *, filename=None)#
Returns a MemoryMappedTensor filled with
fill_value, with the shape and dtype ofinput.- Parameters:
- Keyword Arguments:
filename (str or Path, optional) – the file to write the data to. It must not exist. Defaults to
None, which keeps the data in anonymous shared memory.
Examples
>>> import torch >>> from tensordict import MemoryMappedTensor >>> MemoryMappedTensor.full_like(torch.zeros(3, dtype=torch.int64), 7) MemoryMappedTensor([7, 7, 7])
- property index: Any#
The index of this tensor in the tensor that it was built from.
Deprecated since version 0.15: This is internal to pickling and has no replacement.
- classmethod ones(*size, dtype=None, device=None, filename=None, existsok: bool = False)#
- classmethod ones(shape, *, dtype=None, device=None, filename=None, existsok: bool = False)
Returns a MemoryMappedTensor of the given shape filled with ones.
- Parameters:
*size (int, sequence of int, Size or Tensor) – the shape, as ints (
2, 3) or as one sequence ((2, 3)). It can also be passed as theshapekeyword. A 2-D tensor gives a nested tensor, with the shape of each element in one row.- Keyword Arguments:
dtype (dtype, optional) – the dtype of the tensor. Defaults to
None, which uses the default dtype (torch.get_default_dtype()).device (device, str or int, optional) –
Noneor"cpu"; another device raises aRuntimeError. Defaults toNone.filename (str or Path, optional) – the file to write the data to. Defaults to
None, which keeps the data in anonymous shared memory.existsok (bool, optional) – if
True, an existing file atfilenameis overwritten. IfFalse, it raises aRuntimeError. Defaults toFalse.
Examples
>>> from tensordict import MemoryMappedTensor >>> MemoryMappedTensor.ones(2, 3) MemoryMappedTensor([[1., 1., 1.], [1., 1., 1.]])
- classmethod ones_like(input, *, filename=None)#
Returns a MemoryMappedTensor filled with ones, with the shape and dtype of
input.- Parameters:
input (Tensor) – the tensor whose shape and dtype the result takes.
- Keyword Arguments:
filename (str or Path, optional) – the file to write the data to. It must not exist. Defaults to
None, which keeps the data in anonymous shared memory.
Examples
>>> import torch >>> from tensordict import MemoryMappedTensor >>> MemoryMappedTensor.ones_like(torch.zeros(3)) MemoryMappedTensor([1., 1., 1.])
- property parent_shape: Size#
The shape of the tensor that this tensor was built from.
Deprecated since version 0.15: This is internal to pickling and has no replacement.
- split(split_size, dim=0)#
Splits the tensor into views of
split_size, astorch.Tensor.split()does.The parts are MemoryMappedTensors on the same storage, so they keep the file and can be pickled. Under
torch.compile(), they are regular tensors.
- unbind(dim)#
Removes a dimension and returns the slices along it, as
torch.Tensor.unbind()does.The slices are MemoryMappedTensors on the same storage, so they keep the file and can be pickled. Under
torch.compile(), they are regular tensors. Unliketorch.Tensor.unbind(),dimhas no default.
- classmethod zeros(*size, dtype=None, device=None, filename=None, existsok: bool = False)#
- classmethod zeros(shape, *, dtype=None, device=None, filename=None, existsok: bool = False)
Returns a MemoryMappedTensor of the given shape filled with zeros.
- Parameters:
*size (int, sequence of int, Size or Tensor) – the shape, as ints (
2, 3) or as one sequence ((2, 3)). It can also be passed as theshapekeyword. A 2-D tensor gives a nested tensor, with the shape of each element in one row.- Keyword Arguments:
dtype (dtype, optional) – the dtype of the tensor. Defaults to
None, which uses the default dtype (torch.get_default_dtype()).device (device, str or int, optional) –
Noneor"cpu"; another device raises aRuntimeError. Defaults toNone.filename (str or Path, optional) – the file to write the data to. Defaults to
None, which keeps the data in anonymous shared memory.existsok (bool, optional) – if
True, an existing file atfilenameis overwritten. IfFalse, it raises aRuntimeError. Defaults toFalse.
Examples
>>> from tensordict import MemoryMappedTensor >>> MemoryMappedTensor.zeros(2, 3) MemoryMappedTensor([[0., 0., 0.], [0., 0., 0.]])
- classmethod zeros_like(input, *, filename=None)#
Returns a MemoryMappedTensor filled with zeros, with the shape and dtype of
input.- Parameters:
input (Tensor) – the tensor whose shape and dtype the result takes.
- Keyword Arguments:
filename (str or Path, optional) – the file to write the data to. It must not exist. Defaults to
None, which keeps the data in anonymous shared memory.
Examples
>>> import torch >>> from tensordict import MemoryMappedTensor >>> MemoryMappedTensor.zeros_like(torch.ones(3)) MemoryMappedTensor([0., 0., 0.])