我有许多独立的任务,它们读取但不写入相同的 gensim 模型,大小约为 3.6GB。(Gensim 是一个基于 numpy 构建的主题建模库。)所以我决定通过首先从文件中加载 gensim 模型来并行化它们:
from gensim.models.word2vec import Word2Vec
from multiprocessing import Pool
model = Word2Vec.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)
然后将model
作为参数传递给要运行的进程池doWork
:
def doWork(experiment, doc):
print "Begin working"
# do some work here; access model by experiment.model
class Experiment(object):
def __init__(self, model, docs):
self.model = model
self.docs = docs
def run(self):
pool = Pool(processes = 4)
print "Done preparing"
results = pool.map(doWork, [(self, doc) for doc in self.docs])
return results
experiment = Experiment(model, ['doc1.txt', 'doc2.txt'])
experiment.run()
当我运行这个脚本时(我在这里显示的两个部分是一个可运行的脚本;请复制),它卡在了pool.map
线上并SystemError
发生了。输出是:
Done preparing
Exception in thread Thread-2:
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 342, in _handle_tasks
put(task)
SystemError: NULL result without error in PyObject_Call
在我将 gensim 引入我的程序之前,该错误从未发生过。(没有多处理的 Gensim 也适用于我。)我认为这可能与与底层 gensim 和 numpy (BLAS) 的 C 代码的互操作有关。我想知道这个错误的原因以及如何解决它。如果我不能将 gensim 与子处理一起使用,有什么替代方案?
我认为model
不会被复制,因为我的操作系统(Mac OS X)应该使用写时复制策略。我也不认为它与内存同步有关,因为没有打印一行“开始工作”,即model
我的代码没有访问过。错误在于将 传递model
给子流程。