Jestem trochę zdezorientowany, czy wielowątkowość działa w Pythonie, czy nie.
Wiem, że było wiele pytań na ten temat i przeczytałem wiele z nich, ale nadal jestem zdezorientowany. Wiem z własnego doświadczenia i widziałem, jak inni publikują własne odpowiedzi i przykłady tutaj na StackOverflow, że wielowątkowość jest rzeczywiście możliwa w Pythonie. Dlaczego więc wszyscy powtarzają, że Python jest zablokowany przez GIL i tylko jeden wątek może działać na raz? To oczywiście działa. A może jest jakaś różnica, której tu nie dostanę?
Wielu plakatów / respondentów wciąż wspomina, że wątkowanie jest ograniczone, ponieważ nie wykorzystuje wielu rdzeni. Powiedziałbym jednak, że są one nadal przydatne, ponieważ działają jednocześnie, a tym samym szybciej wykonują połączone obciążenie pracą. Mam na myśli, dlaczego w przeciwnym razie miałby istnieć moduł wątku Pythona?
Aktualizacja:
Dzięki za wszystkie dotychczasowe odpowiedzi. Rozumiem, że wielowątkowość będzie działać tylko równolegle dla niektórych zadań we / wy, ale może działać tylko jedno na raz w przypadku zadań wielordzeniowych związanych z procesorem.
Nie jestem do końca pewien, co to oznacza dla mnie w praktyce, więc podam tylko przykład zadania, które chciałbym wykonać wielowątkowo. Na przykład, powiedzmy, że chcę przejrzeć bardzo długą listę ciągów i wykonać kilka podstawowych operacji na każdym elemencie listy. Jeśli podzielę listę, wyślę każdą podlistę do przetworzenia przez mój kod pętli / łańcucha w nowym wątku i odeślę wyniki z powrotem do kolejki, czy te obciążenia będą działać mniej więcej w tym samym czasie? Co najważniejsze, czy to teoretycznie przyspieszy czas potrzebny do uruchomienia skryptu?
Innym przykładem może być to, że mogę wyrenderować i zapisać cztery różne obrazy za pomocą PIL w czterech różnych wątkach i czy będzie to szybsze niż przetwarzanie obrazów jeden po drugim? Wydaje mi się, że naprawdę się zastanawiam nad tym elementem szybkości, a nie nad prawidłową terminologią.
Wiem również o module przetwarzania wieloprocesowego, ale moim głównym zainteresowaniem w tej chwili są małe i średnie obciążenia zadań (10-30 sekund), więc myślę, że wielowątkowość będzie bardziej odpowiednia, ponieważ podprocesy mogą być inicjowane wolno.
źródło
Odpowiedzi:
GIL nie zapobiega gwintowaniu. Wszystko, co robi GIL, to upewnienie się, że tylko jeden wątek wykonuje jednocześnie kod Pythona; control nadal przełącza się między wątkami.
Tym, czego zapobiega GIL, jest wykorzystywanie więcej niż jednego rdzenia procesora lub oddzielnych procesorów do równoległego uruchamiania wątków.
Dotyczy to tylko kodu w Pythonie. Rozszerzenia C mogą i faktycznie zwalniają GIL, aby umożliwić działanie wielu wątków kodu C i jednego wątku Pythona na wielu rdzeniach. Rozciąga się to na operacje we / wy kontrolowane przez jądro, takie jak
select()
wywołania odczytów i zapisów z gniazda, dzięki czemu Python obsługuje zdarzenia sieciowe w rozsądny sposób w wielowątkowej konfiguracji wielordzeniowej.To, co robi wiele wdrożeń serwerów, to uruchamianie więcej niż jednego procesu Pythona, aby umożliwić systemowi operacyjnemu zarządzanie harmonogramem między procesami w celu maksymalnego wykorzystania rdzeni procesora.
multiprocessing
Biblioteki można również używać do obsługi przetwarzania równoległego w wielu procesach z jednej bazy kodu i procesu nadrzędnego, jeśli odpowiada to Twoim przypadkom użycia.Zwróć uwagę, że GIL ma zastosowanie tylko do implementacji CPythona; Jython i IronPython używają innej implementacji wątków (odpowiednio natywnych wspólnych wątków Java VM i .NET).
Aby bezpośrednio zająć się aktualizacją: Każde zadanie, które próbuje uzyskać przyspieszenie z wykonywania równoległego przy użyciu czystego kodu Pythona, nie zobaczy przyspieszenia, ponieważ kod Pythona z wątkami jest zablokowany do jednego wątku wykonywanego na raz. Jeśli jednak mieszasz rozszerzenia C i operacje we / wy (takie jak operacje PIL lub numpy), każdy kod C może działać równolegle z jednym aktywnym wątkiem Pythona.
Obsługa wątków w Pythonie doskonale nadaje się do tworzenia responsywnego interfejsu GUI lub do obsługi wielu krótkich żądań sieci Web, w których operacje wejścia / wyjścia są bardziej wąskim gardłem niż kod Pythona. Nie nadaje się do zrównoleglania kodu Pythona wymagającego dużej mocy obliczeniowej, trzymania się
multiprocessing
modułu w przypadku takich zadań lub delegowania do dedykowanej biblioteki zewnętrznej.źródło
urllib.urlopen()
?),Image.transform()
Wywoływanie jednego skryptu Pythona z poziomu GUI Pythona i wywoływanie wielunumpy.array()
operacji PIL (np. ) I numpy (np. ) Z wątkami. W swoim komentarzu podałeś więcej przykładów, takich jak używanie wielu wątków do odczytywania plików (np.f.read()
?). Wiem, że wyczerpująca lista nie jest możliwa, chciałem tylko typy przykładów, które podałeś w swojej aktualizacji. Tak czy inaczej, zaakceptowałem twoją odpowiedź :)urllib.urlopen()
wywoływałby gniazda sieciowe, oczekiwanie na wejście / wyjście gniazda to doskonała okazja do przełączania wątków i zrobienia czegoś innego.Tak. :)
Masz moduł gwintowania niskiego poziomu i moduł gwintowania wyższego poziomu . Ale jeśli chcesz po prostu używać maszyn wielordzeniowych, wieloprocesorowych jest moduł .
Cytat z dokumentów :
źródło
W Pythonie dozwolone jest tworzenie wątków, jedynym problemem jest to, że GIL upewni się, że tylko jeden wątek jest wykonywany na raz (bez równoległości).
Więc w zasadzie, jeśli chcesz wielowątkowość kodu w celu przyspieszenia obliczeń, nie przyspieszy to, ponieważ tylko jeden wątek jest wykonywany na raz, ale jeśli użyjesz go na przykład do interakcji z bazą danych, to zrobi.
źródło