大家好,我是威哥。最近在河北燕郊的一个工业质检项目里栽了跟头——用C#写上位机调用YOLOv8做零件缺陷检测,结果单帧推理要220ms,QPS才4点多,内存还跟坐过山车似的,几分钟就飙到2G然后被GC按回去,客户现场的工控机直接卡成PPT。
被逼得没办法,把ONNX Runtime源码翻了个遍,又蹲在GitHub上看了几十个开源项目的实现,折腾了整整一周,终于把QPS拉到了16(刚好300%),内存也稳定在800M左右不飘了。今天把这整套优化方案分享给大家,全是实战踩出来的干货,没有半句虚的。
一、先看看最初的写法有多烂
一开始图省事,直接用了网上最常见的写法:每次来一张图片,先Resize到640×640,转成float数组,new一个DenseTensor,然后调用session.Run(),等结果出来再解析。
大概逻辑就是:图片 -> 预处理(Resize、归一化、HWC转CHW) -> new Tensor -> 同步推理 -> 解析结果 -> 释放Tensor。
问题在哪?第一,每次new Tensor和释放Tensor,GC压力巨大,尤其是640×640的彩色图,Tensor大小是13640*640=1,228,800个float,每次分配都要在托管堆里划一块内存,用完又要等GC回收,一来二去时间全浪费在这了。第二,同步推理意味着CPU预处理完就傻等GPU,GPU推理完又等CPU做后处理,GPU利用率常年在30%以下,纯属浪费性能。
二、第一刀:内存池复用,把GC按死在摇篮里
要解决内存问题,核心思路就
