在训练和测试时间pytorch上以不同方式管理内存

时间:2019-04-13 15:22:56

标签: python deep-learning conv-neural-network pytorch

目前,我正在使用pytorch编写基于U-net的细分模型,我想使用与mobilenet v2上引入的反向残差类似的方法来提高模型在cpu上的速度。 pytorch code for mobile netv2

然后我意识到模型在训练阶段和测试阶段使用了更多的内存。尽管模型应该在训练阶段使用更多的内存,因为所有中间步张量(特征图)都已保存,并且通过可分离的卷积,每个“卷积”操作都会创建更多的张量。 但是在运行时,实际上只有很少的最后一步张量必须保存才能用于跳过连接,而其他所有张量一旦创建下一步就可以删除。在测试阶段,具有正常卷积的u-net和具有可分离卷积的u-net的内存效率应该相同。

我是pytorch的新手,所以我不知道如何编写代码以防止不必要的测试时间开销。由于pytorch与python绑定。我想我可以使用del手动删除正向函数中所有不必要的张量。但是我猜想,如果我只是删除前向函数中的变量,它将影响训练阶段。 pytorch上是否有更高级的功能,可以通过“网络图”优化测试阶段的内存使用? 我也很好奇tensorflow是否可以自动处理这些问题,因为它具有更抽象和更复杂的图构建逻辑。

2 个答案:

答案 0 :(得分:0)

由于您在测试期间使用了torch.no_grad(),因此您自动要求Context-manager禁用梯度计算,这导致比训练少的内存使用。但是,我发现缓存分配器占用大量内存,可以在训练期间每次对模型进行更新后释放这些内存,从而节省了大量内存。

因此,您可以使用函数torch.cuda.empty_cache(),对于我来说,它真的很有帮助。另外,阅读memory management可以帮助您学习有关PyTorch中GPU内存管理的其他重要内容。

答案 1 :(得分:0)

阅读用于resnet的官方pytorch代码后,我意识到我不应该给所有变量起一个名字。aka我不应该写:

conv1 = self.conv1(x)
conv2 = self.conv2(conv1)

我应该写:

out = self.conv1(x)
out = self.conv2(out)

通过这种方式,在使用了conv1之后,python便可以清除它,而没有引用obj对应于conv1。

因为块之间存在剩余连接,所以我需要再有一个python变量来引用该变量:又名

out = self.conv1(x)
residual_connect = out
out = self.conv2(out)
out = conv1 + out

但是在解码阶段,只需要输出即可。因此,我在解码阶段开始时删除了残余连接。

del residual_connect

这看起来像是骇客,但令我惊讶的是它在训练阶段并未引起任何问题。现在,我的模型的ram使用率已大大降低,但我觉得这里应该是解决问题的更优雅的方法。