Darknet YOLOv4 Python环境下detect_image函数内存泄漏问题咨询
darknet.py
detect_image 函数无限循环场景内存泄漏排查与解决方法 第一步:定位泄漏类型
- 区分CPU内存泄漏还是CUDA显存泄漏:
- CPU内存占用通过
htop命令监控进程的RES字段变化 - CUDA显存占用通过
watch -n 1 nvidia-smi命令监控对应进程的显存使用
- CPU内存占用通过
- 做最小复现测试:注释掉循环内所有业务逻辑,仅保留
detect_image调用和空帧输入,确认泄漏来自该函数本身,排除业务代码的内存问题 - 可借助
gc模块验证Python层对象泄漏:每次循环后调用gc.collect(),如果内存上涨速度明显放缓,说明存在Python层未被回收的对象,可搭配objgraph工具统计未释放对象类型
常见泄漏原因与修复方案
1. 检测返回的darknet图片对象未手动释放
darknet底层为C语言实现,分配的图片内存不受Python GC管理,
detect_image返回的检测后图片如果不主动释放会持续堆积
- 修复方法:每次调用
detect_image处理完成后,手动调用释放接口:
import darknet detections, detected_img = darknet.detect_image(network, class_names, input_img, thresh=0.5) # 此处执行你的检测结果处理逻辑 # 处理完成后手动释放图片内存 darknet.free_image(detected_img)
2. OpenCV帧对象未正确回收
- 循环中通过
cv2.imread、cv2.VideoCapture读取的帧属于OpenCV Mat对象,高分辨率场景下如果不主动释放会快速堆积内存 - 修复方法:每次处理完的帧主动删除触发回收:
ret, frame = cap.read() if not ret: break # 帧预处理、检测逻辑 del frame
3. CUDA显存碎片累积
CUDA 10.2版本本身存在显存碎片回收不及时的问题,darknet检测时分配的临时显存如果不同步上下文会持续累积
- 修复方法:
- 每次检测完成后同步CUDA上下文:
import pycuda.driver as cuda # detect_image调用完成后添加同步逻辑 cuda.Context.synchronize()- 每运行100~1000次检测后手动清理显存缓存:
import torch torch.cuda.empty_cache()
4. darknet.py原生代码缺陷
- 部分公开版本的darknet.py中
detect_image函数内部创建的临时图片对象未做释放处理,可自行修改源码:找到函数内部通过darknet.make_image创建的临时im对象,在函数return之前添加darknet.free_image(im)即可。
内容的提问来源于stack exchange,提问作者Philipp
相关产品推荐
相关产品推荐

