Возможно ли в Python настоящее параллельное выполнение потоков для CPU-задач

«Возможно ли в Python настоящее параллельное выполнение потоков для CPU-задач» — вопрос из категории Асинхронность, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нет, из-за механизма Global Interpreter Lock (GIL) в стандартной реализации CPython потоки не могут выполняться по-настоящему параллельно на нескольких ядрах процессора для задач, интенсивно использующих CPU (CPU-bound).

GIL — это мьютекс, который разрешает исполнение Python-байткода только одному потоку в один момент времени.

Разница в применении:

  • I/O-bound задачи (ожидание ответа от сети, чтение с диска): Потоки (threading) эффективны. Пока один поток ждет завершения операции ввода-вывода, GIL освобождается, и другой поток может выполняться.
  • CPU-bound задачи (математические вычисления, обработка данных): Потоки создают лишь конкурентность, а не параллелизм. Для настоящей параллельности на нескольких ядрах следует использовать модуль multiprocessing, который создает отдельные процессы, каждый со своим собственным GIL.

Пример с multiprocessing для CPU-bound задачи:

import multiprocessing
import time

def cpu_task(name):
    print(f"Процесс {name} начал вычисления.")
    # Имитация тяжелой вычислительной задачи
    [i*i for i in range(10**7)]
    print(f"Процесс {name} завершил вычисления.")

if __name__ == "__main__":
    p1 = multiprocessing.Process(target=cpu_task, args=("A",))
    p2 = multiprocessing.Process(target=cpu_task, args=("B",))

    start_time = time.time()
    p1.start()
    p2.start()

    p1.join()
    p2.join()
    end_time = time.time()

    print(f"Все процессы завершены за {end_time - start_time:.2f} секунд.")

Вывод: Для задач, ограниченных вводом-выводом, используйте threading. Для задач, требующих интенсивных вычислений на нескольких ядрах, — multiprocessing.