Вопрос проверяет знание модели исполнения Python, влияния GIL и умение выбрать корректный инструмент параллелизма под тип нагрузки.
CPU-bound — это задачи, где время уходит на вычисления, а не на ожидание ввода-вывода. В CPython есть GIL, который позволяет исполнять Python-код только одному потоку одновременно в пределах процесса. Поэтому несколько потоков чаще дают накладные расходы, но не прирост скорости. Потоки хорошо подходят для I/O-bound задач, где много ожидания сети или диска.
CPU-bound задача — это задача, где узкое место — процессорные вычисления (парсинг, криптография, обработка изображений, численные расчёты).
Определение:
GIL (Global Interpreter Lock) — механизм, который защищает внутренние структуры интерпретатора CPython и обеспечивает, что байткод Python в одном процессе выполняется только одним потоком одновременно.
Что это означает на практике:
Вы создаёте несколько потоков
Они по очереди получают доступ к интерпретатору
Реально вычисления выполняются «по одному»
В итоге:
прироста скорости нет или он минимальный
появляется overhead на переключение потоков
Когда поток ждёт:
сетевой ответ
диск
таймаут
он часто освобождает управление, и другой поток может выполняться. Поэтому потоки дают выигрыш там, где много ожидания.
CPU-bound код в потоках:
from threading import Thread
def work():
s = 0
for i in range(10_000_000):
s += i
threads = [Thread(target=work) for _ in range(4)]
for t in threads: t.start()
for t in threads: t.join()
Обычно это не даст ускорения пропорционально количеству потоков.
Смысловой выбор зависит от задачи:
Multiprocessing / ProcessPoolExecutor
каждый процесс со своим GIL
реальное использование нескольких ядер
Нативные библиотеки
NumPy / OpenCV могут отпускать GIL и считать в C
Перенос вычислений
отдельный сервис, очередь задач, воркеры
(про альтернативы подробно будет в следующем вопросе по списку)
Потоки в CPython почти не ускоряют CPU-bound из-за GIL: параллелизм получается «логическим», но не вычислительным. Для вычислений чаще используют процессы или нативные библиотеки.