注意
转到末尾 以下载完整示例代码。
预分配内存与TensorDict¶
作者: Tom Begley
在这个教程中,您将学习如何利用内存预分配在
TensorDict。
假设我们有一个函数,它返回一个 TensorDict
import torch
from tensordict.tensordict import TensorDict
def make_tensordict():
return TensorDict({"a": torch.rand(3), "b": torch.rand(3, 4)}, [3])
也许我们想多次调用这个函数,并使用结果填充一个单一的TensorDict。
TensorDict(
fields={
a: Tensor(shape=torch.Size([10, 3]), device=cpu, dtype=torch.float32, is_shared=False),
b: Tensor(shape=torch.Size([10, 3, 4]), device=cpu, dtype=torch.float32, is_shared=False)},
batch_size=torch.Size([10, 3]),
device=None,
is_shared=False)
由于我们指定了 batch_size 为 tensordict,因此在循环的第一次迭代中,我们将 tensordict 填充为空张量,这些空张量的第一个维度大小为 N,其余维度则由 make_tensordict 的返回值决定。在上述示例中,我们为键 "a" 预先分配了一个大小为 torch.Size([10, 3]) 的零值数组,为键 "b" 预先分配了一个大小为 torch.Size([10, 3, 4]) 的零值数组。循环后续的迭代将直接就地写入。因此,若并非所有值都被填充,则它们将默认取零值。
让我们通过逐步执行上述循环来演示发生了什么。我们首先初始化一个空的TensorDict。
N = 10
tensordict = TensorDict({}, batch_size=[N, 3])
print(tensordict)
TensorDict(
fields={
},
batch_size=torch.Size([10, 3]),
device=None,
is_shared=False)
在第一次迭代后,tensordict 已经预填充了 "a" 和 "b" 的张量。这些张量除了第一行被分配了随机值外,其余都包含零。
random_tensordict = make_tensordict()
tensordict[0] = random_tensordict
assert (tensordict[1:] == 0).all()
assert (tensordict[0] == random_tensordict).all()
print(tensordict)
TensorDict(
fields={
a: Tensor(shape=torch.Size([10, 3]), device=cpu, dtype=torch.float32, is_shared=False),
b: Tensor(shape=torch.Size([10, 3, 4]), device=cpu, dtype=torch.float32, is_shared=False)},
batch_size=torch.Size([10, 3]),
device=None,
is_shared=False)
后续迭代中,我们在原地更新预分配的张量。
脚本总运行时间: (0 分钟 0.003 秒)