hiroi-sora / RapidOCR-json

OCR离线图片文字识别命令行windows程序,以JSON字符串形式输出结果,方便别的程序调用。基于 RapidOcrOnnx 。
MIT License
172 stars 30 forks source link

[GPU适配] 适配进行中 #13

Open qwedc001 opened 7 months ago

qwedc001 commented 7 months ago

· 使用环境为VS 2022,nvcc参数如下

nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2023 NVIDIA Corporation
Built on Tue_Jul_11_03:10:21_Pacific_Daylight_Time_2023
Cuda compilation tools, release 12.2, V12.2.128
Build cuda_12.2.r12.2/compiler.33053471_0

· CPU版本编译成功 · GPU版本在CPU版本的基础上按照GPU编译指南下载了GPU对应库,并且在generate vs project里更改了生成参数重定向到cuda参数 · vs编译未出现异常 · 编译后尝试运行,出现以下提示

PixPin_2024-01-31_15-43-45

不是很清楚这个given version是哪里来的,于是就卡死了( 初步怀疑是models的问题,但是我又不能确定,我一会去找找低版本的models试试看

qwedc001 commented 7 months ago

然后如果我想的不错的话,可能编译出来GPU版本可以直接拿来替换掉CPU版本,只要models正确的话

hiroi-sora commented 7 months ago
  1. 按我的理解,确实是GPU版本编译出来的exe可以直接替换CPU版的exe,模型库不用动。模型理论上是通用的。
  2. 你在运行GPU版本时,有没有传入参数--GPU=0 ?按照 源码 ,默认应该是不使用GPU(为-1)的。
  3. 如果 RapidOCR-json 的问题难以解决,可以尝试先编译 RapidOcrOnnx 项目本身,看看那边能否编译、正常运行。
qwedc001 commented 7 months ago

刚刚重新测试了一下 1.本报错与模型目录无关,将exe独立摘出仍然会提示此错误,我无法定位这个错误提示的源码 2.尝试传入GPU=0,无效 3.正在尝试编译RapidOcrOnnx

qwedc001 commented 7 months ago

尝试进行了RapidOcrOnnx编译,仍然出现此提示,已经转发到RapidOcr的交流群

qwedc001 commented 7 months ago

依据RapidOCR交流群提供的消息,onnxruntime 对cuda和cudnn的版本有特定的要求。针对不同的cuda和cudnn,很可能需要提供不同的编译版本。 这样的话,需要寻找一部分装载有不同cuda和cudnn的用户来进行测试后才能正式发布GPU版本,并且要提供cuda和cudnn安装方式。 在RapidOCR官方群提供的编译版本在我的机器下可以正常运行,我去寻找一下对应环境的runtime尝试编译一下

qwedc001 commented 7 months ago

另外依据群内消息,根据此篇博文,也有可能是编译的时候产生的动态库链接错误。如果是这样的话只需要替换一次动态库即可解决问题,我测试一下

hiroi-sora commented 7 months ago

也就是说,必须客户机先安装CUDA,才能使用GPU版的RapidOcrOnnx吗?

有没有可能将特定版本的CUDA核心库(几个dll)放置到RapidOcrOnnx的路径下,让它优先使用我们提供的cuda(而不是系统安装的)?

类似: https://blog.csdn.net/zhangfuliang123/article/details/71757961

qwedc001 commented 7 months ago

不,现在定位的问题很有可能是windows在system32下内置一个旧版本的onnxruntime.dll导致的。

另外依据群内消息,根据此篇博文,也有可能是编译的时候产生的动态库链接错误。如果是这样的话只需要替换一次动态库即可解决问题,我测试一下

我正在尝试修复这个问题,但是我没有无cuda的gpu机器能对其进行无cuda环境测试,至于这个cuda要不要安装可能要延后测试。

qwedc001 commented 7 months ago

windows的dll查找优先级应该是先同级目录再system32的,不过我这里产生了很奇怪的情况,把正常运行的onnx从RapidOCR范例拷贝到我自己编译的OCR还是不能正确链接,我再想想

Edit:正在使用windbg进一步检查

qwedc001 commented 7 months ago

也就是说,必须客户机先安装CUDA,才能使用GPU版的RapidOcrOnnx吗?

有没有可能将特定版本的CUDA核心库(几个dll)放置到RapidOcrOnnx的路径下,让它优先使用我们提供的cuda(而不是系统安装的)?

类似: https://blog.csdn.net/zhangfuliang123/article/details/71757961

依据RapidOCR开发者提供的消息,需要使用到的cuda和cuddn DLL依赖高达1G,并且不开源。并不是几个DLL就能解决的问题,必须要整体安装。

PixPin_2024-02-05_19-50-33

我会优先解决onnxruntime的问题,确保编译的RapidOCR-json能正常运作,至于依赖问题我可以先尝试一下您给出的博文,如果不可行就只能安装了。

qwedc001 commented 7 months ago

经过替换旧版本库(onnxruntime-1.14)进行重新编译,现在在RapidOCR-json下内置onnxruntime.dll之类库的情况下已经可以正常在本机使用。我会在我fork的repo底下提供一份release样本。 接下来需要验证的是无cuda环境和新onnx库的执行情况。

执行参数:RapidOCROnnx.exe --GPU=0 采用内部json传入

执行情况:第一次执行约有40秒的无响应,输出结果后从第二次开始几乎秒出。可以认为第一次执行是初始化。

PixPin_2024-02-06_14-44-12
qwedc001 commented 7 months ago

补充:经过测试,无CUDA机不能够正常启动此程序,会无提示闪退。

hiroi-sora commented 7 months ago

你可以在你仓库里写个GPU版构建说明,各个工具、库的版本都罗列清楚。过阵子我也会参考试试。

qwedc001 commented 7 months ago

我成功把onnx库的版本(包括onnx-static和onnx-gpu)提升到了1.16,然后意识到第一次的运行失败很有可能源自我没有搞明白文件夹结构。 在搞明白结构以后,我有一个比较大胆的推测是我们可以直接使用github actions来自动构建,因为升级的流程几乎只是将依赖替换,甚至高版本抛弃了一部分文件夹结构以后会更简单。 onnx gpu前两天发布了1.17,我会再尝试编译一个1.17来验证我的猜想。1.16版本的内容已经上传到release,GPU版的构建说明稍晚上传到github

qwedc001 commented 7 months ago

Update:发现一个非常严重的问题 目前存在可能性,编译机使用的cuda和客户机的小版本不同,会导致直接闪退。 至少从群里得到的回复是这样的,甚至cudnn版本也可能会影响这个过程。 如:本机编译使用cuda为12.2,测试机使用cuda为12.3,闪退无输出。 拉上了人一起来测试。如果多测几轮确实如此那这个适配问题就有点令人头疼了()

qwedc001 commented 7 months ago

经过几轮排查和在RapidOCR群的询问,可以做出的猜测为onnx runtime的gpu版本与cuda兼容性呈现相关。 具体的runtime-cuda版本对应表来源此链接。

https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html

我没有很接触过cuda类编程,也没有查询到具体哪一个版本号的cuda支持哪一代GPU,可能需要再找点材料才能明确这个问题。

GPU的构建指南今天就写出来

qwedc001 commented 7 months ago

折腾了两周无果,不知道为何还是只有我的电脑能运行 我的建议是要不然我先把Rapid官方编译的GPU版本传上来,您试一试能不能打开,如果可以的话再尝试构建RapidOCR-json-gpu

qwedc001 commented 7 months ago

好我刚发完没多久 刚刚在RapidOCR群发现一位在尝试用RapidOCR-json项目搞GPU的,然后让他尝试了一下我的程序,他跑起来了 现在的情况是能跑起来RapidOCR官群提供的群文件GPU版本,应该就能跑起来我编译的RapidOCR-json,应该还是涉及到客户机的cuda和cudnn配置,等着我找时间尝试复现一下

hiroi-sora commented 7 months ago

嗯嗯,辛苦了~

GPU版的兼容性和适配难度我是有预料的。编译和构建只是最初的一步,在各种机器上确保兼容性才是最麻烦的工作。

我目前在忙着Umi v2.1.0的补充工作,暂时没有时间顾及这边。不过你有什么进展,可以将最新编译的包扔到你的release,我有空会测试测试。

我还有一个想法:既然CUDA的安装本身需要一定门槛,且兼容性问题真的难以解决。并且,假设需要用GPU加速的都是有一定动手能力的用户。则我们可以只提供docker版本GPU-OCR引擎(让docker去解决不同系统的适配问题)。用户可以在linux上,或者windows+WSL上安装它,然后Umi的插件通过端口调用该引擎。

进一步的,或许可以将Umi-OCR项目分裂为桌面版本和服务器版本( https://github.com/hiroi-sora/Umi-OCR/issues/351#issuecomment-1952319746 ),桌面版只提供基础的CPU-OCR插件,服务器版则支持GPU插件;桌面版Umi可以调用服务器版提交OCR任务。

qwedc001 commented 7 months ago

收到了,docker那边我没有研究过,可能等着过段时间专门找点时间去看看 现在也找到在用这个项目并且愿意帮我测试GPU的朋友了,有进展我会在这里更新的 服务器端就要依靠其他大佬了,我在这里暂且打call

qwedc001 commented 7 months ago

Docker版本进展非常顺利,原项目RapidOCR-Onnx已经能够正常跑起来,下面开始着手测试RapidOCR-json

qwedc001 commented 7 months ago

有源代码需要修改了

PixPin_2024-02-21_14-36-09

目前还不能确定类似这样windows特供的代码有多少,但是如果要用linux环境编译这些东西肯定都不能要,得想办法改一下

hiroi-sora commented 7 months ago

RapidOCR-json 这边我没有写多平台适配的代码,PaddleOCR-json 那边写了。

你可以参考一下这些文件,它们可以实现复用大部分共通代码,而独立使用不同平台的独特代码:

https://github.com/hiroi-sora/PaddleOCR-json/blob/main/cpp/src/task.cpp https://github.com/hiroi-sora/PaddleOCR-json/blob/main/cpp/src/task_win32.cpp

不过这部分的工作量可能不小。我想了想,如果真的要走docker这条路的话,也许没有必要抓着我的 -json 魔改版不放(这个项目的意义就是简化在桌面平台的部署难度)。PaddleOCR官方本身也提供了比较方便的docker部署方案,用现成的也不错。

参考: https://github.com/PaddlePaddle/PaddleOCR/tree/release/2.7/deploy/fastdeploy/serving

值得调查的是:

  1. PaddleOCR的docker容器是基于python的,理论上性能比C++版慢。咱需要测试开启CUDA后,它跟 RapidOCR-GPU 或别的C++引擎比,性能差距能否接受。
  2. 可否编写一个 .sh 脚本,实现一键部署,简化用户的上手难度。
  3. 编写一个Umi-OCR的插件,调用 官方客户端代码 )的接口,与docker中的OCR引擎交互。
  4. 官方文档只写了支持 v3 模型,但fastdeploy理论上是支持 v4 模型的,不知道是不是文档笔误,可以测试下v4模型可否使用。

总之,只要能实现目标(让Umi能用上GPU,且用户友好)的方法就是好方法,而不必纠结于实现方式。

qwedc001 commented 7 months ago

明确了,这样我先去研究一下PaddleOCR-json的GPU复用,现在已经可以确认docker版本部署两个原项目问题不大 在部署的层面,如果使用docker,那么实际上用户要执行的内容也就只有docker build(或者docker pull,如果把镜像传到docker hub上的话)和docker run,这样唯一的大前提就是开启WSL2,安装Docker for Windows 至于Umi-OCR的插件,可能要等到docker这里确认稳定以后再去编写了,直接调用不大可行了,需要在dockerfile里面写明暴露某个端口通过API的方式访问

qwedc001 commented 7 months ago

不过我需要额外提醒的是,虽然Docker的一键部署可以有效的解决依赖冲突并顺利跑起来OCR引擎,但是在执行完build之后他的image达到了惊人的11GB,并且目前我没有较好的办法可以简化image大小。 (其中:作为parent image的nvidia/cuda镜像大小约为6.5G,剩下的主要占用应该来源于在构建过程中通过apt安装的build-essential以及cmake)

1 2