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

如何让CuPy在变量超出作用域后彻底释放全部GPU内存?

彻底释放CuPy占用GPU内存的解决方案

问题场景

运行显存密集型CUDA C++模型前,用CuPy完成GPU预处理,转CPU后需要完全清空CuPy占用的所有GPU内存,但即使手动删除变量+调用free_all_blocks(),仍有内存残留,复杂场景下残留量可达数十GB,无法满足后续模型的显存需求(当前单卡仅余500MB空闲)。

有效解决方法

1. 全面清理CuPy内存池与CUDA缓存

除了默认内存池,还要清理pinned内存池及CUDA runtime级别的缓存,适合简单场景:

import cupy as cp

def run():
    X = cp.random.rand(10000000,300)
    y = cp.random.randn(300)
    out = X.dot(y)
    out_hst = cp.asnumpy(out)
    
    # 清理所有CuPy内存池
    del X, y, out
    cp._default_memory_pool.free_all_blocks()
    cp._default_pinned_memory_pool.free_all_blocks()
    
    # 同步设备并触发CUDA缓存清理(CUDA 11.2+适用)
    cp.cuda.Device().synchronize()
    cp.cuda.runtime.mallocAsync(0)
    
    return out_hst

说明:CuPy的内存池分为普通和pinned两种,同时CUDA runtime会保留部分设备缓存,mallocAsync(0)会强制触发缓存回收。

2. 子进程隔离预处理(最彻底方案)

利用子进程退出时操作系统自动回收所有资源的特性,彻底清除包括cublas临时内存在内的所有GPU占用,适合复杂场景:
修改主脚本testcupy.py:

import numpy as np
from multiprocessing import Process, Queue

def preprocess(q):
    import cupy as cp
    X = cp.random.rand(10000000,300)
    y = cp.random.randn(300)
    out = X.dot(y)
    out_hst = cp.asnumpy(out)
    q.put(out_hst)

if __name__ == "__main__":
    result_queue = Queue()
    proc = Process(target=preprocess, args=(result_queue,))
    proc.start()
    out = result_queue.get()
    proc.join()
    
    # 子进程已结束,所有GPU内存完全释放
    print("预处理完成,GPU内存已清空")
    input()

说明:子进程运行预处理任务,结束后操作系统会回收其占用的所有GPU资源,无需手动跟踪清理变量或内存池,彻底解决残留问题。

3. 验证内存释放状态

可以通过以下代码确认GPU内存是否完全释放:

import cupy as cp
used_gb = cp.cuda.Device().mem_info[0] / (1024 ** 3)
print(f"当前已用GPU内存: {used_gb:.2f} GB")

或者直接在终端执行nvidia-smi查看显存占用。

为什么之前的方法不彻底

  • CuPy内存池默认会保留部分小内存块作为缓存,仅调用free_all_blocks()无法清除CUDA runtime级别的设备缓存。
  • 复杂场景中,cublas等底层库的临时内存不受CuPy内存池管理,手动删除变量无法回收这部分内存,子进程隔离是唯一彻底的解决方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:37:44