当我将 numpy 数组转换为张量并以不同方式更改 numpy 时,有些会更改张量,有些则不会。这是样品:
在此代码中:
array = np.arange(1., 8.)
tensor = torch.from_numpy(array)
array, tensor
答案是:
(array([1., 2., 3., 4., 5., 6., 7.]),
tensor([1., 2., 3., 4., 5., 6., 7.], dtype=torch.float64))
不,当我以这种方式向 numpy 数组添加 1 时,它会改变张量值:
array = np.arange(1., 8.)
tensor = torch.from_numpy(array)
array += 1
array, tensor
输出为:
(array([2., 3., 4., 5., 6., 7., 8.]),
tensor([2., 3., 4., 5., 6., 7., 8.], dtype=torch.float64))
但是当我以另一种方式更改 numpy 数组时,它不会更改张量:
array = np.arange(1., 8.)
tensor = torch.from_numpy(array)
array = array + 1
array, tensor
输出是:
(array([2., 3., 4., 5., 6., 7., 8.]),
tensor([1., 2., 3., 4., 5., 6., 7.], dtype=torch.float64))
同样,此代码不会改变它:
array = np.arange(1., 8.)
tensor = torch.from_numpy(array)
array = array + 1
array += 1
array, tensor
将 pytorch 的张量更改为 numpy 数组时也会发生这种情况。
为什么 numpy 和 torch 可以这样工作?
+=
就地修改,而 x = x + 1
创建副本。
您可能想阅读有关固定内存的内容。我怀疑 PyTorch 正在使用它来减少数据传输开销以获得更好的性能。当您使用
array = array + 1
重新分配时,可能会创建一个副本(您可以尝试使用 id(array)
打印数组的地址,以检查分配后地址是否更改,这意味着制作了副本)
import numpy as np
arr = np.arange(3)
print((arr, id(arr)))
arr+=1
print((arr, id(arr)))
arr = arr + 1
print((arr, id(arr)))
结果是:
(array([0, 1, 2]), 1951948494416)
(array([1, 2, 3]), 1951948494416)
(array([2, 3, 4]), 1952052860880)
当您创建副本时,旧数组仍被 GPU 使用,因此它保留在那里(内存未释放),因此您仍然可以访问其旧内容(检查按引用传递与按值传递)。