Dlaczego Python został napisany w GIL?

Globalna blokada interpretera (GIL) wydaje się być często wymieniana jako główny powód, dla którego wątki i tym podobne są trudne w Pythonie – co rodzi pytanie „Dlaczego w ogóle to zrobiono?”

Będąc nie programistą, nie mam pojęcia, dlaczego tak może być – jaka była logika stojąca za wprowadzeniem GIL?

Komentarze

  • artykuł w Wikipedii stwierdza, że ” GIL może być znaczącą przeszkodą dla paralelizmu – cena płacona za dynamizm języka ” , i dodaje, że ” Powody stosowania takiej blokady to: zwiększona prędkość programów jednowątkowych (brak konieczności nabywania lub zwalniania blokad na wszystkich strukturach danych osobno) oraz łatwa integracja bibliotek C, które zwykle są nie jest bezpieczny dla wątków. ”
  • @RobertHarvey, Dynamizm nie ma nic do roboty z tym. Problemem jest mutacja.
  • stackoverflow.com/questions/265687/…
  • Czy ' t nie może pomóc w odczuciu, że podobnie jak ' Javy ' brak liczb bez znaku, miało to zapobiec osobom, które tego nie robią ' nie wiedzą, co robią ' sobie w stopę. Niestety, każdy, kto wie wie, co ' robi, dostaje niedostateczny język, co jest prawdziwym wstydem, ponieważ Python rządzi na wiele innych sposobów
  • @Basic Musi istnieć jakiś standardowy sposób radzenia sobie z tablicami bajtowymi w Javie (nie ' nie używałem go od dłuższego czasu), aby wykonywać obliczenia kryptograficzne. Python (na przykład) nie ' nie ma podpisanych liczb, ale nie ' nie próbowałbym nawet wykonywać z nim operacji bitowych, ponieważ są lepsze sposoby.

Odpowiedź

Istnieje kilka implementacji Pythona, na przykład CPython, IronPython, RPython, itd.

Niektóre z nich mają GIL, inne nie. Na przykład CPython ma GIL:

From http://en.wikipedia.org/wiki/Global_Interpreter_Lock

Aplikacje napisane w językach programowania z wykorzystaniem GIL można zaprojektować tak, aby korzystały z oddzielnych procesów w celu osiągnięcia pełnej równoległości, ponieważ każdy proces ma własny interpreter z kolei ma swój własny GIL.

Korzyści z GIL

  • Zwiększona prędkość programów jednowątkowych.
  • Łatwa integracja bibliotek C, które zwykle nie są bezpieczne dla wątków.

Dlaczego Python (CPython i inne) używa GIL

W CPythonie, globalna blokada interpretera (GIL) jest muteksem, który zapobiega jednoczesnemu wykonywaniu kodów bajtowych Pythona przez wiele natywnych wątków. Ta blokada jest konieczna głównie dlatego, że zarządzanie pamięcią w CPythonie nie jest bezpieczne dla wątków.

GIL jest kontrowersyjny, ponieważ uniemożliwia programom wielowątkowym CPython pełne wykorzystanie zalet systemów wieloprocesorowych w pewnych sytuacjach. Należy pamiętać, że potencjalnie blokuje lub długotrwałe operacje, takie jak I / O, przetwarzanie obrazu i przetwarzanie numerów NumPy, mają miejsce poza GIL. Dlatego tylko w programach wielowątkowych, które spędzają dużo czasu wewnątrz GIL, interpretując kod bajtowy CPython, GIL staje się wąskie gardło.

Python ma GIL w przeciwieństwie do blokowania drobnoziarnistego z kilku powodów:

  • Jest szybszy w przypadku jednowątkowych.

  • Jest szybszy w przypadku programów wielowątkowych dla programów powiązanych we / wy.

  • Jest szybszy w przypadku wielowątkowości dla programów związanych z procesorem ich praca wymagająca dużej mocy obliczeniowej w bibliotekach C.

  • To sprawia Rozszerzenia C łatwiejsze do napisania: nie będzie przełączania wątków Pythona z wyjątkiem przypadków, gdy pozwolisz na to (tj. między makrami Py_BEGIN_ALLOW_THREADS i Py_END_ALLOW_THREADS).

  • Ułatwia to zawijanie bibliotek C. Nie musisz się martwić o bezpieczeństwo wątków. Jeśli biblioteka nie jest bezpieczna dla wątków, po prostu blokujesz GIL podczas jej wywoływania.

GIL może być wydawane przez rozszerzenia C. Standardowa biblioteka Pythona uwalnia GIL wokół każdego blokującego wywołania I / O. W związku z tym GIL nie ma wpływu na wydajność serwerów związanych z wejściem / wyjściem. Możesz więc tworzyć serwery sieciowe w Pythonie za pomocą procesów (fork), wątków lub asynchronicznych operacji wejścia / wyjścia, a GIL nie będzie Ci przeszkadzał.

Biblioteki numeryczne w C lub Fortranie można w podobny sposób wywołać za pomocą GIL wydany. Podczas gdy twoje rozszerzenie C czeka na zakończenie FFT, interpreter będzie wykonywał inne wątki Pythona.GIL jest zatem łatwiejszy i szybszy niż blokowanie drobnoziarniste również w tym przypadku. To stanowi większość pracy numerycznej. Rozszerzenie NumPy zwalnia GIL kiedy tylko jest to możliwe.

Wątki są zwykle złym sposobem pisania większości programów serwerowych. Jeśli ładunek jest mały, rozwidlenie jest łatwiejsze. Jeśli obciążenie jest duże, asynchroniczne programowanie we / wy i sterowane zdarzeniami (np. Przy użyciu Twisted Framework w Pythonie) jest lepsze. Jedynym usprawiedliwieniem korzystania z wątków jest brak os.fork w systemie Windows.

GIL jest problemem wtedy i tylko wtedy, gdy wykonujesz pracę intensywnie wykorzystującą procesor w czystym Pythonie. Tutaj możesz uzyskać czystszy projekt przy użyciu procesów i przekazywania komunikatów (np. Mpi4py). W Pythonie znajduje się również moduł „przetwarzania” sklep, który zapewnia procesom ten sam interfejs co wątki (tj. zamień Threading.Thread na processing.Process).

Wątki mogą być używane do utrzymania responsywności GUI niezależnie od GIL. Jeśli GIL osłabia wydajność (por. powyższa dyskusja), możesz pozwolić swojemu wątkowi zrodzić proces i poczekać na jego zakończenie.

Komentarze

  • Brzmi jak kwaśne winogrona do mnie. Python potrafi ' t poprawnie obsługiwać wątki, więc wymyślasz powody, dla których wątki są niepotrzebne lub nawet złe. ” Jeśli obciążenie jest niski, fo rking jest łatwiejszy „, poważnie? A GIL jest ” szybszy ” we wszystkich tych przypadkach tylko wtedy, gdy nalegasz na używanie GC zliczania odwołań.
  • s/RPython/PyPy/g. @MichaelBorgwardt Podawanie powodów za GIL jest w pewnym sensie celem pytania, czy nie ' tak? Chociaż zgodziłbym się, że część treści tej odpowiedzi (mianowicie dyskusja nad alternatywami) nie ma znaczenia. I na dobre lub na złe, odliczanie jest teraz prawie niemożliwe do pozbycia się – jest głęboko zakorzenione w całym API i bazie kodu; ' jest prawie niemożliwe, aby się go pozbyć bez przepisania połowy kodu i złamania całego kodu zewnętrznego.
  • Nie ' nie zapomnij o bibliotece multiprocessing – standardowej od 2.6. Pule procesów roboczych tego ' są super-zręczną abstrakcją dla niektórych prostych typów równoległości.
  • @alcalde Tylko jeśli nie ' nie wiem, co ' robisz i / lub nie ' nie chcesz, aby Twoje wątki mogły współpracować / porozumieć się. W przeciwnym razie ' jest królewskim problemem, zwłaszcza biorąc pod uwagę obciążenie związane z uruchomieniem nowego procesu w niektórych systemach operacyjnych. Mamy serwery z 32 rdzeniami, więc aby w pełni wykorzystać je w CPythonie, ' d potrzebuję 32 procesów. To ' nie jest ” dobrym rozwiązaniem ” to ' to sposób na obejście niedociągnięć CPythona '.
  • Fakt, że wątki istnieją na platformach innych niż Windows, powinien być wystarczającym dowodem, że rozwidlanie nie jest ' nie wystarcza w każdej sytuacji.

Odpowiedź

Pierwsza off: Python nie ma GIL. Python jest językiem programowania. Język programowania to zbiór abstrakcyjnych reguł matematycznych i ograniczeń. W specyfikacji języka Python nie ma nic, co mówi, że musi istnieć GIL.

Istnieje wiele różnych implementacji Pythona. Niektóre mają GIL, inne nie.

Jednym prostym wytłumaczeniem posiadania GIL jest to, że pisanie współbieżnego kodu jest trudne. Umieszczając gigantyczną blokadę wokół swojego kodu, zmuszasz go, aby zawsze działał seryjnie. Problem rozwiązany!

W szczególności w CPythonie ważnym celem jest ułatwienie rozszerzenia interpretera o wtyczki napisane w C. Ponownie, pisanie współbieżnego kodu jest trudne, więc gwarantując, że nie będzie współbieżność, ułatwia pisanie rozszerzeń dla interpretera. Poza tym wiele z tych rozszerzeń to po prostu cienkie otoki wokół istniejących bibliotek, które mogły nie zostać napisane z myślą o współbieżności.

Komentarze

  • Że ' to ten sam argument, co w Javie ' – brak typów liczbowych bez znaku – programiści uważają, że wszyscy inni są głupsi niż są …
  • @Basic – wierz lub nie, nawet jeśli ' nie jesteś naprawdę głupi, okazuje się, że posiadanie języka, który upraszcza założenia, oznacza, że nie ' Myślenie o pewnych rzeczach, aby działały, jest nadal pożyteczne.CPython jest świetny do pewnych rzeczy, w tym prostych aplikacji wielowątkowych (gdzie program jest powiązany z IO, a jest ich wiele i dlatego GIL nie ' nie ma znaczenia), ponieważ decyzje projektowe, które podjęły GIL to najlepsze rozwiązanie, które również ułatwia programowanie tych aplikacji, zwłaszcza dzięki temu, że obsługuje atomowe operacje na kolekcjach .
  • @Jules Tak, to ' jest bardzo przydatny, dopóki nie będziesz potrzebować tych możliwości. cpython ' s ” preferowane ” rozwiązanie ” po prostu napisz to w innym języku, takim jak c ++ „, oznacza to utratę wszystkich korzyści z Pythona. Jeśli ' piszesz połowę swojego kodu w języku c ++, to po co zaczynać od Pythona? Jasne, w przypadku małych projektów API / kleju jest to ' szybkie i łatwe, a dla ETL ' nie ma sobie równych, ale ' nie nadaje się do wszystkiego, co wymaga podnoszenia dużych ciężarów. To samo, co używanie Javy do komunikacji ze sprzętem … To ' to prawie komiczne obręcze, przez które trzeba przeskoczyć.
  • @Basic Jeden z Pythona ' s i tym samym w większym stopniu podstawową filozofią CPythona ' jest uczynienie technologii ” przyjazną i łatwy w użyciu „. Programowanie równoległe bez blokady globalnej to nie . Biorąc pod uwagę, że istnieje wiele implementacji bez GIL, sensowne jest dostarczenie przynajmniej jednej implementacji, która go posiada.
  • Mówisz „, warto przynajmniej podać jedna implementacja, która to ma. ” lubię to ' to oczywisty wniosek, ale żadnego innego języka I ' mam świadomość, że w ten sposób przeszkadza programistom, więc może ' nie być tak oczywistym.

Odpowiedź

Jaki jest cel GIL?

Dokumentacja CAPI mówi na ten temat:

Interpreter Pythona nie jest w pełni bezpieczny dla wątków . Aby obsługiwać wielowątkowe programy w języku Python, istnieje blokada globalna, zwana globalną blokadą interpretera lub GIL, która musi być utrzymywana przez bieżący wątek, zanim będzie mógł bezpiecznie uzyskać dostęp do obiektów Pythona. Bez blokady nawet najprostsze operacje mogłyby powodować problemy w programie wielowątkowym: na przykład, gdy dwa wątki jednocześnie zwiększają liczbę odwołań do tego samego obiektu, liczba odwołań mogłaby zostać zwiększona tylko raz zamiast dwukrotnie.

Innymi słowy, GIL zapobiega zepsuciu państwa. Programy w Pythonie nigdy nie powinny generować błędu segmentacji, ponieważ dozwolone są tylko operacje bezpieczne dla pamięci. GIL rozszerza to zapewnienie na programy wielowątkowe.

Jakie są alternatywy?

Jeśli celem GIL jest ochrona państwa przed korupcją, to jedną z oczywistych alternatyw jest zamknięcie na znacznie drobniejszym ziarnie; być może na poziomie obiektu. Problem polega na tym, że chociaż wykazano, że zwiększa wydajność programów wielowątkowych, ma więcej narzutów, w wyniku czego programy jednowątkowe cierpią.

Komentarze

  • Byłoby wspaniale pozwolić użytkownikowi uruchomić program z opcją interpretera zastępującą gil dla drobnoziarnistej blokady i w jakiś sposób wiedzieć – w sposób tylko do odczytu – czy bieżący proces został podniesiony z czy bez gil.
  • Pomimo GIL udało mi się wygenerować błąd segmentacji w programie wielowątkowym z powodu nieostrożnego użycia modułu pyodbc. Dlatego ” nigdy nie powinno powodować błędu segmentacji. ” jest błędem.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *