[英]python multiprocessing, make instance per process and reuse it
我正在使用pytesseract通过多处理方法进行一些ocr。
该方法如下所示:
tess_api = PyTessBaseAPI()
Parallel(n_jobs=4)(delayed(execute)(image) for image in images)
具有以下功能:
def execute(image):
tess_api.SetImage(image)
text = tess_api.GetUTF8Text()
这将导致并发问题,因为在工作程序2执行gettext()之前,工作程序1可能会覆盖映像。
现在的想法是让每个工人拥有一个PyTessBaseAPI
实例。 主要的想法是做类似的事情:
tess_apis = [PyTessBaseAPI(), PyTessBaseAPI(), PyTessBaseAPI(), PyTessBaseAPI()]
然后将tess_api[0]
给工作程序0,但我不知道如何在工作程序和实例之间建立连接。 有什么建议,或者什么是更好的方法? 因为我有成千上万张图像,所以我不想在execute函数中创建实例。
在每个工作进程开始读取其工作队列之前,使用Pool(initializer=...)
初始化Tesseract对象一次。
tess_api = None
def initialize_worker():
global tess_api
tess_api = PyTessBaseAPI() # initialize a copy for this instance
def execute(image):
tess_api.SetImage(image)
text = tess_api.GetUTF8Text()
def main():
with multiprocessing.Pool(initializer=initialize_worker) as p:
for result in p.imap_unordered(images, chunksize=10):
# ...
这仅在您使用实际流程时才有效; 如果您使用的是线程(考虑到Tesseract是C并会发布GIL,这可能会起作用),则可以使用contextvars
/ threading.local
。
Pool(initializer=...)
可以如上所述。 但是,如果您想做更复杂的事情,建议您使用Ray 。
然后可以表示如下。
import ray
ray.init()
@ray.remote
class Worker(object):
def __init__(self):
self.tess_api = PyTessBaseAPI()
def execute(self, image):
self.tess_api.SetImage(image)
return self.tess_api.GetUTF8Text()
# Create several Worker actors.
workers = [Worker.remote() for _ in range(4)]
# Execute tasks on them in parallel.
result_ids = [worker.execute.remote(image) for worker in workers]
# Get the results
results = ray.get(result_ids)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.