Ответ
CPU-bound задачи (интенсивные вычисления) в стандартном CPython упираются в Global Interpreter Lock (GIL), который не позволяет нескольким потокам выполнять Python-байткод одновременно на разных ядрах CPU. Для обхода этого ограничения используются следующие подходы:
-
Многопроцессорность (
multiprocessing) Самый распространенный способ. Каждый процесс получает собственный интерпретатор Python и, соответственно, собственный GIL, что позволяет выполнять код параллельно на разных ядрах. Почему: Простота использования и наличие в стандартной библиотеке.from multiprocessing import Pool def square(x): return x * x if __name__ == '__main__': # Создаем пул из 4 процессов with Pool(4) as p: results = p.map(square, range(100)) print(results) -
concurrent.futures.ProcessPoolExecutorБолее высокоуровневый интерфейс для работы с пулом процессов, построенный поверхmultiprocessing. Почему: Удобный и современный API для управления асинхронными задачами.from concurrent.futures import ProcessPoolExecutor def square(x): return x * x with ProcessPoolExecutor(max_workers=4) as executor: results = list(executor.map(square, range(100))) print(results) -
NumbaJIT (Just-In-Time) компилятор, который переводит числовой Python-код в быстрый машинный код, часто обходя GIL. Почему: Идеально для научных и математических вычислений, особенно с использованием NumPy. Требует минимальных изменений в коде (только декоратор).from numba import jit import numpy as np @jit(nopython=True) # nopython=True гарантирует отсутствие вызовов Python API def sum_array(arr): total = 0.0 for i in range(arr.shape[0]): total += arr[i] return total my_array = np.arange(1_000_000, dtype=np.float64) sum_array(my_array) # Первый вызов компилирует функцию -
CythonПозволяет писать код на диалекте Python с C-аннотациями типов, который затем компилируется в нативный C/C++ код. Позволяет вручную освобождать GIL для параллельного выполнения в потоках. Почему: Дает максимальный контроль над производительностью и взаимодействием с C-библиотеками.
Вывод: для большинства общих задач multiprocessing является лучшим выбором. Для числовых вычислений стоит предпочесть Numba, а для максимальной оптимизации и интеграции с C — Cython.