Корутины, зелёные потоки и мультипроцессинг

Корутины и зелёные потоки в Python — это разные концепции, хотя обе используются для параллелизма. Корутины — это "ручной" асинхронизм, зелёные потоки — "автоматический" параллелизм в одном потоке. Но мультипроцессинг все равно круче.

Скажем сразу, что для CPU-задач ни то, ни другое не даст ускорения. Они хороши для I/O-задач.

Корутины (Coroutines)

Что это: Асинхронные функции, работающие в рамках одного потока (thread). Управляются через asyncio в Python.

Как работают: Выполнение приостанавливается на await, позволяя другим корутинам работать в это время. Это кооперативная многозадачность (вы сами указываете, где ждать).

Плюсы: Легковесные, нет затрат на переключение потоков, идеальны для I/O-операций (например, сеть, файлы).

Минусы: Требуют явного управления (await), не параллельны для CPU-задач, так как работают в одном потоке.

Пример: async def process_line() с await asyncio.sleep().

Зелёные потоки (Green Threads)

Что это: Легковесные "потоки", эмулируемые библиотекой (например, gevent), а не ОС. Работают в одном реальном потоке.

Как работают: Автоматически переключаются при блокирующих операциях (I/O), благодаря патчу стандартных модулей (monkey.patch_all()).

Плюсы: Прозрачность (код выглядит как синхронный), автоматическое переключение, хороши для I/O-задач.

Минусы: Не используют многопроцессорность (один поток), требуют патча для совместимости.

Пример: gevent.spawn(worker) для параллельной обработки.

Главные отличия

  1. Управление:    - Корутины: Явное (await), вы сами решаете, где ждать.    - Зелёные потоки: Неявное, переключение автоматическое при I/O.

  2. Модель:    - Корутины: Кооперативная (вы уступаете управление).    - Зелёные потоки: Превентивная (библиотека решает за вас).

  3. Инструменты:    - Корутины: Встроены в Python через asyncio.    - Зелёные потоки: Требуют внешних библиотек (gevent, eventlet).

  4. Использование:    - Корутины: Точный контроль над асинхронностью.    - Зелёные потоки: Удобство для кода, похожего на синхронный.

CPU-bound tasks

CPU-задачи - это задачи, которые требуют интенсивных вычислений и нагружают процессор (CPU), а не ждут внешних ресурсов вроде сети или диска.

CPU-задачи — это "мозговой штурм" для процессора, а не ожидание данных.

Примеры:

  • Математические вычисления (например, вычисление факториала большого числа).
  • Обработка изображений (фильтры, рендеринг).
  • Сжатие данных или шифрование.
  • Поиск в массиве или сложные алгоритмы (например, сортировка).

Особенности:

Основное время тратится на работу процессора, а не на ожидание I/O (ввод/вывод).

В Python такие задачи ограничены GIL (Global Interpreter Lock), из-за чего многопоточность (threads) не ускоряет их на нескольких ядрах.

Чем отличаются от I/O-задач?

I/O-задачи (I/O-bound): Ждут внешних операций (чтение файла, запрос к серверу). Хорошо работают с корутинами и зелёными потоками.

CPU-задачи: "Гоняют" процессор. Для ускорения нужен multiprocessing (несколько процессов) или распараллеливание на ядра.

Multiprocessing

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

Multiprocessing — это "армия клонов" Python, где каждый делает свою работу на отдельном ядре

Как работает:

Каждый процесс — это независимая копия программы с собственным интерпретатором Python и памятью.

Процессы распределяются по ядрам CPU, что даёт настоящее параллельное выполнение.

Управление через модуль multiprocessing: создание процессов, пулы (pools), обмен данными через очереди или pipes.

Отличия от потоков/корутин:

  1. Процессы:    - Независимы, используют разные ядра.    - Больше памяти и времени на запуск.    - Подходят для CPU-задач.
  2. Потоки (threading):    - Делят память, работают в одном процессе.    - Ограничены GIL в Python — не параллельны для CPU.    - Хороши для I/O-задач.
  3. Корутины:    - В одном потоке, кооперативные.    - Легковесные, для I/O.

Когда использовать:

Multiprocessing — для CPU-задач (вычисления, обработка данных), где нужна настоящая многопроцессорность.

Пример: обработка больших массивов чисел, параллельные тяжёлые вычисления.