W Pythonie standardowa biblioteka udostępnia moduł threading do programowania wielowątkowego. Wątki pozwalają wykonywać kilka operacji równolegle w ramach jednego procesu. Jednak w standardowej implementacji Pythona (CPython) istnieje mechanizm GIL (Global Interpreter Lock) — globalna blokada interpretera, która pozwala tylko jednemu wątkowi na jednoczesne wykonywanie bajtowego kodu Pythona.
Oznacza to, że w CPython wielowątkowość nie pozwala osiągnąć rzeczywistej równoległości w wykonywaniu kodu Pythona na poziomie procesora; równoległość jest użyteczna tylko dla zadań związanych z oczekiwaniem (I/O-bound). Dla zadań typu CPU-bound zaleca się użycie modułu multiprocessing, który uruchamia kilka procesów i omija GIL.
Przykład:
import threading def worker(): print('Start') # ciężkie obliczenia print('End') threads = [threading.Thread(target=worker) for _ in range(5)] for t in threads: t.start() for t in threads: t.join()
Aby uzyskać równoległość przy intensywnych obliczeniach, stosuj multiprocessing:
from multiprocessing import Pool def square(x): return x*x with Pool(4) as p: print(p.map(square, [1, 2, 3, 4]))
Czy wielowątkowość w Pythonie może przyspieszyć wykonywanie zadań obliczeniowych?
Odpowiedź: Nie, z powodu GIL w standardowej implementacji Pythona (CPython) wątki nie przyniosą wzrostu wydajności w zadaniach CPU-bound; dla takich zadań używaj multiprocessing lub alternatywnych implementacji interpretera (np. Jython, IronPython), które nie mają GIL.
Historia
W projekcie do przetwarzania dużych ilości danych zespół próbował przyspieszyć obliczenia za pomocą wątków (
threading). Zamiast przyspieszenia czas pracy wzrósł, ponieważ GIL nie pozwalał wątkom działać równolegle; po przejściu namultiprocessingproblem został rozwiązany.
Historia
Programista próbował jednocześnie pobierać duże pliki i przetwarzać je w kilku wątkach, ale często napotykał na "deadlock" z powodu nieostrożnego użycia wspólnych zmiennych bez blokad (bezpieczeństwo wątków).
Historia
Na serwerze backendowym zaimplementowano przetwarzanie ciężkich zapytań w puli wątków. Przy wzroście obciążenia serwer zaczął "zamierać" — okazało się, że większość czasu wątki spędzały na oczekiwanie na wykonanie kodu Pythona z powodu GIL, mimo że zapytania nie były związane z intensywnym I/O.