You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch示例程序内存占用过高原因排查求助

内存占用异常过高问题分析

注意:请谨慎运行以下代码,maxlen设置过高会耗尽电脑所有可用内存,导致系统卡顿甚至完全无响应,无法通过shell终止进程,只能重启电脑。

import numpy as np
import collections
import torch

# q = collections.deque(maxlen=1500)  # 占用约6.4GB
# q = collections.deque(maxlen=3000)  # 占用约12GB
q = collections.deque(maxlen=5000)  # 占用约18GB

def f():
    nparray = np.zeros([4,84,84], dtype=np.uint8)
    q.append(nparray)
    nparray1 = np.zeros([32,4,84,84], dtype=np.float32)
    tens = torch.tensor(nparray1, dtype=torch.float32)

while True:
    f()

我正在调试这个内存占用极高的程序,通过top命令的VIRT列测量内存时,发现实际占用远超预期:比如将maxlen从1500增至3000,我计算的预期内存增长仅约403MB(计算方式:4 * 84 * 84 * 15000 / (1024**2)),但实际增长了6GB。

另外发现collections.deque和PyTorch张量的分配存在交互:注释掉两者中任意一项,内存占用就会恢复正常——比如注释张量创建行后,总内存仅约2GB。恳请帮忙分析原因。


核心原因解析

  1. PyTorch内存池的惰性释放机制
    PyTorch创建张量时会向系统申请连续内存块,即使张量局部引用消失,内存池也不会立即释放这块内存,而是留作后续张量复用。循环持续创建张量时,内存池会不断膨胀,直到耗尽系统可用内存。

  2. Deque持有numpy数组导致GC延迟
    deque持续持有numpy数组,会让这些数组的引用计数始终不为0,Python垃圾回收(GC)无法主动回收它们。这会持续占用系统内存,导致PyTorch内存池无法有效复用已申请的内存块,只能不断向系统申请新内存,最终推高VIRT内存占用。

  3. 两者交互放大内存问题
    单独注释deque时,numpy数组在函数结束后失去引用,GC会及时回收,系统内存压力小,PyTorch内存池可以正常复用内存;单独注释张量时,没有持续的内存池膨胀,内存占用自然正常。但两者同时存在时,deque占用内存导致系统内存紧张,PyTorch无法复用内存,只能持续申请新内存,最终出现内存占用远超预期的情况。

验证与解决方向

  • 手动触发GC:在循环中加入import gc; gc.collect(),可部分缓解内存占用,但无法彻底解决PyTorch内存池的惰性释放问题。
  • 调整PyTorch内存策略:如果使用GPU,可调用torch.cuda.empty_cache()释放显存;CPU环境下可尝试设置torch.set_num_threads(1)减少内存开销,或使用torch.utils.checkpoint优化内存占用。
  • 优化deque使用:限制maxlen不要过大,或定期清理deque中的旧元素,释放numpy数组的引用,让GC可以回收内存,缓解系统内存压力。

内容的提问来源于stack exchange,提问作者Julian Francis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 14:35:21