torch中tensor的in-place操作

运行一些操作可能会导致为新结果分配内存。例如,如果我们用Y = X + Y,我们将取消引用Y指向的张量,而是指向新分配的内存处的张量。
在下面的例子中,我们用Python的id()函数演示了这一点,它给我们提供了内存中引用对象的确切地址。运行Y = Y + X后,我们会发现id(Y)指向另一个位置。这是因为Python首先计算Y + X,为结果分配新的内存,然后使Y指向内存中的这个新位置。

在Python中,id 函数返回的是对象的唯一标识符,通常是对象在内存中的地址

before = id(Y)
Y = Y + X
id(Y) == before

# False

这可能是不可取的,原因有两个:

  1. 首先,我们不想总是不必要地分配内存。在机器学习中,我们可能有数百兆的参数,并且在一秒内多次更新所有参数。通常情况下,我们希望原地执行这些更新;
  2. 如果我们不原地更新,其他引用仍然会指向旧的内存位置,这样我们的某些代码可能会无意中引用旧的参数。

幸运的是,执行原地操作非常简单。我们可以使用切片表示法将操作的结果分配给先前分配的数组,例如Y[:] = 。为了说明这一点,我们首先创建一个新的矩阵Z,其形状与另一个Y相同,使用zeros_like来分配一个全0的块。

Z = torch.zeros_like(Y)
print('id(Z):', id(Z))
Z[:] = X + Y
print('id(Z):', id(Z))

#id(Z): 140327634811696
#id(Z): 140327634811696

如果在后续计算中没有重复使用X,我们也可以使用X[:] = X + Y或X += Y来减少操作的内存开销。

before = id(X)
X += Y
id(X) == before

#True

总结

在PyTorch中,张量(tensor)的行为与numpy数组类似,但也有它们自己的特点。下面是对您提供的两段代码的解释:

  1. 对于 Y = Y + X:
    这里发生的是一个非就地(out-of-place)操作。Y + X 创建了一个新的张量来存储加法的结果,然后这个新的张量被赋值给变量Y。因此,Y的id会改变,因为它现在引用了一个新的对象。所以,id(Y) == before 的结果将是 False。

  2. 对于 X += Y 或者 X.add_(Y):
    这里发生的是一个就地(in-place)操作。+= 是 add_ 方法的简写,这个方法会修改 X 张量本身的内容而不会创建一个新的张量。因此,X的id不会改变,id(X) == before 的结果将是 True。

就地操作在处理大型数据时非常有用,因为它可以减少内存的使用,避免不必要的复制。在PyTorch中,就地操作通常有一个后缀 ,比如 add、mul_ 等。但是,在自动微分(如使用PyTorch的梯度下降算法)时,就地操作可能会导致问题,因为它们可能会覆盖掉计算梯度所需的中间值。因此,在设计模型时需要谨慎使用就地操作。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值