[英]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.