CUDA out of memory - on the 8th epoch?

username: pozimek
cooked: <p>Hey,</p>
<p>My training is crashing due to a ‘CUDA out of memory’ error, except that it happens at the 8th epoch. In my understanding unless there is a memory leak or unless I am writing data to the GPU that is not deleted every epoch the CUDA memory usage should not increase as training progresses, and if the model is too large to fit on the GPU then it should not pass the first epoch of training.</p>
<p>Any advice on how to debug this issue will be greatly appreciated as I am not sure myself where to even begin. Could faulty garbage collection be responsible? If so, are there any settings I can pass to Python’s/Pytorch’s GC to prevent this crash from occurring at the cost of performance? Are there any known bugs that could be the cause for this and if so are there any known workarounds? Does anyone know of any tools that can help me pinpoint the cause of this issue, such as a CUDA memory monitor that can tell me by how much is memory usage increasing every epoch?</p>

username: albanD
cooked: <p>Hi</p>
<blockquote>
<p>Could faulty garbage collection be responsible?</p>
</blockquote>
<p>Python is refcounted. So no issue here <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=12" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p>The usual reason this happens is:</p>
<ul>
<li>You accumulate your loss (for later printing) in a differentiable manner like <code>all_loss += loss</code>. This means that <code>all_loss</code> keeps all the history of all the previous iterations. You can fix it by doing <code>all_loss += loss.item()</code> to get a python number that does not track gradients.</li>
<li>You reuse some Tensor that requires_grad from one iteration to the next. Effectively growing the graph of history needed to compute gradient at each iteration. You need to check elements that are reused from one iteration to the next.</li>
<li>You save some state in a list in a differentiable manner, add <code>.detach()</code> to break the history graph and only store the value of the Tensor (and not all its history).</li>
</ul>
<p>Let me know if it helps !</p>

username: pozimek
cooked: <aside class="quote no-group" data-username="albanD" data-post="2" data-topic="67288">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/alband/48/215_2.png" class="avatar"> albanD:</div>
<blockquote>
<p>Python is refcounted.</p>
</blockquote>
</aside>
<p>I understand that this guarantees no leaks, but does that guarantee that GC will always be on time?</p>
<aside class="quote no-group" data-username="albanD" data-post="2" data-topic="67288">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/alband/48/215_2.png" class="avatar"> albanD:</div>
<blockquote>
<p>You accumulate your loss (for later printing) in a differentiable manner like <code>all_loss += loss</code> .</p>
</blockquote>
</aside>
<p>All of my loss accumulation is already using loss.item().</p>
<aside class="quote no-group" data-username="albanD" data-post="2" data-topic="67288">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/alband/48/215_2.png" class="avatar"> albanD:</div>
<blockquote>
<p>You save some state in a list in a differentiable manner</p>
</blockquote>
</aside>
<p>I was actually guilty of this. I am training a ‘hard’ attention recurrent model that directs a ‘window’ around an image to produce <a href="https://papers.nips.cc/paper/5542-recurrent-models-of-visual-attention.pdf" rel="noopener nofollow ugc">‘glimpses’</a>, and I was storing the past glimpse locations in a memory tensor. I instantiated this memory with torch.zeros(), which sets requires_gradients to False by default, but I didn’t realize that setting an element of this memory with a non-detached tensor would attach the entire memory tensor. I now call .detach() on the input tensor before inserting it into memory. I also <a href="https://github.com/kevinzakka/recurrent-visual-attention/issues/29" rel="noopener nofollow ugc">posted about this</a> on the repo I based my code on for anyone curious.</p>
<p>I’m restarting training now, and I’ll report back on whether this helped once training is over. Each epoch takes 30+ minutes so it will be a while <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=12" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20">. Thanks for the help, saved me a day or two of pulling my hair out.</p>

username: albanD
cooked: <aside class="quote no-group" data-username="pozimek" data-post="3" data-topic="67288">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/pozimek/48/15216_2.png" class="avatar"> pozimek:</div>
<blockquote>
<p>does that guarantee that GC will always be on time?</p>
</blockquote>
</aside>
<p>The Python standard does not guarantee that. But CPython (the only python implementation we support) uses refcount and delete the objects as soon at it reach zero (there is no garbage collector involved). So yes as long as you use CPython (and you don’t create reference cycle, but that is fairly rare and should not happen).</p>
<p>Congrats on finding the issue !</p>