当前位置: 首页 > news >正文

PaddleOCR GPU 推理显存不释放?这样改,显存稳稳回落不翻倍--亲测有效

PaddleOCR GPU 推理显存不释放?这样改,显存稳稳回落不翻倍

现象

Flask 包一层 PaddleOCR 3.x 做 OCR 服务,启动基线 576MiB,识别同一张图:

  • 旧版(naive_best_fit)涨到 670MiB 左右就稳了

  • 新版(auto_growth)直接飙到 1400+ MiB,nvidia-smi 看着像泄漏

实测不是真泄漏,是分配器策略 + 清理姿势不对 + 预处理画蛇添足三件事叠一起。

根因一句话

Paddle 的 GPU 显存分配器默认会把“释放的块”囤在自己池子里不还给驱动,empty_cache()能不能把显存退给 nvidia-smi,取决于分配策略:

  • naive_best_fit(旧):预占一大块,池子锁死,empty_cache()基本无效

  • auto_growth(新,pip 版默认):按需cudaMalloc,空闲块可以被empty_cache()归还 ✅

但很多人用了auto_growth还是不回落,是因为清理顺序错了,或者预处理把输入 shape 搞出花样,导致 cuDNN workspace 越缓存越多。

解决办法(四步,照抄)

1. import paddle 之前设环境变量

import os # 关键:换 auto_growth,empty_cache 才管用 os.environ["FLAGS_allocator_strategy"] = "auto_growth" os.environ["FLAGS_fraction_of_gpu_memory_to_use"] = "0.3" # 30% 上限兜底 os.environ["FLAGS_initial_gpu_memory_in_mb"] = "512" os.environ["FLAGS_reallocate_gpu_memory_in_mb"] = "128" os.environ["FLAGS_cudnn_exhaustive_search"] = "0" os.environ["FLAGS_conv_workspace_size_limit"] = "64"

必须放在import paddle/import paddleocr最前面,晚了不生效。

2. 预处理别瞎缩放对齐

显存是被 det 的text_det_limit_side_len=960和 rec 固定高度卡死的,外部预缩放省不到显存,只会让小字识别率掉

不要做 32 倍数对齐,不要强行 resize 到小图,只转 RGB:

def preprocess_image(image_path): from PIL import Image with Image.open(image_path) as img: if img.mode not in ('RGB', 'L'): img.convert('RGB').save(image_path) return image_path

3. 正确的显存回收函数(顺序不能乱)

必须先等 kernel 跑完 → Python 断引用 → 再等一次 → 最后empty_cache()

import gc import paddle def clean_gpu_memory(force=False): # 节流:每 N 次清一次,别每次请求都 synchronize if not force: clean_gpu_memory._n += 1 if clean_gpu_memory._n < 15: return clean_gpu_memory._n = 0 paddle.device.synchronize() # 2.5+ 新 API,替代 cuda.synchronize() gc.collect() # 断 Python 侧 tensor 引用 paddle.device.synchronize() paddle.device.cuda.empty_cache() # 只有 auto_growth 下能真退回显存 clean_gpu_memory._n = 0

paddle.device.cuda.synchronize()2.5.0 起弃用,换成paddle.device.synchronize()

4. 推理完在 finally 里清一次

python

def process_single_image(path): start = time.time() result = None try: with _ocr_lock: # predictor 非线程安全,加锁 result = ocr.predict(preprocess_image(path)) return {'texts': parse(result), 'time_cost': round(time.time()-start, 4)} finally: del result clean_gpu_memory()

并发用 Flask 默认多线程时,Paddle inference predictor 不是线程安全的,不加锁显存峰值会翻倍,结果还可能串。

验证

服务起好后看这两个值:

curl http://localhost:19600/gpumem curl "http://localhost:19600/gpumem?clean=1"
  • allocated_mb每次识别完回落到基线 → 正常

  • reserved_mb高但 allocated 回落 → 只是池子缓存,不是泄漏

  • 强制 clean 后 reserved 往下掉 → auto_growth 生效

避坑补充

  • 不要在推理外面套paddle.no_grad():走的是 inference predictor,没有反向图,写了也没用

  • 不要在每次predict后都synchronize():阻塞等 kernel,白等;只在 clean 里同步

  • 文件大小限制在preprocess_image里 raise 别被同函数 except 吞掉,要往外抛

  • 同卡跑别的任务,用auto_growth+fraction=0.3naive_best_fit友好得多

改完同图识别:基线 576 → 峰值 ~680 → 清完回 580 左右,不再翻倍。

http://www.jsqmd.com/news/1299149/

相关文章:

  • OBS Spout2插件:三步告别视频传输限制,开启高效创作新时代
  • 查重率亮红灯反复修改,有哪些真正值得信赖的的降AIGC平台推荐?
  • 如何用AgentMemory管理Continue的会话记忆
  • B2B反向海淘独立站:自建VS采购SaaS系统,中小卖家最优选型指南
  • C语言填空题精讲:40道题巩固专升本与期末考点
  • 网络迷因与同人创作标题解析:从社群梗到内容传播策略
  • 二极管核心应用电路全解析:从整流、保护到信号处理实战
  • 2:大模型深度对比 | 五大场景实测
  • 2026年威海人防密闭接线盒生产厂家怎么选?这份严选指南给出3个关键考察点 - geo交流
  • 2026年优选指南:如何甄选运行稳定的耐高温喷射器技术方案? - geo交流
  • 商用变频空调APF提升背后,电流采样精度为什么影响压缩机控制?
  • STM32嵌入式开发:数组查表法实现多级菜单系统设计
  • 终极分屏解决方案:Tab-Resize浏览器扩展使用指南
  • 不平衡电网下VSG控制与PR控制器设计实践
  • 需求明明写得很长,Codex 还是跑偏:问题往往不是信息不够,而是没分层
  • 兰亭妙微交互设计公司分享:别让设计抛弃银发群体:5 个落地级适老化交互细节及产品优化
  • STM32最小系统板硬件设计全解析:从电源时钟到PCB布局实战
  • HTTP 500错误排查实战:从日志分析到代码防御的完整指南
  • 2026版小程序开发工具商户号支付配置——受理关系不存在
  • 2026人行通道闸场景选购指南:社区、写字楼、景区、工地适配方案
  • NCM音乐格式转换革命:解锁网易云音乐的终极自由
  • 2026年最新 国内专业智慧园区公司大盘点
  • 2026年烟台多管通风组合防水套管源头厂家优选指南:如何精准筛选高性价比方案? - geo交流
  • 5分钟极速配置:OpCore-Simplify智能OpenCore EFI生成工具完全指南
  • DLSS Swapper终极指南:3分钟学会智能切换DLSS版本,免费提升游戏性能45%
  • 无锡全域钢构厂房修缮甄选攻略:4 家专业彩钢瓦除锈防水翻新服务商实测测评 + 本地专属避坑全攻略 - 本地便民网
  • 百度网盘提取码智能获取工具:如何5秒破解资源分享密码难题
  • Python面向对象编程与对象拷贝机制详解
  • Python猜拳游戏:从基础实现到AI博弈与GUI开发的编程实践
  • 一个能把漏洞报告交到你手里的YASA SKILL