0Pricing
Python Academy · Урок

Основы multiprocessing

Используйте несколько ядер CPU

«Основы multiprocessing» — бесплатный урок Python Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Python Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Python Academy содержит 4 уроков всего.

Зачем нужна многопроцессная обработка

GIL не позволяет потокам выполнять байт-код Python параллельно. Модуль multiprocessing обходит это ограничение, запуская отдельные процессы, каждый со своим интерпретатором и GIL, поэтому задачи с высокой нагрузкой на CPU действительно выполняются на нескольких ядрах.

import multiprocessing as mp
print('CPU cores available:', mp.cpu_count())

Запуск Process

Process(target=func) повторяет API потоков. Вызовите start(), чтобы запустить процесс, и join(), чтобы дождаться его завершения.

import multiprocessing as mp

def worker():
    print('hello from a child process')

if __name__ == '__main__':
    p = mp.Process(target=worker)
    p.start()
    p.join()
    print('parent done')

Защита главного модуля

На некоторых платформах дочерние процессы импортируют Ваш скрипт. Без защиты if __name__ == '__main__': можно начать рекурсивно порождать процессы. Всегда помещайте код запуска в эту защиту.

import multiprocessing as mp

def task(n):
    print('processing', n)

if __name__ == '__main__':
    for i in range(3):
        p = mp.Process(target=task, args=(i,))
        p.start()
        p.join()

Передача аргументов

Используйте args для позиционных аргументов и kwargs для именованных — так же, как в потоках. Аргументы сериализуются и отправляются дочернему процессу.

import multiprocessing as mp

def show(label, times):
    for _ in range(times):
        print(label)

if __name__ == '__main__':
    p = mp.Process(target=show, args=('hi',), kwargs={'times': 2})
    p.start()
    p.join()

Пул исполнителей

multiprocessing.Pool управляет группой процессов. pool.map распределяет между ними итерируемый объект и собирает результаты в исходном порядке.

import multiprocessing as mp

def square(n):
    return n * n

if __name__ == '__main__':
    with mp.Pool(processes=2) as pool:
        print(pool.map(square, range(6)))

ProcessPoolExecutor

API concurrent.futures также предлагает ProcessPoolExecutor с тем же интерфейсом submit/map, который Вы видели для потоков.

from concurrent.futures import ProcessPoolExecutor

def cube(n):
    return n ** 3

if __name__ == '__main__':
    with ProcessPoolExecutor() as ex:
        print(list(ex.map(cube, range(5))))

Отдельные пространства памяти

У каждого процесса есть собственная память. Изменение глобальной переменной в дочернем процессе не изменяет копию в родительском процессе. Данные необходимо явно возвращать или совместно использовать.

import multiprocessing as mp

counter = 0

def bump():
    global counter
    counter += 100

if __name__ == '__main__':
    p = mp.Process(target=bump)
    p.start()
    p.join()
    print('parent counter still:', counter)

Возврат результатов

Поскольку память не является общей, возвращайте результаты через Pool.map, объекты-исполнители или очереди, а не изменяйте глобальные переменные.

import multiprocessing as mp

def double(n):
    return n * 2

if __name__ == '__main__':
    with mp.Pool(2) as pool:
        results = pool.map(double, [1, 2, 3, 4])
    print('results:', results)

apply_async для отдельных вызовов

apply_async планирует один вызов и возвращает дескриптор результата. Вызовите .get(), чтобы получить значение.

import multiprocessing as mp

def add(a, b):
    return a + b

if __name__ == '__main__':
    with mp.Pool(2) as pool:
        r = pool.apply_async(add, (3, 4))
        print(r.get())

Требование сериализации

Целевые функции и аргументы должны быть сериализуемыми, чтобы пересекать границу между процессами. Функции верхнего уровня работают; лямбда-функции и локальные функции обычно не работают.

import multiprocessing as mp

def top_level(n):
    return n + 1

if __name__ == '__main__':
    with mp.Pool(2) as pool:
        print(pool.map(top_level, [10, 20]))

Когда стоит использовать процессы

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

import multiprocessing as mp

def heavy(n):
    return sum(i * i for i in range(n))

if __name__ == '__main__':
    with mp.Pool() as pool:
        print(pool.map(heavy, [1000, 2000, 3000]))

Быстрая проверка

Проверьте, насколько хорошо Вы поняли многопроцессную обработку.

Итоги

Вы изучили основы многопроцессной обработки:

  • Процессы обходят GIL и обеспечивают настоящий параллелизм вычислений на CPU.
  • Используйте защиту if __name__ == '__main__'.
  • Pool и ProcessPoolExecutor распределяют работу и собирают результаты.
  • Память не является общей; аргументы должны быть сериализуемыми.

Далее: безопасный обмен данными с помощью очередей и блокировок.

Часто задаваемые вопросы

Урок «Основы multiprocessing» бесплатный?

Да — полный текст урока «Основы multiprocessing» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Python Academy, подпишись на CoddyKit PRO. Курс Python Academy содержит 4 уроков всего.

Чему я научусь в уроке «Основы multiprocessing»?

Используйте несколько ядер CPU Ты практикуешь Python Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Python Academy?

Предыдущий опыт не требуется. Python Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Основы multiprocessing»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Python Academy?

Да. Каждый урок Python Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Потоки и GIL
  2. ThreadPoolExecutor
  3. Основы multiprocessing
  4. Безопасный обмен данными
← Назад к Python Academy