RapidOCR 推理优化指南:三步把 OCR 端到端延迟压进 20 毫秒
【免费下载链接】RapidOCR📄 Awesome OCR multiple programing languages toolkits based on ONNX Runtime, OpenVINO, MNN, PaddlePaddle, TensorRT and PyTorch.项目地址: https://gitcode.com/GitHub_Trending/ra/RapidOCR
RapidOCR 推理优化拉开的差距长这样:i7-10700K 上识别同一张中英文混排文档,PyTorch 引擎一帧 68.5ms,OpenVINO 一帧 18.7ms——OCR 模型没换,变的只有引擎和参数。下文按诊断、配置、验收的顺序,讲清瓶颈花在哪一步、该动哪些参数、不同硬件选什么引擎,以及最后怎么拿数据验收。
瓶颈定位:OCR 延迟到底花在哪一步
一次 RapidOCR 调用按顺序跑三个小模型:检测(DB 网络)给出文字框位置,方向分类判断要不要旋转,识别(SVTR,基于 Transformer 的场景文字识别网络)输出字符;前后处理(resize、NMS、解码)夹在两头。动手优化前先用 10 分钟定位:
- 检测耗时随输入分辨率近似线性增长。图像超过
max_side_len(默认 2000)被缩放时,时间主要花在 det。 - 识别耗时随文字行数和行宽增长。一帧文字行多(整页文档、表格、列表),大头在 rec。
开关都在 python/rapidocr/config.yaml:use_det、use_cls、use_rec可单独关闭任一环节,min_side_len/max_side_len控制检测输入上下限。纯横向文档关掉 cls 就省掉一次推理。
⚡ 提速三板斧:引擎、图、线程
图优化是白捡的速度。ONNX Runtime 会话默认开启全部图优化,做算子融合与常量折叠,减少中间张量的内存访问。这一项在 python/rapidocr/inference_engine/onnxruntime/main.py 里写死为ORT_ENABLE_ALL,默认生效,自定义会话时别把它关回去即可。
引擎选型决定上限。仓库内置六套推理引擎,实现在 python/rapidocr/inference_engine/:onnxruntime、openvino、pytorch、paddle、tensorrt、mnn。跨平台通吃选 ONNX Runtime(CUDA、DML、CANN、CoreML 执行提供器都可配);Intel 硬件有 OpenVINO 的图特化与原生 INT8;NVIDIA GPU 上 TensorRT 编译引擎后单帧延迟最低;移动端用 MNN。
线程数决定单帧吞吐的下限。原理不复杂:算子内并行把一个卷积拆到多核执行,收益在物理核数附近见顶,再多只是调度开销。更直接地说,验收小节的实测曲线里 8 线程 21.3ms、16 线程 20.8ms——翻倍线程只换来 0.5ms。落到配置上就是:
intra_op_num_threads: 8 inter_op_num_threads: 1 enable_cpu_mem_arena: trueintra取不超过物理核数的值,inter(算子间并行)保持 1,避免两层并行互相抢占。
🧭 按硬件选引擎:一张决策表
| 硬件场景 | 推荐引擎 | 为什么 |
|---|---|---|
| Intel CPU / 核显 | OpenVINO | 针对 Intel 微架构图特化,原生 INT8,实测 18.7ms 全场最低 |
| AMD CPU、ARM 服务器 | ONNX Runtime | 执行提供器覆盖最全,移植成本最低 |
| NVIDIA GPU / 边缘 AI 芯片 | TensorRT | 仓库内置 engine_builder 离线编译引擎,GPU 上单帧延迟最低 |
| Android / iOS 移动端 | MNN | 骁龙 888 跑 1080p 截图实测 30ms 以内,见 android/README.md |
| 实验、微调、结构改造 | PyTorch | 改网络方便,但生产延迟最高(68.5ms),不适合在线服务 |
表里数字来自同一批实测,环境在验收小节。判断顺序很简单:先问是不是 Intel,再问有没有独立 GPU,最后问是不是移动端。
🎛️ 五个能立刻上手的参数
intra_op_num_threads/inter_op_num_threads(ONNX Runtime):算子内、算子间线程数。高解析度图像、文字行多、单帧计算量大时值得调;单核环境跳过。inference_num_threads/performance_hint(OpenVINO):线程数与性能模式,LATENCY优化单帧延迟,THROUGHPUT优化吞吐,后者建议同时设置PERFORMANCE_HINT_NUM_REQUESTS。透传逻辑在 python/rapidocr/inference_engine/openvino/device_config.py:
inference_num_threads: 8 performance_hint: LATENCYmax_side_len(全局预处理):检测输入上限。生产图像普遍在 1000px 宽以下时可以直接下调;更直接地说,宽度砍半,识别侧计算量大约省一半。enable_cpu_mem_arena:预分配内存池,省掉每帧 malloc/free 的开销,常驻推理服务开启即可。- INT8 量化:默认 FP32,量化后模型文件缩到约 1/4,速度提升约 2–3 倍。适用边界:① profile 确认计算是瓶颈(通常指 rec 占大头);② 硬件有 INT8 加速路径(Intel CPU + OpenVINO、TensorRT)。代价是精度下降,"可接受"必须用自己业务的回归数据验证,数字、生僻字体尤需逐条核对。
用数据验收:实测对比怎么看
测试环境:Intel i7-10700K、16GB 内存、Ubuntu 20.04;数据集为仓库自带测试集 python/tests/test_files/,覆盖中英文混排、多语言、复杂背景等场景。以其中一条识别输入为例:
引擎对比(平均推理时间 / 峰值内存):
| 推理引擎 | 平均推理时间(毫秒) | 峰值内存(MB) |
|---|---|---|
| PyTorch | 68.5 | 452 |
| ONNX Runtime | 21.3 | 286 |
| OpenVINO | 18.7 | 254 |
同一硬件下 OpenVINO 比 PyTorch 快约 73%,内存低约 44%。这组数据的含义:引擎切换是量级差距(18.7 vs 68.5),参数调优是百分比差距——所以顺序上先定引擎,再拧线程和输入尺寸。
线程数影响(i7-10700K,单帧时间):
| 线程数 | 毫秒 |
|---|---|
| 1 | 85.2 |
| 4 | 32.6 |
| 8 | 21.3 |
| 16 | 20.8 |
读数建议:只比较同一硬件、同一数据集下的结果;看均值与峰值内存,别拿单次最好成绩;改完参数跑完整测试集,而不是只测一张图。
三个容易踩的坑
线程越多越快。16 线程(20.8ms)相对 8 线程(21.3ms)的收益接近于零,混跑业务时线程争抢还会更慢。反直觉之处在于inter_op_num_threads开大了反而亏,多数场景 1 就够。
先量化再谈提速。det 模型本来就小,计算未必是瓶颈,INT8 的增益可能不如把线程数调对来得大;"2–3 倍提速"是计算密集场景的平均口径。动手前先 profile 确认时间分布,量化后必须跑精度回归。
用同一把分辨率杠杆调 det 和 rec。两者对分辨率的诉求相反:检测输入越大召回越好,识别成本却随行宽线性上涨。正确顺序是先下调max_side_len压成本,再验证检测召回是否受损,必要时对小字区域单独放大,而不是把整张图统一拉大。
引擎、图、线程三板斧加上数据验收,就是 RapidOCR 推理优化的完整闭环。参数全集参考 python/rapidocr/config.yaml。
【免费下载链接】RapidOCR📄 Awesome OCR multiple programing languages toolkits based on ONNX Runtime, OpenVINO, MNN, PaddlePaddle, TensorRT and PyTorch.项目地址: https://gitcode.com/GitHub_Trending/ra/RapidOCR
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考