hiroi-sora / PaddleOCR-json

OCR离线图片文字识别命令行windows程序,以JSON字符串形式输出结果,方便别的程序调用。提供各种语言API。由 PaddleOCR C++ 编译。
Apache License 2.0
954 stars 126 forks source link

好似内存不能自动释放 #135

Closed zclcz closed 4 months ago

zclcz commented 4 months ago

docker部署 套接字服务

启动一开始 start

运行一段时间后 识别了很多图片 然后中间闲置一天 但是内存一直不下来 end

zclcz commented 4 months ago

image

Gavin1937 commented 4 months ago

你好,这是由mkldnn加速库激进的内存调度策略而导致的问题。一个绕过该问题的方法是:让另一个进程来管理引擎的运行,每隔一段时间就重启引擎来释放内存(Umi-OCR用的就是这种策略)。

具体细节可以看看这两个Issues:#43、#90

zclcz commented 4 months ago

如果使用重启策略的话 我是docker部署的怎么监听和重启呢还是内部重启的 这边可以给一下代码吗

zclcz commented 4 months ago

看了一下其他的issue 这里可以改为套接字参数的方式配置最大占用内存触发重启 以及空闲多少秒重启引擎吗 还有Java这块demo套接字传入的配置参数没有运行是无效的

Gavin1937 commented 4 months ago

可以在(Umi-OCR的仓库里)[https://github.com/hiroi-sora/Umi-OCR]找找看。不过主要就是以下几种方法

  1. 直接在外部重启docker容器。可以直接让调用api的进程来重启,或者让另一个脚本来重启。
  2. 写一个简单的python中间层并放到docker里面,让中间层来管理引擎进程。监听引擎的输出来判断当前是否有OCR工作,然后就可以在工作间隙重启引擎。
  3. 修改引擎本身,加一个简单的自动清理内存的功能(需要熟悉C++)。

PaddleOCR-json 之后将会重构,跟进PaddleOCR v2.7+ 版本,这个版本已经解决了内存泄漏的问题。所以说PaddleOCR-json短期内应该不会处理这个问题。

不过我觉得可以先加一个临时的内存清理功能用着先,之后重构时再去掉。你怎么看 @hiroi-sora

Gavin1937 commented 4 months ago

改为套接字参数的方式配置最大占用内存触发重启

引擎内部是没有直接触发重启的机制的

还有Java这块demo套接字传入的配置参数没有运行是无效的

如果你是用java demo来调用的docker容器api的话,输入参数是没用的。因为java api的参数是直接输入给一个本地进程的,而docker容器会自动启动引擎进程。

zclcz commented 4 months ago

这边纯Java服务端调用的应用 其他语言编程能力几乎为0 很多地方不懂也不会改代码 目前这个版本好像会固定吃掉1200M内存 我先上线使用吧 待后续有更新优化我再重新构建docker镜像使用

hiroi-sora commented 4 months ago

我想一下,能否把Umi那一套 http api 的模块拆分出来,这样就能实现自动化的外部内存管理

Gavin1937 commented 4 months ago

我想一下,能否把Umi那一套 http api 的模块拆分出来,这样就能实现自动化的外部内存管理

我加了一个简单的内存管理功能,直接新开一条线程来清理PPOCR对象,在这个branch。和外部内存管理相比,这个方案不需要额外带一个python程序和环境,但是内存清理的不太干净,在我的机子上最终会保持600MB的占用(引擎初始占用只有100MB)。

Gavin1937 commented 4 months ago

另外我觉得可以新开一个issue来讨论引擎重构相关的内容。多大幅度的重构?具体要去掉/增加什么功能?引擎上面的API和Umi-OCR要跟着改动多少?等等。这样也方便其他开发者来贡献。

hiroi-sora commented 4 months ago

但是内存清理的不太干净,在我的机子上最终会保持600MB的占用

看了你的代码,按理说 det cls rec 三个模型对象都已经删除了,也许是mkl的占用没删。试下命令行 -enable_mkldnn=false 关掉mkl,还会不会有残留。

如果关掉mkl就没有残留了,说明引擎进程中不管怎么改都无法实现完全的重启,必须用外部进程来管理,将引擎进程kill掉才能释放所有占用的内存。

我觉得可以新开一个issue来讨论引擎重构相关的内容。多大幅度的重构?具体要去掉/增加什么功能?引擎上面的API和Umi-OCR要跟着改动多少?

明白。不过我最近较忙,大幅度的改动可能等过段时间看看

Gavin1937 commented 4 months ago

关掉mkl,还会不会有残留

关掉了还有残留。在我的机子上:引擎初始占用100MB,跑一次OCR之后变成575MB,之后自动清理内存后变成525MB。 我估计有可能是底层的哪个依赖开辟的资源没有被清空,比如说底层依赖开的线程没被清理掉。 不过貌似引擎的内存占用最终还是会达到一个平衡点后不再增长,我挂机一晚上看看。

不过我最近较忙,大幅度的改动可能等过段时间看看

我接下来下半年也比较忙,有时间我就看看。

Gavin1937 commented 4 months ago

我把引擎放docker里挂着测试了差不多一天,感觉应该没问题。

总共做了两次测试,第一次是:引擎在30分钟没有OCR任务后就清理内存,然后我让另一个python脚本每隔20分钟就发送一个OCR任务给引擎。在这种情况下,引擎完全没有清理内存的时间,内存占用是按照输入的OCR任务来的,在达到一个上限后就稳定起来了。

(横轴时间、纵轴内存占用) image

再意识到第一次测试测不到内存清理功能后我又做了第二次测试:这次让引擎在30分钟没有OCR任务后就清理内存,然后另一个python脚本每隔50分钟就发送随机0~10个OCR任务给引擎。

(横轴时间、纵轴内存占用。在第4小时之后我就把python脚本停下了) image

这次就好很多了,内存清理有在正常工作。只要没有频繁的OCR任务,引擎内存占用就会降下来到一个固定值(在我这里是600MB左右)。

不过内存确实是清理不干净,估计某些依赖的资源没有被完全释放。我检查了一下OCR的输出,没发现什么问题,所以这个功能应该不影响OCR?

下面是测试用的数据、脚本、和结果。结果是那些*.log.*文件,第一次测试的python结果被不小心覆盖掉了。 test_data.zip

没有问题的话我就整理一下发个PR。

hiroi-sora commented 4 months ago

没有问题的话我就整理一下发个PR

这样吧,

  1. PR给我新分支 autoclean
  2. main分支docker文档里 clone 本仓库 这句话,改为引导用户去clone autoclean分支,比如 git clone --single-branch --branch autoclean https://github.com/hiroi-sora/PaddleOCR-json.git https://github.com/hiroi-sora/PaddleOCR-json/blob/6bbf2f36dfe1ca686d9d0b267df520a3e2ab901a/cpp/README-docker.md?plain=1#L8
Gavin1937 commented 4 months ago

行了

zclcz commented 4 months ago

行了

我重新clone了代码 重新构建了docker镜像 运行了一下 请问这属于释放内存了吗 感觉只释放了20兆 image

Gavin1937 commented 4 months ago
zclcz commented 4 months ago
  • -auto_memory_cleanup=30

image Merge了autoclean之后验证可以了 docker运行增加参数30s清理内存 效果很明显

hiroi-sora commented 3 months ago

v1.4.1 新测试版跟进了 PP-OCR 最新推理库,在内存控制方面有了很大优化,连续执行OCR任务的内存占用为 1.5GB 左右(以前>2.5GB)。另外,新增了参数 --cpu_mem ,控制内存占用上限。

https://github.com/hiroi-sora/PaddleOCR-json/releases/tag/v1.4.1-dev

不过,新版本中我没有正式引入 空闲时自动释放内存 的功能。原因: