Как я могу распараллелить запомненный вызов на внешнюю программу? - PullRequest
0 голосов
/ 08 июля 2019

У меня есть программа обработки данных, написанная на Python, которая должна вызывать внешнюю программу в течение одного этапа. Профилирование показывает, что около 50% общего времени обработки затрачивается на эту одну стадию.

У меня есть компьютер с несколькими ядрами, поэтому параллелизм кажется решением. Проблема в том, что звонок запоминается:

def one_stage_of_processing(long_list_of_inputs, cache={}):
    outputs = []
    for input in list_of_inputs:
        outputs.append(expensive_external_processing(input, cache))
    return outputs

def expensive_external_processing(input, cache):
    if input not in cache:
        cache[input] = subprocess.run(...).stdout
    return cache[input]

И опыт работы с Си заставляет меня опасаться условий гонки, повреждающих кеш.

Какой самый лучший, самый Pythonic способ распараллелить этот этап обработки? Я хотел бы сохранить памятку на месте, потому что ее удаление увеличивает время выполнения в четыре раза.

Ответы [ 2 ]

1 голос
/ 08 июля 2019

Вы можете использовать multiprocessing для параллельного запуска функций, а затем использовать multiprocessing.Queue для синхронизации кэша между процессами.

1 голос
/ 08 июля 2019

Вы можете запустить задачу асинхронно, а затем поместить future в заметку. Любой, кто спрашивает о результате из памятки, сталкивается с одним из трех состояний: нет памятки (поэтому запустите новую дорогостоящую задачу внешней обработки), невыполненную будущую заметку (вы можете подождать или признать, что это еще не сделано, и пойти и сделать что-то еще, пока готово) или выполнено будущее напоминание (результат сразу доступен). Таким образом, вы можете избежать выдачи нескольких идентичных запросов до того, как будет выполнена их обработка. Обратите внимание, что фьючерсы доступны только с версии 3.5.

Вы также можете увидеть, почему задача занимает так много времени. Если расчет тяжелый, то нет пути к этому; но если автозагрузка тяжелая (что очень часто случалось при таких вещах. В этом случае очень полезно обернуть другой исполняемый файл во что-то, что имеет цикл и может общаться (проще всего) веб-сервис.) Это позволяет вам получить реальную стоимость каждого запроса, полностью избегая затрат на запуск, которые вы получаете, порождая новый подпроцесс для каждого запроса.

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