Как инициализировать пул многопроцессорных рабочих python с общим состоянием? - PullRequest
0 голосов
/ 02 июня 2018

Я пытаюсь выполнить параллельно некоторый алгоритм машинного обучения .

Когда я использую многопроцессорность, это медленнее, чем без.Я предпочитаю, что сериализация pickle моделей, которые я использую, замедляет весь процесс.Итак, вопрос: как я могу инициализировать работника пула с начальным состоянием, чтобы мне не нужно было сериализовать / десериализовать для каждого отдельного вызова моделей?

Вот мой текущийкод:

import pickle
from pathlib import Path
from collections import Counter
from multiprocessing import Pool

from gensim.models.doc2vec import Doc2Vec

from wikimark import html2paragraph
from wikimark import tokenize


def process(args):
    doc2vec, regressions, filepath = args
    with filepath.open('r') as f:
        string = f.read()
    subcategories = Counter()
    for index, paragraph in enumerate(html2paragraph(string)):
        tokens = tokenize(paragraph)
        vector = doc2vec.infer_vector(tokens)
        for subcategory, model in regressions.items():
            prediction = model.predict([vector])[0]
            subcategories[subcategory] += prediction
    # compute the mean score for each subcategory
    for subcategory, prediction in subcategories.items():
        subcategories[subcategory] = prediction / (index + 1)
    # keep only the main category
    subcategory = subcategories.most_common(1)[0]
    return (filepath, subcategory)


def main():
    input = Path('./build')
    doc2vec = Doc2Vec.load(str(input / 'model.doc2vec.gz'))
    regressions = dict()
    for filepath in input.glob('./*/*/*.model'):
        with filepath.open('rb') as f:
            model = pickle.load(f)
        regressions[filepath.parent] = model

    examples = list(input.glob('../data/wikipedia/english/*'))

    with Pool() as pool:
        iterable = zip(
            [doc2vec] * len(examples),  # XXX!
            [regressions] * len(examples),  # XXX!
            examples
        )
        for filepath, subcategory in pool.imap_unordered(process, iterable):
            print('* {} -> {}'.format(filepath, subcategory))


if __name__ == '__main__':
    main()

Строки, отмеченные XXX!, указывают на данные, которые сериализовались, когда я звонил pool.imap_unodered.Существует не менее 200 МБ данных, которые сериализуются.

Как можно избежать сериализации?

1 Ответ

0 голосов
/ 02 июня 2018

Решение так же просто, как использовать глобальный для doc2vec и regressions.

...