我想在目前使用多处理实现的程序中使用spaCy。具体来说,我正在使用ProcessingPool
来生成4个子进程,然后这些子进程就会完成他们的快乐任务。
要使用spaCy(专门用于POS标记),我需要调用spacy.load('en')
,这是一个昂贵的调用(需要大约10秒)。如果我要在每个子进程中加载此对象,则需要约40秒,因为它们都是从同一位置读取的。这太烦人了。
但我无法弄清楚让他们分享正在加载的对象的方法。这个对象不能被腌制,这意味着(据我所知):
Pool.map
来电Manager
实例无法存储和使用它,然后在进程间共享我该怎么办?
答案 0 :(得分:2)
我不知道你如何准确使用Pool.map
,但请注意Pool.map
不能处理大量输入。在Python 3.6中,它在Lib/multiprocessing/pool.py中实现,如您所见,它声明它需要iterable
作为第一个参数,但实现在运行多进程映射之前执行consume the whole iterable。因此,如果您需要处理大量数据,我认为您不需要Pool.map
。也许Pool.imap
和Pool.imap_unordered
可以有效。
关于您的实际问题。我有一个不涉及Pool.map
的解决方案,并且类似多进程foreach
。
首先,您需要继承Pool
并创建一个工作进程:
from multiprocessing import cpu_count
from multiprocessing import Queue
from multiprocessing import Process
class Worker(Process):
english = spacy.load('en')
def __init__(self, queue):
super(Worker, self).__init__()
self.queue = queue
def run(self):
for args in iter(self.queue.get, None):
# process args here, you can use self.
您准备了这样的流程池:
queue = Queue()
workers = list()
for _ in range(cpu_count()): # minus one if the main processus is CPU intensive
worker = Worker(queue)
workers.append(worker)
worker.start()
然后您可以通过queue
for args in iterable:
queue.put(args)
iterable
是您传递给工作人员的参数列表。上面的代码会尽可能快地推送iterable
的内容。基本上,如果工人足够慢,几乎所有的iterable都会在工人完成工作之前被推到队列中。这就是为什么迭代的内容必须适合内存。
如果工人的论点(又名。iterable
)不能适应记忆,你必须以某种方式同步主要的工作流程和工人......
最后请务必致电以下人员:
for worker in workers:
queue.put(None)
for worker in workers:
worker.join()