Сериализация объектов для многопроцессорной обработки медленная - есть ли способ сериализации только один раз? - PullRequest
0 голосов
/ 13 июня 2018

Я пытаюсь распараллелить функцию, которая принимает объект в Python:

При использовании Pathos функция карты автоматически уклоняет объект перед его распределением по процессорам.

Однако,укроп объекта каждый раз занимает ~ 1 мин, и мне нужно запустить эту функцию до 100 раз.В общем, требуется всего 2 часа, чтобы просто сериализовать объект, прежде чем даже запустить его.

Есть ли способ просто сериализовать его один раз и использовать его несколько раз?

Спасибо большоемного

1 Ответ

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

Самое простое, что нужно сделать - это сделать это вручную.

Без примера вашего кода мне придется сделать много предположений и написать что-то довольно расплывчатое, поэтому давайте рассмотрим простейший случай.

Предположим, вы используете dill вручную,поэтому ваш существующий код выглядит следующим образом:

obj = function_that_creates_giant_object()
for i in range(zillions):
    results.append(pool.apply(func, (dill.dumps(obj),)))

Все, что вам нужно сделать, это вывести dumps из цикла:

obj = function_that_creates_giant_object()
objpickle = dill.dumps(obj)
for i in range(zillions):
    results.append(pool.apply(func, (objpickle,)))

Но в зависимости от вашего фактического использования, этоможет быть, лучше просто прикрепить кеш перед dill:

cachedpickle = functools.lru_cache(maxsize=10)(dill.dumps)

obj = function_that_creates_giant_object()
for i in range(zillions):
    results.append(pool.apply(wrapped_func, (cachedpickle(obj),))

Конечно, если вы используете макипатч multiprocessing, чтобы использовать dill вместо pickle, выможно так же легко исправить это, чтобы использовать эту cachedpickle функцию.


Если вы используете multiprocess, который является раздвоенной версией multiprocessing, которая предварительно заменяет dill на pickle, менее очевидно, как это исправить;вам нужно будет просмотреть исходный код и посмотреть, где он использует dill, и заставить его использовать вашу оболочку.Но IIRC, он просто делает import dill as pickle где-то и затем использует тот же код, что и (слегка устаревшая версия multiprocessing), так что он не так уж и отличается.

На самом делеВы даже можете написать модуль, который предоставляет тот же интерфейс, что и pickle и dill:

import functools
import dill

def loads(s):
    return dill.loads(s)

@lru_cache(maxsize=10)
def dumps(o):
    return dill.dumps(o)

… и просто заменить import dill as pickle на import mycachingmodule as pickle.

…или даже monkeypatch после загрузки с multiprocess.helpers.pickle = mycachingmodule (или с любым другим подходящим именем - вам все равно придется найти, где соответствующая import происходит в источнике того, что вы используете).


И это настолько сложно, насколько это возможно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...