TL;DR
Utilice .clone().detach()
(ou de préférence .detach().clone()
)
Si vous détachez d'abord le tenseur puis le clonez, le chemin de calcul n'est pas copié, dans l'autre sens, il est copié puis abandonné. Ainsi, .detach().clone()
est très légèrement plus efficace forums pytorch
car il est légèrement rapide et explicite dans ce qu'il fait.
Utilisation de perflot
j'ai tracé le timing de différentes méthodes pour copier un tenseur 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
L'axe des x est la dimension du tenseur créé, l'axe des y indique le temps. Le graphique est en échelle linéaire. Comme vous pouvez le voir clairement, le tensor()
o new_tensor()
prend plus de temps par rapport aux trois autres méthodes.
Nota: En plusieurs essais, j'ai remarqué que parmi b, c, e, n'importe quelle méthode peut avoir le temps le plus bas. Il en va de même pour a et d. Mais, les méthodes b, c, e ont systématiquement un temps plus faible que a et 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',
)
6 votes
Un avantage de
b
est qu'il rend explicite le fait quey
ne fait plus partie du graphe de calcul, c'est-à-dire qu'il ne nécessite pas de gradient.c
est différent des 3 en ce quey
nécessite toujours un diplôme.1 votes
Et si
torch.empty_like(x).copy_(x).detach()
- c'est la même chose quea/b/d
? Je reconnais que ce n'est pas une façon intelligente de procéder, j'essaie simplement de comprendre le fonctionnement de l'autograd. Je suis confus par le documents pourclone()
qui disent "Contrairement à copy_(), cette fonction est enregistrée dans le graphe de calcul," ce qui m'a fait penser àcopy_()
ne nécessiterait pas de gradation.3 votes
Il y a une note assez explicite dans les docs :
When data is a tensor x, new_tensor() reads out ‘the data’ from whatever it is passed, and constructs a leaf variable. Therefore tensor.new_tensor(x) is equivalent to x.clone().detach() and tensor.new_tensor(x, requires_grad=True) is equivalent to x.clone().detach().requires_grad_(True). The equivalents using clone() and detach() are recommended.
6 votes
Pytorch '1.1.0' recommande #b maintenant et montre un avertissement dans #d
0 votes
@ManojAcharya peut-être envisager d'ajouter votre commentaire comme une réponse ici.
0 votes
Qu'en est-il
.clone()
par lui-même ?