multiprocessing — Многопроцессность
Модуль multiprocessing позволяет создавать параллельные программы, обходящие глобальную блокировку интерпретатора (GIL) за счёт использования процессов вместо потоков. Идеально для тяжелых вычислений на CPU.
import multiprocessing
Базовый процесс
На Windows код создания процессов должен быть внутри блока if __name__ == '__main__':.
import multiprocessing
import time
def cpu_heavy_task(name):
print(f"Процесс {name} начался")
# Эмуляция вычислений
time.sleep(2)
print(f"Процесс {name} завершен")
if __name__ == '__main__':
p = multiprocessing.Process(target=cpu_heavy_task, args=("A",))
p.start() # Запуск в отдельном процессе
p.join() # Ожидание завершения
Пул процессов (Рекомендуется)
Для распределения функции по массиву данных на всех ядрах процессора:
import multiprocessing
import time
def process_number(n):
time.sleep(1)
return n * n
if __name__ == '__main__':
data = [1, 2, 3, 4, 5, 6, 7, 8]
# Pool автоматически создает по 1 процессу на каждое ядро
with multiprocessing.Pool() as pool:
# Метод map блокирует выполнение до получения всех результатов
results = pool.map(process_number, data)
print(results) # [1, 4, 9, 16, 25, 36, 49, 64]
Обмен данными (Очереди)
Поскольку процессы имеют независимую память (в отличие от потоков), глобальные переменные не будут общими. Нужно использовать Queue.
import multiprocessing
def worker(q):
# Добавляем данные в общую очередь
q.put("Данные из дочернего процесса")
if __name__ == '__main__':
q = multiprocessing.Queue()
p = multiprocessing.Process(target=worker, args=(q,))
p.start()
print(q.get()) # Читаем данные из главного процесса
p.join()
Частые ошибки
- Отсутствие
if __name__ == '__main__':— приведет к бесконечному циклу создания процессов на Windows. - Обмен объектами — данные, передаваемые в другие процессы, сериализуются через pickle. Не всё можно передать (например, открытые файлы).
- Слишком много маленьких задач — создание процесса стоит дорого (ЦПУ/Память). Если задача выполняется за 0.001 секунды, мультипроцессность её замедлит.
Официальная документация
multiprocessing — Process-based parallelism
Полный справочник API (API Reference)
Классы Process и Pool
| Класс | Описание |
|---|---|
multiprocessing.Process |
Представляет процесс ОС (принимает target-функцию и её args). Его нужно запускать .start(). |
multiprocessing.Pool |
Класс-менеджер пула из нескольких процессов для массового распределения задач. |
Методы пула (Pool)
| Метод | Описание |
|---|---|
Pool.map(func, iterable) |
Эквивалент обычной проверки map, работает кусками по массиву. Полностью блокирует основной код, пока не вычислит весь массив! |
Pool.apply_async(func, args) |
Асинхронно кидает 1 задачу в пул. Не блокирует код операцией ожидания вычисления процессом. |
Pool.close() |
Запрещает добавлять пулу новые задачи. |
Pool.join() |
Режим "Ожидания". Замораживает скрипт на этой строке, пока процессы в пуле работают. Вызывается только после close(). |
IPC (межпроцессное взаимодействие)
| Класс | Описание |
|---|---|
multiprocessing.Queue |
Потокобезопасная очередь для передачи сообщений и данных между процессами. (Добавлять q.put(), читать q.get()). |
multiprocessing.Pipe |
Двусторонний канал. Возвращает кортеж из двух объектов Connection. |
multiprocessing.Lock |
Блокировка (мьютекс) ОС-уровня. |