Вопрос проверяет понимание альтернатив потокам в Python и умение выбирать корректный инструмент для вычислительно нагруженных задач.
Для CPU-bound задач чаще всего используют несколько процессов вместо потоков. Также применяют нативные библиотеки, которые выполняют вычисления вне Python и освобождают GIL. В некоторых случаях задачи выносят в отдельные сервисы или очереди фоновых задач. Выбор зависит от объёма вычислений и архитектуры системы.
CPU-bound задачи — это задачи, в которых основное время тратится на вычисления, а не на ожидание ввода-вывода.
Так как потоки в CPython ограничены GIL, применяются другие подходы.
Самый распространённый и понятный вариант.
Каждый процесс:
имеет собственный интерпретатор
имеет собственный GIL
может выполняться на отдельном ядре CPU
Пример с multiprocessing:
from multiprocessing import Process
def work():
total = 0
for i in range(10_000_000):
total += i
processes = [Process(target=work) for _ in range(4)]
for p in processes: p.start()
for p in processes: p.join()
Особенности:
реальный параллелизм
высокая стоимость создания процессов
необходимость сериализации данных (pickle)
Более удобная абстракция поверх multiprocessing.
from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor() as pool:
pool.map(work, range(4))
Подходит для:
batch-вычислений
CPU-интенсивных фоновых задач
Многие библиотеки:
выполняют код вне Python
временно освобождают GIL
Примеры:
NumPy
SciPy
OpenCV
import numpy as np
arr = np.random.rand(10_000_000)
result = np.sum(arr)
Здесь вычисления происходят в C, а не в Python-цикле.
Для больших систем часто применяют:
очередь задач
пул воркеров
асинхронную обработку
Примеры:
Celery
RQ
кастомные worker-сервисы
Это позволяет:
масштабировать вычисления горизонтально
изолировать тяжёлые задачи
Для CPU-bound задач в Python используют процессы, нативные библиотеки или вынос вычислений во внешние воркеры. Потоки для этой цели почти всегда неэффективны.