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

Python删除类实例后psutil无法准确显示可用内存的原因及替代方案

问题原因与解决方案

核心原因

psutil的virtual_memory()统计的是系统全局内存状态,而Python解释器(及PyTorch这类依赖库)有自身的内存池机制:当删除对象并触发垃圾回收后,释放的内存会先被Python内存池保留,不会立刻归还给操作系统。这就导致psutil仍会将这部分内存标记为“已占用”,但Windows资源管理器统计的是实际归还给系统的内存,因此出现数据差异。

另外,PyTorch的CPU张量内存管理也有类似逻辑,释放的内存会被PyTorch内部缓存,而非直接交还系统。

解决方案

1. 统计当前Python进程的内存(而非系统全局)

使用psutil.Process()获取当前进程的内存使用情况,能准确反映你的Python程序实际占用的内存:

import psutil
import gc
import torch

# 获取当前Python进程
proc = psutil.Process()

# 分配内存
x = torch.randint(0,255,size=(300,3,200,200),dtype=torch.float32)
conv = Modules.Conv2D(3,3,2,10,save_flag=False)
print("进程占用物理内存(RSS):", proc.memory_info().rss / 1024 / 1024, "MB")

# 删除实例并回收内存
del conv, x
gc.collect()
# 若使用GPU张量,需额外调用torch.cuda.empty_cache()
# torch.cuda.empty_cache()

print("进程占用物理内存(RSS):", proc.memory_info().rss / 1024 / 1024, "MB")

这里的rss(常驻集大小)是进程实际占用的物理内存,能精准体现代码执行过程中的内存变化。

2. 强制PyTorch释放CPU内存

对于PyTorch的CPU张量,除了触发GC,还可以手动强制释放内部缓存的内存(适用于PyTorch 1.6+):

import torch
torch._C._empty_cpu_cache()

执行该方法后,PyTorch会将缓存的CPU内存归还给操作系统,再用psutil.Process()统计即可得到更准确的结果。

3. 细粒度内存分析工具

若需要逐行定位内存变化,可使用memory_profiler库:

from memory_profiler import profile

@profile
def test_memory():
    x = torch.randint(0,255,size=(300,3,200,200),dtype=torch.float32)
    conv = Modules.Conv2D(3,3,2,10,save_flag=False)
    del conv, x
    gc.collect()
    torch._C._empty_cpu_cache()

test_memory()

运行后会输出每一行代码的内存变化数据,便于精准排查内存释放情况。

4. Windows平台直接调用系统API

如果需要获取和资源管理器完全一致的系统内存数据,可通过ctypes调用Windows系统API:

import ctypes

class MEMORYSTATUSEX(ctypes.Structure):
    _fields_ = [
        ("dwLength", ctypes.c_ulong),
        ("dwMemoryLoad", ctypes.c_ulong),
        ("ullTotalPhys", ctypes.c_ulonglong),
        ("ullAvailPhys", ctypes.c_ulonglong),
        ("ullTotalPageFile", ctypes.c_ulonglong),
        ("ullAvailPageFile", ctypes.c_ulonglong),
        ("ullTotalVirtual", ctypes.c_ulonglong),
        ("ullAvailVirtual", ctypes.c_ulonglong),
        ("sullAvailExtendedVirtual", ctypes.c_ulonglong),
    ]

def get_system_memory():
    stat = MEMORYSTATUSEX()
    stat.dwLength = ctypes.sizeof(MEMORYSTATUSEX)
    ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat))
    used_percent = stat.dwMemoryLoad
    free_mb = stat.ullAvailPhys / 1024 / 1024
    total_mb = stat.ullTotalPhys / 1024 / 1024
    return used_percent, free_mb, total_mb

# 使用示例
used_pct, free_mb, total_mb = get_system_memory()
print(f"已用内存: {used_pct}% 可用内存: {free_mb:.2f} MB")

该方法直接调用Windows内核接口,返回结果与资源管理器完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 07:39:55