Python中的+=操作

前几日在写一段Pytorch代码时,又一次遇到了in-place操作的问题。

1
output+=pos  # pos是不可更新的tensor,output是可更新的tensor

程序报错:“one of the variables needed for gradient computation has been modified by an inplace operation”。

无意中将代码改成output=output+pos,程序就不会报错了。

在查阅了相关资料后,将我的思考整理下来。

在Python中,i=i+1i+=1是不同的,如果被操作数没有部署 ’iadd‘方法,则i=i+1i+=1是等价的,’+=‘并不会产生in-place操作;当被操作数有部署该方法且正确部署,则是会产生in-place操作的。当没有in-place操作时,i=i+1表示对i重分配,也即i指向了另一个空间而不是原来的空间。

所以,这样的例子就能解释清楚了:

1
2
3
4
5
6
7
8
9
10
import numpy as np

A = np.arange(12).reshape(4,3)
for a in A:
a = a + 1
# A并没有被改变
B = np.arange(12).reshape(4,3)
for b in B:
b += 1
# B被改变了

在Pytorch中,也有部署’iadd()‘操作,所以对于output+=pos,output内部的值被改变了,也即在计算图中引入了环,在反向求导时则会出错。

因此,在Pytorch中,应当避免in-place的操作。

Reference:
https://stackoverflow.com/questions/41446833/what-is-the-difference-between-i-i-1-and-i-1-in-a-for-loop