Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
zclcz opened this issue Jun 26, 2024 · 19 comments
Closed

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

zclcz opened this issue Jun 26, 2024 · 19 comments

Comments

@zclcz
Copy link

zclcz commented Jun 26, 2024

docker部署 套接字服务

启动一开始
start

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

@zclcz
Copy link
Author

zclcz commented Jun 26, 2024

image

@Gavin1937
Copy link
Contributor

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

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

@zclcz
Copy link
Author

zclcz commented Jun 27, 2024

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

@zclcz
Copy link
Author

zclcz commented Jun 27, 2024

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

@Gavin1937
Copy link
Contributor

可以在(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
Copy link
Contributor

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

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

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

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

@zclcz
Copy link
Author

zclcz commented Jun 27, 2024

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

@hiroi-sora
Copy link
Owner

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

@Gavin1937
Copy link
Contributor

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

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

@Gavin1937
Copy link
Contributor

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

@hiroi-sora
Copy link
Owner

hiroi-sora commented Jun 27, 2024

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

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

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

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

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

@Gavin1937
Copy link
Contributor

关掉mkl,还会不会有残留

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

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

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

@Gavin1937
Copy link
Contributor

Gavin1937 commented Jun 28, 2024

我把引擎放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
Copy link
Owner

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

这样吧,

  1. PR给我新分支 autoclean
  2. main分支docker文档里 clone 本仓库 这句话,改为引导用户去clone autoclean分支,比如 git clone --single-branch --branch autoclean https://github.com/hiroi-sora/PaddleOCR-json.git
    2. clone 本仓库,**然后在 `cpp` 文件夹下打开一个终端(或PowerShell)**

@Gavin1937
Copy link
Contributor

行了

hiroi-sora added a commit that referenced this issue Jun 29, 2024
更新内存问题相关文档 + 添加localhost作为套接字特殊地址 (#135)
hiroi-sora added a commit that referenced this issue Jun 29, 2024
@zclcz
Copy link
Author

zclcz commented Jul 1, 2024

行了

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

@Gavin1937
Copy link
Contributor

  • 首先,请确保你有下载autoclean分支,可以用命令 git branch 来查看。
  • 然后,清理内存的效果要在进行OCR之后才能看得出来区别,你可以随便跑一次OCR然后等待引擎清内存。为了方便测试,你可以在docker run命令的末尾加上参数-auto_memory_cleanup=30来加速。意思是:在没有任务30秒后清理内存(默认30分钟)。

@zclcz
Copy link
Author

zclcz commented Jul 2, 2024

  • -auto_memory_cleanup=30

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

@hiroi-sora
Copy link
Owner

hiroi-sora commented Jul 30, 2024

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

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

  • 如果作为桌面软件的OCR后端(如Umi-OCR)那样,闲时释放内存确实能提升用户体验。但桌面软件可以用脚本从外部重启进程来释放内存。
  • 如果作为服务端或Docker容器使用,管理员应该设计预留定额的内存给各个部署服务,闲时释放内存对服务器的意义有限。更重要的是确保单个服务的内存占用不超过某个上限。而 --cpu_mem 能实现这一点。
  • 闲时自动释放内存需要起多线程,且需要跨线程操作引擎实例,存在潜在的不稳定因素。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants