gpt4 book ai didi

python - 多个子流程需要很长时间才能完成

转载 作者:行者123 更新时间:2023-12-04 18:29:47 25 4
gpt4 key购买 nike

我有一个使用 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 .

enter image description here

现在我希望这代表 this comment 在多个进程上发生(或见 this directly ),所以代码在这里:
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 .所以这是一个更大问题的缩小版本。我的问题可以找到 here .

无限循环的解释: val最初为 0。它与 2^i 进行或运算当第 i 个过程完成时。因此,如果有 3 个进程,那么如果第一个进程(i=0)完成,那么 2^0 = 1val 进行或运算1. 完成第二和第三道工序后, val变成 2^0 | 2^1 | 2^2 = 7. 和 2^3-1也是 7。所以循环一直工作到 val等于 2^{number of processes}-1 .

最佳答案

根据 the faq (我强调):

Tesseract 4 also uses up to four CPU threads while processing a page, so it will be faster than Tesseract 3 for a single page.

If your computer has only two CPU cores, then running four threads will slow down things significantly and it would be better to use a single thread or maybe a maximum of two threads! Using a single thread eliminates the computation overhead of multithreading and is also the best solution for processing lots of images by running one Tesseract process per CPU core.

Set the maximum number of threads using the environment variable OMP_THREAD_LIMIT.

To disable multithreading, use 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 秒之间,运行之间有很多变化。

要使您的代码正常工作,请使用 binary bitwise or operator, | 而不是 logical or operator, or :
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.121s。所以 while循环很复杂而且不是很快。

关于python - 多个子流程需要很长时间才能完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53838992/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com