Nested computational graphs during forward for videos

Idriss_Mghabbar: <p>Hello,</p>
<p>I am using pre-trained models on imagenet to build custom video classification models.<br>
In the first phase, we compute the forward on every frame:</p>
<pre><code class="lang-auto">outputs = []
for i in range(n_frames):
     outputs.append(pretrained_model(video[i])
</code></pre>
<p>Given that “outputs” is updated at each iteration, this loop results in a nested computational graph because the graphs are retained at every iteration.</p>
<p>This causes a cuda out of memory for big models.</p>
<p>Is there a way to do this better ?</p>
<p>Thanks</p>

albanD: <p>Hi,</p>
<p>Do you actually need all the outputs at the same time?<br>
If so, you can try the checkpoint module to reduce the memory usage to only one branch at a time: <a href="https://pytorch.org/docs/stable/checkpoint.html?highlight=checkpoint#torch.utils.checkpoint.checkpoint" class="inline-onebox">torch.utils.checkpoint — PyTorch 1.8.0 documentation</a></p>

Idriss_Mghabbar: <p>Hello albanD,</p>
<p>Thank you for your reply !!</p>
<p>Yes I need to fill the ouputs list because it will be used as an input to a customized model later on.<br>
I don’t fully understand the usage of checkpoints in that context as it is just in the forward, the weights do not change, there is just a computational graph that is being created.<br>
Can you be more specific please ?</p>
<p>Ideally, I want to tell PyTorch to use the same computational graph of the first frame for the next frames as it does not change.</p>

albanD: <blockquote>
<p>Ideally, I want to tell PyTorch to use the same computational graph of the first frame for the next frames as it does not change.</p>
</blockquote>
<p>The thing is that what takes memory is not the graph itself, but the intermediary buffers that are needed to do the backward. And these buffers are different for each input you give.</p>
<blockquote>
<p>Can you be more specific please ?</p>
</blockquote>
<p>You can try:</p>
<pre data-code-wrap="python"><code class="lang-python">outputs = []
for i in range(n_frames):
     outputs.append(checkpoint(pretrained_model, video[i]))
</code></pre>

Idriss_Mghabbar: <p>I tried it and since I have to do a backward later on, it didn’t work.</p>
<p>Is there a way to save up memory knowing that it’s basically many forwards without a backward between them while keeping the required buffers to do a backward later?</p>
<p>Please tell me if it’s not clear, I can give more information.</p>

albanD: <p>It is not super clear. But if the checkpoint proposed above didn’t work to reduce the memory enough. The you most likely won’t have enough memory.<br>
In particular, can you estimate the memory used by one of such forward + state for it. And see if that will fit?</p>

Idriss_Mghabbar: <p>Thank you for making me discover checkpoints ! They are very useful to trade compute for memory.</p>
<p>I’m afraid that since i’m checkpointing all of the pre-trained model, the tensors are not requiring grad anymore.</p>
<p>I get this error :</p>
<pre><code class="lang-auto">  UserWarning: None of the inputs have requires_grad=True. Gradients will be None
  warnings.warn("None of the inputs have requires_grad=True. Gradients will be None")
</code></pre>
<p>I made the input requires grad. I hope this will solve the problem.</p>
<p>Thank you</p>