我有一个函数,它接收图像列表,并在将OCR应用到图像之后,在列表中生成输出。我有另一个函数,它通过使用多处理来控制这个函数的输入。因此,当我有一个列表(即没有多处理)时,列表的每个图像都需要1s,但是当我将必须并行处理的列表增加到4个时,每个图像都得到了惊人的13s。
为了了解问题的真正所在,我尝试创建一个最小的问题工作示例。这里我有两个函数eat25
和eat100
,它们打开一个图像name
并将其提供给使用API pytesseract
的OCR。eat25
做了25次,eat100
做了100次。
我在这里的目标是在没有多处理的情况下运行eat100
,用多处理运行eat25
(有4个进程)。从理论上讲,如果我有4个不同的处理器(我有2个内核,每个内核有2个线程,因此CPU=4(如果我错了,请纠正我的错误),那么这就应该比eat100
少4倍。
但是,当我看到代码在打印“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))
那么,问题到底在哪里?任何帮助都是非常感谢的!
编辑:图像normalBox.tiff
可以找到这里。如果人们复制代码并检查问题是否继续,我将非常高兴。
发布于 2018-11-30 17:33:04
我是pathos
的作者。如果您的代码需要1s
连续运行,那么在天真的进程并行中运行很可能需要更长的时间。使用简单的进程并行是有开销的:
我建议检查一些简单的东西,以检查您的问题可能在哪里:
pathos.pools.ThreadPool
使用线程并行而不是进程并行。这可以减少串行化和旋转池的一些开销。pathos.pools._ProcessPool
来更改pathos
管理池的方式。没有下划线,pathos
将池保持为单例,并且需要一个“终止”来显式地杀死池。使用下划线时,当删除池对象时,池将停止。请注意,您的caller
函数没有close
或join
(或terminate
)池。dill.dumps
来检查序列化的程度。像大型numpy
数组这样的东西可能需要一段时间才能序列化。如果传递的内容很大,您可以考虑使用共享内存数组(即multiprocess.Array
或numpy
数组的等效版本--参见:numpy.ctypeslib
)来最小化每个进程之间传递的内容。后者是更多的工作,但如果您有大量的序列化,可以提供巨大的节省。没有共享内存池,因此如果需要执行该路由,则必须对单个multiprocess.Process
对象执行for循环。
https://stackoverflow.com/questions/53468446
复制相似问题