我有一个使用subprocess模块的Popen运行的进程
result = subprocess.Popen(['tesseract','mypic.png','myop'])
st = time()
while result.poll() is None:
sleep(0.001)
en = time()
print('Took :'+str(en-st))其结果是:
Took :0.44703030586242676在这里,发出一个tesseract调用来处理图像mypic.png(附加)并将OCR的结果输出到myop.txt。

现在,我希望在代表这句话 (或参见这直接)的多个进程上发生这种情况,因此代码如下:
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,我发现了这个特定的错误,它在使用multiprocessing或pathos并行运行时花费了很多时间。因此,这是一个更大问题的缩小版本。我对此的问题可以找到这里。
无限循环的解释: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为止。
发布于 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。最优值取决于您的机器可以同时支持多少线程。
例如,在我的机器上:
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秒,在运行之间有很大的变化。
val = val | (1 << (i))例如,
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))打印输出,如
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循环非常复杂,速度也不是很快。
https://stackoverflow.com/questions/53838992
复制相似问题