Loops inside a model slows gradient calculation dramatically

James_Hickman: <p>I’m quite new to pytorch and this is my first time posting here so if this has already been addressed or is obvious then I apologize in advance but here is the problem I’m having:</p>
<p>I have a neural network model that trains very quickly when vectorized, here is the vectorized form:<br>
yatomic=((torch.sigmoid(x.mm(torch.t(w1))+torch.t(b1.mm(M1)))-0.5).mm(torch.t(w2))+torch.t(b2.mm(M1)))<br>
ypred=torch.mv(R,(yatomic[:,0]))<br>
loss=(torch.mul((y[:,0]-ypred),Ninv[:,0])**2.0).sum() .  <span class="hashtag">#MSE</span> of model</p>
<p>This trains in about 5 minutes and converges very nicely.</p>
<p>However if I instead compute the mean square error in the loss term using for loops (as opposed to the R matrix above which is an alternative to the loops) then the gradient calculation takes around 25X longer, for example the same model but with loops</p>
<p>yatomic=(torch.sigmoid(x.mm(torch.t(w1))+torch.t(b1.mm(M1)))-0.5).mm(torch.t(w2))+torch.t(b2.mm(M1))<br>
k1=0; k2=0; S1=0.0<br>
for i in range(0,len(sample)): <span class="hashtag">#sum</span> over atomic structures<br>
i1=sample[i]  <span class="hashtag">#id</span> dictionary<br>
S=0.0<br>
for j in atoms[i1]:   <span class="hashtag">#sum</span> over atoms in structure<br>
S=S+yatomic[k1,0]<br>
k1=k1+1<br>
S1=S1+((S-y[i,0])*Ninv[i,0])**2.0 <span class="hashtag">#compare</span> with DFT energy<br>
loss=S1</p>
<p>The model still works and outputs the correct values but it is just much slower, am I doing something wrong/stupid here that is slowing everything down, or is pytorch just much faster at calculating the gradient for matrix-type operations and therefore the slowing is unavoidable when using the loops.</p>
<p>I know that the obvious answer is “why are you using the loops just use the vectorized form” but the neural network is just the first part of the “full” model. I need to use the output of the neural network as an input to an analytical physical model and the model is very difficult to vectorize and at least at present requires some loops and can’t be expressed as a series of matrix-vector operations.</p>
<p>Also I should note that the loops are not the bottleneck, they completes almost instantaneously, it is the gradient calculation that is slowing things down.</p>
<p>Any help would be appreciated!</p>

albanD: <p>Hi,</p>
<p>The problem with for loops is two fold:</p>
<ul>
<li>Running the python code for the for loops can be slow and running very small ops is usually less efficient than running big ones (this slows down both the forward and backward pass).</li>
<li>All the indexing ops are not free.</li>
<li>The number of operations they add to the computational graph is huge and so any operation with it becomes very expensive.</li>
</ul>

xwwwwww: <p>Hi, I’m confused that “for loops slows down backward pass” as I think bp speed is only conditioned on the constructed computational graph, therefore has nothing to do with the forward implementation</p>

albanD: <p>But the computational graph match the forward pass. So if you do a lot of ops in the forward, the graph will be large and the backward slower.</p>

xwwwwww: <p>Ah, I see.  Take matrix multiplication as an example, each loop would create a new node in the computational graph, while <code>torch.matmul</code> would only create an op?</p>