Pytorch复制张量的首选方法

时间:2019-03-20 16:51:42

标签: copy pytorch tensor

似乎有几种方法可以在Pytorch中创建张量副本,包括

y = tensor.new_tensor(x) #a

y = x.clone().detach() #b

y = torch.empty_like(x).copy_(x) #c

y = torch.tensor(x) #d
根据我得到的用户警告,如果执行ba,则明显优先使用

d而不是ad。为什么首选它?性能?我认为它的可读性较差。

是否/反对使用c

3 个答案:

答案 0 :(得分:34)

TL; DR

使用.clone().detach()(最好是.detach().clone()

如果首先分离张量然后克隆它,则不会复制计算路径,反之,则将其复制并放弃。因此,.detach().clone()的效率略高。-pytorch forums

因为它的功能略显快速。


我使用perflot绘制了复制pytorch张量的各种方法的时间。

y = tensor.new_tensor(x) # method a

y = x.clone().detach() # method b

y = torch.empty_like(x).copy_(x) # method c

y = torch.tensor(x) # method d

y = x.detach().clone() # method e

x轴是创建的张量的尺寸,y轴显示时间。该图是线性比例。如您所见,与其他三种方法相比,tensor()new_tensor()花费的时间更多。

enter image description here

注意:在多次运行中,我注意到在b,c,e中,任何方法的时间都可以最少。 a和d也是如此。但是,方法b,c,e始终比a和d具有更低的时序。

import torch
import perfplot

perfplot.show(
    setup=lambda n: torch.randn(n),
    kernels=[
        lambda a: a.new_tensor(a),
        lambda a: a.clone().detach(),
        lambda a: torch.empty_like(a).copy_(a),
        lambda a: torch.tensor(a),
        lambda a: a.detach().clone(),
    ],
    labels=["new_tensor()", "clone().detach()", "empty_like().copy()", "tensor()", "detach().clone()"],
    n_range=[2 ** k for k in range(15)],
    xlabel="len(a)",
    logx=False,
    logy=False,
    title='Timing comparison for copying a pytorch tensor',
)

答案 1 :(得分:0)

Pytorch'1.1.0'现在建议#b并显示对#d的警告

答案 2 :(得分:0)

检查张量是否被复制的一个示例:

import torch
def samestorage(x,y):
    if x.storage().data_ptr()==y.storage().data_ptr():
        print("same storage")
    else:
        print("different storage")
a = torch.ones((1,2), requires_grad=True)
print(a)
b = a
c = a.data
d = a.detach()
e = a.data.clone()
f = a.clone()
g = a.detach().clone()
i = torch.empty_like(a).copy_(a)
j = torch.tensor(a) # UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).


print("a:",end='');samestorage(a,a)
print("b:",end='');samestorage(a,b)
print("c:",end='');samestorage(a,c)
print("d:",end='');samestorage(a,d)
print("e:",end='');samestorage(a,e)
print("f:",end='');samestorage(a,f)
print("g:",end='');samestorage(a,g)
print("i:",end='');samestorage(a,i)

出局:

tensor([[1., 1.]], requires_grad=True)
a:same storage
b:same storage
c:same storage
d:same storage
e:different storage
f:different storage
g:different storage
i:different storage
j:different storage

如果显示不同存储,则张量将被复制。 PyTorch有近100种不同的构造函数,因此您可以添加更多方法。

如果我需要复制张量,我将仅使用copy(),这也会复制与AD相关的信息,因此,如果我需要删除与AD相关的信息,我将使用:

y = x.clone().detach()