← Назад к вопросам
Есть ли в Python полная поддержка параллелизм?
2.3 Middle🔥 231 комментариев
#Python Core#Асинхронность и многопоточность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Есть ли в Python полная поддержка параллелизма?
Короткий ответ: Нет, в CPython полной поддержки параллелизма нет из-за GIL. Но есть решения.
Проблема: Global Interpreter Lock (GIL)
GIL — это мьютекс в CPython, который позволяет только одному потоку выполнять Python код одновременно.
import threading
import time
def cpu_intensive(n):
# Сложные вычисления
total = 0
for i in range(n):
total += i ** 2
return total
start = time.time()
# ❌ Потоки НЕ распараллелятся на CPU из-за GIL
t1 = threading.Thread(target=cpu_intensive, args=(100_000_000,))
t2 = threading.Thread(target=cpu_intensive, args=(100_000_000,))
t1.start()
t2.start()
t1.join()
t2.join()
print(f"Потоки: {time.time() - start:.2f}с") # ~10 сек (двойное время!)
# ✅ Процессы распараллелятся идеально
from multiprocessing import Process
start = time.time()
p1 = Process(target=cpu_intensive, args=(100_000_000,))
p2 = Process(target=cpu_intensive, args=(100_000_000,))
p1.start()
p2.start()
p1.join()
p2.join()
print(f"Процессы: {time.time() - start:.2f}с") # ~5 сек (параллельно!)
Три уровня параллелизма
1. Многопоточность (Threading) — для I/O
Потоки НЕ параллельны для CPU-bound задач, но идеальны для I/O-bound.
import threading
import requests
def fetch_url(url):
response = requests.get(url) # БЛОКИРУЕТ, но отпускает GIL
return response.status_code
start = time.time()
urls = ['http://example.com'] * 10
threads = [threading.Thread(target=fetch_url, args=(url,)) for url in urls]
for t in threads:
t.start()
for t in threads:
t.join()
print(f"Многопоточность: {time.time() - start:.2f}с") # ~1 сек (параллельно!)
Почему работает: Когда поток ждёт сетевого ответа, он отпускает GIL, позволяя другим потокам выполняться.
2. Многопроцессность (Multiprocessing) — для CPU
Процессы — это отдельные Python интерпретаторы, каждый со своим GIL.
from multiprocessing import Pool
import time
def factorial(n):
result = 1
for i in range(1, n + 1):
result *= i
return result
if __name__ == '__main__':
start = time.time()
# Использование процессов
with Pool(processes=4) as pool:
results = pool.map(factorial, [10000] * 4)
print(f"Многопроцессность: {time.time() - start:.2f}с") # ~5 сек
# Сравнение: последовательное выполнение
start = time.time()
results = [factorial(10000) for _ in range(4)]
print(f"Последовательно: {time.time() - start:.2f}с") # ~20 сек
3. Асинхронность (Async) — для высокой конкурентности
Один поток, много корутин. Идеально для тысяч одновременных операций I/O.
import asyncio
import aiohttp
async def fetch_url_async(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return response.status
async def main():
start = time.time()
tasks = [fetch_url_async('http://example.com') for _ in range(100)]
results = await asyncio.gather(*tasks)
print(f"Асинхронность: {time.time() - start:.2f}с") # ~1 сек для 100 запросов
if __name__ == '__main__':
asyncio.run(main())
Сравнительная таблица
| Подход | CPU-bound | I/O-bound | Сложность | Масштабируемость |
|---|---|---|---|---|
| Threading | ❌ Нет | ✅ Да | Низкая | Сотни |
| Multiprocessing | ✅ Да | ❌ Нет | Средняя | Процессоры |
| Async | ❌ Нет | ✅ Да | Средняя | Тысячи |
Решения для полного параллелизма
1. PyPy
# PyPy имеет другую реализацию и может быть быстрее
pypy3 your_script.py
2. Jython / IronPython
Другие реализации Python без GIL.
3. Cython для критичного кода
# fast_code.pyx
cpdef int factorial(int n):
cdef int result = 1
cdef int i
for i in range(1, n + 1):
result *= i
return result
4. Расширения на C/C++
# Вызов C функций отпускает GIL
import ctypes
libc = ctypes.CDLL('libc.so.6')
result = libc.function() # Выполняется без GIL
5. Python 3.13+ с экспериментальным режимом без GIL
python3.13 -X gil=0 your_script.py # Экспериментально!
Практические рекомендации
# ❌ Ошибка: использовать threading для CPU-bound
from threading import Thread
result = sum(n**2 for n in range(100_000_000)) # Медленно!
# ✅ Правильно: использовать multiprocessing
from multiprocessing import Pool
with Pool() as p:
result = sum(p.map(lambda n: n**2, range(100_000_000)))
# ❌ Ошибка: использовать threading для 10000 одновременных операций
threads = [Thread(target=fetch, args=(url,)) for url in urls]
# ✅ Правильно: использовать async
async def main():
tasks = [fetch_async(url) for url in urls]
return await asyncio.gather(*tasks)
Итоговый ответ
Python НЕ имеет полной поддержки параллелизма из-за GIL в CPython, но:
- ✓ I/O-bound: Threading и Async работают отлично
- ✓ CPU-bound: Multiprocessing работает идеально
- ✓ Смешанные задачи: Комбинируй подходы
- ✓ Критичный код: Пиши на C/Cython
GIL — это не проблема, если использовать правильный инструмент для задачи.