首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多个子进程需要很长时间才能完成。

多个子进程需要很长时间才能完成。
EN

Stack Overflow用户
提问于 2018-12-18 18:23:38
回答 1查看 2.1K关注 0票数 2

我有一个使用subprocess模块的Popen运行的进程

代码语言:javascript
复制
result = subprocess.Popen(['tesseract','mypic.png','myop'])
st = time()
while result.poll() is None:
    sleep(0.001)
en = time()

print('Took :'+str(en-st))

其结果是:

代码语言:javascript
复制
Took :0.44703030586242676

在这里,发出一个tesseract调用来处理图像mypic.png(附加)并将OCR的结果输出到myop.txt

现在,我希望在代表这句话 (或参见这直接)的多个进程上发生这种情况,因此代码如下:

代码语言:javascript
复制
lst = []
for i in range(4):
    lst.append(subprocess.Popen(['tesseract','mypic.png','myop'+str(i)]))

i=0
l = len(lst)
val = 0 
while(val!=(1<<l)-1):
    if(lst[i].poll() is None):
        print('Waiting for :'+str(i))
        sleep(0.01)
    else:
        temp = val
        val = val or (1<<(i))
        if(val!=temp):
            print('Completed for :'+temp)
    i = (i+1) %l

这段代码所做的是对tesseract进行4次调用,将流程对象保存在一个列表lst中,遍历所有这些对象,直到完成--所有的。对无限循环的实现在底部给出了说明。

这里的问题是,后一个程序花了很长时间才能完成。它一直在使用poll()函数(即None )等待进程完成,直到进程尚未完成为止。这不应该发生的。只要超过0.44秒就可以了。不会像10分钟那样!为什么会发生这种情况?

通过深入研究pytesseract,我发现了这个特定的错误,它在使用multiprocessingpathos并行运行时花费了很多时间。因此,这是一个更大问题的缩小版本。我对此的问题可以找到这里

无限循环的解释:val最初是0。当ith流程完成时,它是带有ORed和2^i的。因此,如果有3个进程,那么如果第一个进程(i=0)完成了,那么2^0 = 1就可以用val使其变为1。当第二个和第三个进程完成时,val变成2^0 \ 2^2 = 7。2^3-1也是7个。所以循环一直工作到val等于2^{number of processes}-1为止。

EN

Stack Overflow用户

回答已采纳

发布于 2018-12-19 03:59:09

常见问题 (我的重点是):

在处理一个页面时,Tesseract 4也会消耗最多4个CPU线程,因此对于单个页面,它将比Tesseract 3更快。 如果您的计算机只有两个CPU核心,那么运行四个线程将大大减慢速度,最好是使用一个线程,或者最多使用两个线程!使用单个线程的消除了多线程的计算开销,也是处理大量图像的最佳解决方案,每个CPU核心运行一个Tesseract进程。 使用环境变量OMP_THREAD_LIMIT设置最大线程数。 若要禁用多线程,请使用OMP_THREAD_LIMIT=1。

因此,如果希望同时运行多个tesseract进程,则可能希望减少(或试验) OMP_THREAD_LIMIT。最优值取决于您的机器可以同时支持多少线程。

例如,在我的机器上:

代码语言:javascript
复制
import subprocess
import time
import os 

t = time.perf_counter()    
tasks = [('mypic.png', 'myop{}'.format(i)) for i in range(4)]
procs = [subprocess.Popen(['tesseract', infile, outfile], env={'OMP_THREAD_LIMIT':'1'})
         for infile, outfile in tasks]
for proc in procs:
    proc.wait()
print('{} s'.format(time.perf_counter()-t))

在0.220秒内完成,而没有env={'OMP_THREAD_LIMIT':'1'}的相同代码通常需要3.1-5.1秒,在运行之间有很大的变化。

要使代码正常工作,请使用|而不是or

代码语言:javascript
复制
val = val | (1 << (i))

例如,

代码语言:javascript
复制
import time
import subprocess
lst = []
for i in range(4):
    lst.append(subprocess.Popen(['tesseract', 'mypic.png', 'myop'+str(i)]))

i = 0
l = len(lst)
val = 0
counter = 0
while(val != (1 << l)-1):
    if(lst[i].poll() is None):
        time.sleep(0.001)
    else:
        temp = val
        val = val | (1 << (i))
        if(val != temp):
            print('Completed for : {}'.format(i))
    i = (i+1) % l

    counter += 1
print('{} iterations'.format(counter))

打印输出,如

代码语言:javascript
复制
Completed for : 1
Completed for : 2
Completed for : 3
Completed for : 0
6121 iterations

注意,循环仍然迭代数千次,主要是在lst[i].poll()返回None时,但也因为i = (i+1) % l可以多次重新访问相同的值。如果一次迭代需要0.001s,那么6121次迭代将花费6.121秒。因此,while循环非常复杂,速度也不是很快。

票数 2
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53838992

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档