PyTesseract 调用与多处理一起使用时工作速度非常慢

Moo*_*ter 3 python tesseract multiprocessing python-tesseract pathos

我有一个函数,它接收图像列表并在将 OCR 应用于图像后在列表中生成输出。我有另一个函数,通过使用多处理来控制此函数的输入。因此,当我只有一个列表(即没有多重处理)时,列表中的每个图像花费了大约 1 秒,但是当我将必须并行处理的列表增加到 4 时,每个图像花费了惊人的 13 秒。

为了了解问题的真正所在,我尝试创建一个最小的问题示例。在这里,我有两个函数eat25eat100它们打开一个图像name并将其提供给使用 API 的 OCR pytesseracteat25做25次,eat100做100次。

我的目标是在eat100没有多处理和eat25多处理(有 4 个进程)的情况下运行。理论上,eat100如果我有 4 个独立的处理器(我有 2 个内核,每个内核有 2 个线程,因此 CPU(s) = 4(如果我错了,请纠正我),这应该比我少 4 倍的时间)。

但是当我看到代码在打印“Processing 0”4次后甚至没有响应时,所有的理论都被浪费了。不过,单处理器功能eat100运行良好。

我测试了一个简单的范围立方函数,它在多处理中运行良好,所以我的处理器可以肯定运行良好。这里唯一的罪魁祸首可能是:

  • pytesseract: 看到这个
  • 代码不好?我做的不对。

`

from pathos.multiprocessing import ProcessingPool
from time import time 
from PIL import Image
import pytesseract as pt
def eat25(name):
    for i in range(25):
        print('Processing :'+str(i))
        pt.image_to_string(Image.open(name),lang='hin+eng',config='--psm 6')
def eat100(name):
    for i in range(100):
        print('Processing :'+str(i))
        pt.image_to_string(Image.open(name),lang='hin+eng',config='--psm 6')
st = time()
eat100('normalBox.tiff')
en = time()
print('Direct :'+str(en-st))
#Using pathos
def caller():
    pool = ProcessingPool()
    pool.map(eat25,['normalBox.tiff','normalBox.tiff','normalBox.tiff','normalBox.tiff'])
if (__name__=='__main__'):
    caller()
en2 = time()

print('Pathos :'+str(en2-en))
Run Code Online (Sandbox Code Playgroud)

那么,问题究竟出在哪里呢?任何帮助表示赞赏!

编辑:图像normalBox.tiff可以在这里找到。如果人们重现代码并检查问题是否仍然存在,我会很高兴。

Mik*_*rns 5

我是pathos作者。如果您的代码需要1s串行运行,那么在原始进程并行运行时很可能需要更长的时间。使用 naive process parallel 会产生开销:

  1. 必须在每个处理器上启动一个新的 python 实例
  2. 您的函数和依赖项需要序列化并发送到每个处理器
  3. 您的数据需要序列化并发送到处理器
  4. 反序列化也一样
  5. 您可能会遇到来自长期池或大量数据序列化的内存问题。

我建议检查一些简单的事情来检查您的问题可能出在哪里:

  • 尝试pathos.pools.ThreadPool使用线程并行而不是进程并行。这可以减少一些序列化和旋转池的开销。
  • 尝试pathos.pools._ProcessPool更改pathos管理池的方式。没有下划线,pathos将池保持为单例,并需要“终止”以明确终止池。使用下划线,当您删除池对象时,池就会消失。请注意,您的caller函数没有closejoin(或terminate)池。
  • 您可能想通过尝试dill.dumps并行处理的元素之一来检查序列化的数量。像大numpy数组这样的东西可能需要一段时间来序列化。如果传递的内容的大小很大,您可能会考虑使用共享内存数组(即 amultiprocess.Array或数组的等效版本numpy- 另请参阅:)numpy.ctypeslib以最小化每个进程之间传递的内容。

后者需要更多的工作,但如果您有很多要序列化的内容,则可以节省大量资金。没有共享内存池,所以multiprocess.Process如果你需要走那条路,你必须对单个对象进行 for 循环。