Co to jest globalna blokada tłumacza i dlaczego stanowi problem?
Podczas usuwania GIL z Pythona powstało wiele hałasu i chciałbym zrozumieć, dlaczego jest to takie ważne. Nigdy sam nie napisałem kompilatora ani tłumacza, więc nie bądź oszczędny w szczegółach, prawdopodobnie potrzebuję ich do zrozumienia.
python
python-internals
gil
e-satis
źródło
źródło
Odpowiedzi:
GIL Pythona ma na celu serializację dostępu do wewnętrznych elementów interpretera z różnych wątków. W systemach wielordzeniowych oznacza to, że wiele wątków nie może skutecznie wykorzystywać wielu rdzeni. (Gdyby GIL nie doprowadził do tego problemu, większość ludzi nie przejmowałaby się GIL - problem ten jest podnoszony tylko z powodu rosnącej częstości występowania systemów wielordzeniowych.) Jeśli chcesz to szczegółowo zrozumieć, możesz obejrzeć ten film lub obejrzeć ten zestaw slajdów . To może być za dużo informacji, ale poprosiłeś o szczegóły :-)
Zauważ, że GIL Pythona jest tak naprawdę tylko problemem dla CPython, implementacji referencyjnej. Jython i IronPython nie mają GIL. Jako programista w Pythonie ogólnie nie spotykasz GIL, chyba że piszesz rozszerzenie C. Autorzy rozszerzeń C muszą zwolnić GIL, gdy ich rozszerzenia blokują operacje wejścia / wyjścia, aby inne wątki w procesie Pythona miały szansę na uruchomienie.
źródło
regex
,lxml
,numpy
modułów. Cython pozwala na wydanie GIL w niestandardowym kodzie, np.b2a_bin(data)
Załóżmy, że masz wiele wątków, które tak naprawdę nie dotykają się nawzajem. Powinny one być wykonywane tak niezależnie, jak to możliwe. Jeśli masz „globalną blokadę”, którą musisz zdobyć, aby (powiedzmy) wywołać funkcję, która może skończyć się wąskim gardłem. Możesz skończyć, nie mając wiele korzyści z posiadania wielu wątków.
Aby umieścić to w prawdziwej analogii: wyobraź sobie 100 programistów pracujących w firmie z jednym kubkiem kawy. Większość programistów spędza czas na czekaniu na kawę zamiast kodowania.
Żadna z tych rzeczy nie jest specyficzna dla Pythona - nie znam szczegółów, po co Python potrzebował GIL. Mam jednak nadzieję, że daje to lepszy obraz ogólnej koncepcji.
źródło
Najpierw zrozumiemy, co zapewnia GIL w Pythonie:
Każda operacja / instrukcja jest wykonywana w tłumaczu. GIL zapewnia, że tłumacz jest utrzymywany przez pojedynczy wątek w określonym momencie . Twój program pythonowy z wieloma wątkami działa w jednym tłumaczu. W dowolnym momencie tłumacz ten jest utrzymywany przez jeden wątek. Oznacza to, że tylko wątek, w którym znajduje się tłumacz, działa w dowolnym momencie .
Dlaczego to jest problem:
Twoja maszyna może mieć wiele rdzeni / procesorów. I wiele rdzeni pozwala na jednoczesne wykonywanie wielu wątków, tzn. Wiele wątków może być wykonywanych w dowolnym momencie. . Ale ponieważ interpreter jest utrzymywany przez jeden wątek, inne wątki nic nie robią, nawet jeśli mają dostęp do rdzenia. Tak więc, nie otrzymujesz żadnej korzyści zapewnianej przez wiele rdzeni, ponieważ w dowolnym momencie używany jest tylko jeden rdzeń, który jest rdzeniem używanym przez wątek, w którym aktualnie znajduje się interpreter. Tak więc wykonanie programu potrwa tak długo, jak gdyby był to program jednowątkowy.
Jednak potencjalnie blokujące lub długotrwałe operacje, takie jak operacje we / wy, przetwarzanie obrazu i niszczenie liczb NumPy, zdarzają się poza GIL. Zabrano stąd . W przypadku takich operacji operacja wielowątkowa będzie nadal szybsza niż pojedyncza operacja wątkowa, pomimo obecności GIL. Tak więc GIL nie zawsze jest wąskim gardłem.
Edycja: GIL to szczegół implementacji CPython. IronPython i Jython nie mają GIL, więc powinien być w nich naprawdę wielowątkowy program, myślałem, że nigdy nie korzystałem z PyPy i Jython i nie jestem tego pewien.
źródło
Python nie pozwala na wielowątkowość w najprawdziwszym tego słowa znaczeniu. Ma pakiet wielowątkowy, ale jeśli chcesz wielowątkowy, aby przyspieszyć swój kod, zwykle nie jest dobrym pomysłem, aby go użyć. Python ma konstrukcję o nazwie Global Interpreter Lock (GIL).
https://www.youtube.com/watch?v=ph374fJqFPE
GIL zapewnia, że tylko jeden z twoich „wątków” może być wykonywany jednocześnie. Wątek nabywa GIL, wykonuje trochę pracy, a następnie przekazuje GIL do następnego wątku. Dzieje się to bardzo szybko, więc dla ludzkiego oka może się wydawać, że twoje wątki wykonują się równolegle, ale tak naprawdę po prostu korzystają z tego samego rdzenia procesora. Całe to przekazywanie GIL zwiększa koszty wykonania. Oznacza to, że jeśli chcesz, aby Twój kod działał szybciej, korzystanie z pakietu wątków często nie jest dobrym pomysłem.
Istnieją powody, aby używać pakietu wątków Pythona. Jeśli chcesz uruchomić kilka rzeczy jednocześnie, a wydajność nie jest problemem, to jest całkowicie w porządku i wygodne. Lub jeśli uruchamiasz kod, który musi na coś czekać (jak niektóre IO), może to mieć sens. Ale biblioteka wątków nie pozwoli na użycie dodatkowych rdzeni procesora.
Wielowątkowość może być zlecona na zewnątrz systemu operacyjnego (poprzez przetwarzanie wieloskładnikowe), niektórych zewnętrznych aplikacji, które wywołują Twój kod Python (np. Spark lub Hadoop), lub jakiegoś kodu, który wywołuje Twój kod Python (np .: możesz mieć swój Python wywołanie kodu funkcji C, która wykonuje kosztowne wielowątkowe operacje).
źródło
Ilekroć dwa wątki mają dostęp do tej samej zmiennej, masz problem. Na przykład w C ++ sposobem na uniknięcie tego problemu jest zdefiniowanie jakiejś blokady mutex, aby zapobiec dwóm wątkom, aby, powiedzmy, wejść do obiektu ustawiającego obiekt w tym samym czasie.
Wielowątkowość jest możliwa w Pythonie, ale dwa wątki nie mogą być wykonywane w tym samym czasie z większą dokładnością niż jedna instrukcja Pythona. Działający wątek otrzymuje blokadę globalną o nazwie GIL.
Oznacza to, że jeśli zaczniesz pisać kod wielowątkowy, aby skorzystać z procesora wielordzeniowego, wydajność się nie poprawi. Zwykłym obejściem jest przejście na wiele procesów.
Pamiętaj, że możesz zwolnić GIL, jeśli jesteś w metodzie, którą napisałeś na przykład w C.
Korzystanie z GIL nie jest nieodłączne od Pythona, ale z niektórych jego interpreterów, w tym z najczęstszym CPython. (#edytowane, patrz komentarz)
Problem GIL jest nadal aktualny w Pythonie 3000.
źródło
Dokumentacja Python 3.7
Chciałbym również podkreślić następujący cytat z dokumentacji Pythona
threading
:To łącze do pozycji Glosariusz, w
global interpreter lock
której wyjaśniono, że GIL sugeruje, że równoległość wątkowa w Pythonie jest nieodpowiednia do zadań związanych z procesorem :Ten cytat sugeruje również, że dyktowania, a tym samym przypisywanie zmiennych, są również wątkowo bezpieczne jako szczegóły implementacji CPython:
Następnie dokumentacja
multiprocessing
pakietu wyjaśnia, w jaki sposób pokonuje GIL poprzez proces odradzania, ujawniając interfejs podobny dothreading
:I dokumentacja dla
concurrent.futures.ProcessPoolExecutor
wyjaśnienia, że wykorzystujemultiprocessing
jako backend:które powinny być skontrastowane z inną klasą bazową,
ThreadPoolExecutor
która używa wątków zamiast procesówz którego dochodzimy do wniosku, że
ThreadPoolExecutor
jest odpowiedni tylko do zadań związanych z We / Wy, a jednocześnieProcessPoolExecutor
może obsługiwać zadania związane z procesorem.Poniższe pytanie dotyczy przede wszystkim tego, dlaczego GIL istnieje: Dlaczego blokada globalnego interpretera?
Eksperymenty procesowe a wątkowe
W Multiprocessing vs Threading Python przeprowadziłem eksperymentalną analizę procesu vs wątków w Pythonie.
Szybki podgląd wyników:
źródło
Dlaczego Python (CPython i inni) korzysta z GIL
From http://wiki.python.org/moin/GlobalInterpreterLock
W CPython globalna blokada interpretera (GIL) to muteks, który uniemożliwia wielu wątkom natywnym wykonywanie bajtów kodu Pythona jednocześnie. Ta blokada jest konieczna głównie dlatego, że zarządzanie pamięcią CPython nie jest bezpieczne dla wątków.
Jak usunąć go z Pythona?
Podobnie jak Lua, może Python mógłby uruchomić wiele maszyn wirtualnych, ale Python tego nie robi, myślę, że powinny istnieć inne powody.
W Numpy lub w innej rozszerzonej bibliotece Pythona czasami udostępnienie GIL innym wątkom może zwiększyć wydajność całego programu.
źródło
Chcę podzielić się przykładem z wielowątkowości książki dotyczącej efektów wizualnych. Oto klasyczna sytuacja martwego zamka
Teraz rozważ zdarzenia w sekwencji powodujące zakleszczenie.
źródło