python 多处理,为每个进程创建实例并重用它
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()
这会导致并发问题,因为 Worker 1 可能会在 Worker 2 执行 gettext() 之前覆盖图像
现在的想法是让每个工人拥有一个 PyTessBaseAPI
实例。
主要想法是做类似的事情:
tess_apis = [PyTessBaseAPI(), PyTessBaseAPI(), PyTessBaseAPI(), PyTessBaseAPI()]
然后将tess_api[0]
交给worker 0但是我不知道如何在worker和instance之间建立连接。
有什么建议,或者更好的方法是什么?
因为我有成千上万的图像,所以我不想在执行函数中创建实例。
在每个工作进程开始读取其作业队列之前,使用 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)
您可以阅读有关 Ray in the documentation 的更多信息。请注意,我帮助开发 Ray。
我正在使用 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()
这会导致并发问题,因为 Worker 1 可能会在 Worker 2 执行 gettext() 之前覆盖图像
现在的想法是让每个工人拥有一个 PyTessBaseAPI
实例。
主要想法是做类似的事情:
tess_apis = [PyTessBaseAPI(), PyTessBaseAPI(), PyTessBaseAPI(), PyTessBaseAPI()]
然后将tess_api[0]
交给worker 0但是我不知道如何在worker和instance之间建立连接。
有什么建议,或者更好的方法是什么?
因为我有成千上万的图像,所以我不想在执行函数中创建实例。
在每个工作进程开始读取其作业队列之前,使用 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)
您可以阅读有关 Ray in the documentation 的更多信息。请注意,我帮助开发 Ray。