【问题标题】:multiprocessing with textacy or spacy具有 textacy 或 spacy 的多处理
【发布时间】:2019-10-08 22:05:36
【问题描述】:

我正在尝试通过 textacy 的并行化来加快处理大量文本的速度。当我从多处理中使用 Pool 时,生成的文本语料库是空的。我不确定问题是否出在我使用 textacy 或 multiprocessing 范例的方式上? 这是说明我的问题的示例:

import spacy
import textacy
from multiprocessing import Pool

texts_dict={
"key1":"First text 1."
,"key2":"Second text 2."
,"key3":"Third text 3."
,"key4":"Fourth text 4."
}

model=spacy.load('en_core_web_lg')

# this works

corpus = textacy.corpus.Corpus(lang=model)

corpus.add(tuple([value, {'key':key}],) for key,value in texts_dict.items())

print(corpus) # prints Corpus(4 docs, 8 tokens)
print([doc for doc in corpus])

# now the same thing with a worker pool returns empty corpus

corpus2 = textacy.corpus.Corpus(lang=model)

pool = Pool(processes=2) 
pool.map( corpus2.add, (tuple([value, {'key':key}],) for key,value in texts_dict.items()) )

print(corpus2) # prints Corpus(0 docs, 0 tokens)
print([doc for doc in corpus2])

# to make sure we get the right data into corpus.add
pool.map( print, (tuple([value, {'key':key}],) for key,value in texts_dict.items()) )

Textacy 基于 spacy。 Spacy 不支持多线程,但应该可以在多个进程中运行。 https://github.com/explosion/spaCy/issues/2075

根据@constt https://*.com/a/58317741/4634344 的伟大建议,将结果收集到语料库中适用于 n_docs= 10273 n_sentences= 302510 n_tokens= 2053129 的数据集。

对于更大的数据集(16000 个文档 3MM 令牌),我收到以下错误:

result_corpus=corpus.get() 
  File "<string>", line 2, in get
  File "/usr/lib/python3.6/multiprocessing/managers.py", line 772, in _callmethod
    raise convert_to_error(kind, result)
multiprocessing.managers.RemoteError: 
---------------------------------------------------------------------------
Unserializable message: Traceback (most recent call last):
  File "/usr/lib/python3.6/multiprocessing/managers.py", line 283, in serve_client
    send(msg)
  File "/usr/lib/python3.6/multiprocessing/connection.py", line 206, in send
    self._send_bytes(_ForkingPickler.dumps(obj))
  File "/usr/lib/python3.6/multiprocessing/connection.py", line 393, in _send_bytes
    header = struct.pack("!i", n)
struct.error: 'i' format requires -2147483648 <= number <= 2147483647

' 我会调查,但如果您有直接的解决方案 - 非常感谢!

【问题讨论】:

    标签: python multiprocessing spacy pool textacy


    【解决方案1】:

    由于 python 进程在不同的内存空间中运行,您必须在池中的进程之间共享您的 corpus 对象。为此,您必须将corpus 对象包装到一个可共享的类中,您将使用BaseManager 类进行注册。以下是重构代码以使其工作的方法:

    #!/usr/bin/python3
    from multiprocessing import Pool
    from multiprocessing.managers import BaseManager
    
    import spacy
    import textacy
    
    
    texts = {
        'key1': 'First text 1.',
        'key2': 'Second text 2.',
        'key3': 'Third text 3.',
        'key4': 'Fourth text 4.',
    }
    
    
    class PoolCorpus(object):
    
        def __init__(self):
            model = spacy.load('en_core_web_sm')
            self.corpus = textacy.corpus.Corpus(lang=model)
    
        def add(self, data):
            self.corpus.add(data)
    
        def get(self):
            return self.corpus
    
    
    BaseManager.register('PoolCorpus', PoolCorpus)
    
    
    if __name__ == '__main__':
    
        with BaseManager() as manager:
            corpus = manager.PoolCorpus()
    
            with Pool(processes=2) as pool:
                pool.map(corpus.add, ((v, {'key': k}) for k, v in texts.items()))
    
            print(corpus.get())
    

    输出:

    Corpus(4 docs, 16 tokens)
    

    【讨论】:

    • 感谢您提出非常明确的建议!我已经在示例和较小的真实数据集(n_docs= 153 n_sentences= 953 n_tokens= 7600)上运行它,没有任何问题。但是对于具有 16000 个文档和大约 1600 个文档的数据集。 3MM代币出现错误。我会将错误消息添加到问题中。
    • n_docs= 10273 n_sentences= 302510 n_tokens= 2053129 也通过了
    • @Diego 您是否尝试过将文档拆分为长度为 10000 的块,并使用相同的共享语料库在池中按顺序处理它们?
    • 是的,我刚刚这样做了,它可以在相同的限制下正常工作。数字 2,147,483,647(或十六进制 7FFF,FFFF16)是计算中 32 位有符号二进制整数的最大正值。我运行 64 位 python。看来这是影响我的问题github.com/joblib/joblib/issues/731#issuecomment-409893849 但它必须已经修复(但在 Python 3.8 中?)阶段:已解决组件:版本:Python 3.8
    • 我尝试安装 python 3.8 但没有*用于 scipy (openblas,lapack) 所以我暂时放弃了这条途径。无论如何,不​​幸的是,与单个进程相比,上述并行执行并没有带来任何加速。我想知道我应该在这里发布我的发现还是接受您的回答并开始另一个问题?
    最近更新 更多