此分配背后的逻辑是什么:了解 numpy 中的就地分配操作



我有两个相当简单的代码,给出了不同的答案。我知道这是由于共享的参考,但我不太清楚在第二种情况下究竟发生了什么

a = np.ones(5)
b = torch.from_numpy(a)
a=np.add(a, 1, out=a)
print(a)
print(b)

[输出]:

[2. 2.2. 2.2.]

tensor([2., 2., 2., 2., 2.], dtype=torch.float64(

a = np.ones(5)
b = torch.from_numpy(a)
a=a+1
print(a)
print(b)

[输出]:

[2. 2.2. 2.2.]

Tensor([1., 1., 1., 1., 1.], dtype=torch.float64(

为什么在第二种情况下没有改变b?

在第一种情况下,ab共享相同的内存(即ba的视图,换句话说,b指向(数组(值a也指向该值(,并且out参数保证在np.add()操作完成后更新a的相同内存。 而在第二种情况下,当您执行a = a+1并且b仍然指向a的旧值时,a是新副本。

尝试第二种情况:

a += 1

并观察ab确实都已更新。

In [7]: a = np.ones(5) 
...: b = torch.from_numpy(a) 
...: a += 1   
In [8]: a  
Out[8]: array([2., 2., 2., 2., 2.])
In [9]: b 
Out[9]: tensor([2., 2., 2., 2., 2.], dtype=torch.float64)

正如@hpaulj在他的评论中恰当地指出的那样,当我们做a = a+1时,会创建一个新对象,a现在将指向这个新的(数组(对象而不是旧的对象,该对象仍然由b指向。这就是b的(数组(未更新的原因。


为了更好地理解这种行为,你可能想参考 Ned Batchelder 关于名称如何绑定到 Python 中的值的优秀文章

最新更新