Пытаюсь понять многопроцессорные очереди

#python #multiprocessing

#python #многопроцессорная обработка

Вопрос:

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

Я понимаю, как с multiprocessing помощью вы можете запускать несколько экземпляров функции над набором данных с помощью фрагмента кода, подобного этому:

 from multiprocessing import Pool

with Pool() as pool:
    pool.map(my_func, data)
  

Теперь, что, если у меня есть две функции, первая из которых является входом для второй, чтобы они могли выполняться параллельно? Я понимаю, что идея состоит в том, чтобы использовать очередь, но все примеры, которые я нашел, не так быстро и легко понять. Я просмотрел раздел 10.4.10 «Стандартная библиотека Python 3 на примере», но не смог понять, как применить это к моему случаю.

Мой вариант использования — это программа, которая копирует файлы в целевую папку, затем вычисляет контрольную сумму MD5 копии. Я бы хотел, чтобы копия следующего файла запускалась во время вычисления контрольной суммы MD5 ранее завершенной копии. Таким образом, вывод функции (copy) представляет собой имя файла с путем (string), который является вводом второй функции (контрольная сумма MD5).

Есть ли у кого-нибудь базовая модель кода, подобная приведенной выше, чтобы я начал?

Комментарии:

1. почему вы не вычисляете контрольную сумму при копировании? копирование файла обязательно включает в себя чтение файла, так почему бы просто не передать его через контрольную сумму одновременно. когда я попытался сделать что-то подобное, я подумал, что было бы важнее перекрывать сканирование каталогов обработкой файлов. Я полагаю, это будет зависеть от того, какую часть дерева каталогов вы хотите обработать / скопировать

Ответ №1:

Не зная вашей реализации, но это не совсем задача Pool . Первый вопрос заключается в том, что будет делать ваша основная программа.

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

Другая возможность — выполнить обе задачи в одной и той же функции внутри пула. Если у вас есть дополнительные ресурсы, просто увеличьте количество рабочих. Обе ваши задачи требуют интенсивного ввода-вывода. Узким местом этого будет ввод-вывод, и вы ничего не выиграете от добавления большего количества процессора к задаче. Это мой любимый, основанный на том, что я мало знаю.

Если вам действительно нужны два подпроцесса для этого — один для копирования и один для подсчета контрольных сумм, вам понадобятся пул, подпроцесс и очередь. Или только два подпроцесса, если пул не нужен. Я слишком ленив, чтобы написать рабочий пример, но идея состоит в том, чтобы создать multiprocessing.queue() , а затем использовать multiprocessing.Process для запуска калькулятор контрольной суммы с очередью в качестве параметра. Наконец, вы запустите пул — или другой процесс, если одного достаточно для насыщения вашего ввода-вывода — и передадите ту же очередь рабочему.

Если вы в конечном итоге используете Pool и решите использовать map или map_async, вам также потребуется использовать partial from functools для создания копии вашего worker, у которой уже есть очередь в качестве параметра, поскольку map может отправлять только один параметр — имя файла. Если вы используете apply_async, то вы можете отправить рабочему как имя файла, так и очередь в качестве параметров.

Когда ваш копировальный аппарат скопировал файл, он put() добавит имя файла в очередь. Ваш процесс проверки контрольной суммы — это цикл while true, который находится в queue.get() и ожидает появления имен файлов. Если вам затем нужно где-то вернуть контрольную сумму, вам понадобится другая очередь для исходящего трафика, другой параметр для подпроцессов и основная программа, ожидающая чтения результатов из этой очереди.

Это работает, но я уверен, что это не улучшит производительность по сравнению с моделью, в которой ваш рабочий выполняет копирование и вычисление контрольной суммы за один раз. Как вы можете видеть, это становится намного более запутанным, и вы потенциально потеряете некоторую скорость при отправке информации в очередях туда и обратно. Очереди работают, но они не являются чудодейственными исполнителями.

Комментарии:

1. Моя самая искренняя благодарность за ваше подробное объяснение. Это действительно помогло мне понять процесс. Исходя из этого, я действительно менее уверен, что стоит изучить этот вариант использования. Я могу потратить больше времени на поиск оптимального подхода, чем на самом деле было бы получено от увеличения производительности, если оно окажется незначительным. Независимо от того, есть ли у меня решение моего вопроса, я действительно многое понял!