Wyjaśnienie GVL
Dlaczego wątki są ograniczone
Wyjaśnienie GVL to bezpłatna lekcja Ruby Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Ruby Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Ruby Academy zawiera 4 lekcji w sumie.
Czym jest GVL?
GVL (Global VM Lock, historycznie GIL) to blokada wewnątrz CRuby, standardowego interpretera Ruby.
- Pozwala ona tylko jednemu wątkowi wykonywać kod Ruby w danej chwili.
- Chroni wewnętrzne mechanizmy interpretera przed uszkodzeniem podczas współbieżnego dostępu.
- Oznacza to, że kod Ruby wykonujący wyłącznie obliczenia CPU nie działa naprawdę równolegle na wielu rdzeniach.
Zrozumienie GVL wyjaśnia, kiedy wątki pomagają, a kiedy nie.
Dlaczego istnieje
Wewnętrzne mechanizmy CRuby (alokowanie obiektów, garbage collection i rozszerzenia C) nie zostały w całości zaprojektowane jako bezpieczne wątkowo. GVL zapewnia im bezpieczeństwo, wykonując kod Ruby szeregowo.
Usunięcie go w bezpieczny i uporządkowany sposób jest trudne, dlatego CRuby nadal go używa. JRuby i TruffleRuby nie mają GVL i mogą uruchamiać wątki na wielu rdzeniach.
Praca typu CPU-bound
W przypadku zadań typu CPU-bound (obliczeń matematycznych, sortowania i analizowania) wątki nie przyspieszają działania programu w CRuby. W danej chwili tylko jeden wątek wykonuje kod Ruby, więc dwa wątki CPU dają w przybliżeniu efekt jednego wątku powiększony o dodatkowy narzut.
def heavy
sum = 0
1_000_00.times { |i| sum += i }
sum
end
puts heavy
puts "CPU work does not parallelize under the GVL"Operacje I/O zwalniają GVL
Najważniejsza informacja jest taka, że blokujące operacje I/O zwalniają GVL. Gdy wątek śpi, odczytuje plik lub czeka na gniazdo, zwalnia blokadę, dzięki czemu inny wątek może wykonywać kod Ruby.
Dlatego wątki świetnie nadają się do pracy typu I/O-bound nawet w obecności GVL.
Nakładające się oczekiwanie
W tym przykładzie trzy wątki wykonują sleep. Ponieważ sleep zwalnia GVL, okresy oczekiwania nakładają się na siebie. Całkowity czas wynosi około 0.2s, a nie 0.6s.
start = Time.now
threads = (1..3).map do
Thread.new { sleep 0.2 }
end
threads.each(&:join)
elapsed = Time.now - start
puts "Elapsed roughly: " + elapsed.round(1).to_sRozszerzenia C mogą go zwalniać
Dobrze napisane rozszerzenia C mogą zwalniać GVL podczas długotrwałych obliczeń natywnych za pomocą rb_thread_call_without_gvl. Dzięki temu intensywne operacje natywne mogą działać równolegle, a wątki Ruby mogą kontynuować pracę.
Niektóre biblioteki osiągają więc prawdziwą równoległość nawet w CRuby.
Wątki nadal się przełączają
Nawet w przypadku pracy CPU GVL nie zamraża pozostałych wątków na zawsze. CRuby okresowo wywłaszcza wątek, aby każdy otrzymał swoją kolej. Praca jest współbieżna (przeplatana), ale nie równoległa (wykonywana jednocześnie).
results = []
mutex = Mutex.new
threads = (1..3).map do |n|
Thread.new do
mutex.synchronize { results << n }
end
end
threads.each(&:join)
puts "Collected: " + results.sort.join(", ")Współbieżność a równoległość
Dwa ważne pojęcia:
- Współbieżność: zadania robią postępy, przeplatając się. GVL na to pozwala.
- Równoległość: zadania działają dokładnie w tym samym momencie na różnych rdzeniach. GVL uniemożliwia to w przypadku kodu Ruby.
Wątki zapewniają współbieżność, a Ractory zapewniają równoległość.
Omijanie GVL
Aby wykorzystać wiele rdzeni do pracy CPU w CRuby, można:
- Uruchomić wiele procesów (każdy ma własny GVL).
- Użyć Ractorów do uzyskania równoległości w obrębie jednego procesu.
- Przekazać pracę do rozszerzeń C, które zwalniają GVL.
W przypadku pracy I/O zwykłe wątki zazwyczaj wystarczą.
Procesy nie współdzielą GVL
Każdy proces systemu operacyjnego uruchamia własną maszynę wirtualną Ruby z własnym GVL. Forkowanie zapewnia prawdziwą równoległość, ale procesy nie współdzielą pamięci i zużywają więcej zasobów.
puts "Main pid: " + Process.pid.to_s
puts "Each forked process has its own independent GVL"Wybór strategii
Wskazówki dotyczące wyboru:
- Dużo czasu spędzanego na oczekiwaniu? Proszę użyć wątków.
- Dużo obliczeń CPU i potrzeba wykorzystania rdzeni? Proszę użyć procesów lub Ractorów.
- Potrzebny jest współdzielony stan? Proszę użyć wątków z
Mutex, pamiętając o ograniczeniach GVL.
Znajomość GVL zapobiega typowemu błędowi polegającemu na oczekiwaniu, że wątki CPU będą skalować się liniowo.
Szybki test
Sprawdź swoją wiedzę na temat GVL.
Podsumowanie: GVL
Najważniejsze informacje o Global VM Lock:
- W CRuby tylko jeden wątek wykonuje kod Ruby w danej chwili.
- GVL chroni wewnętrzne mechanizmy interpretera.
- Blokujące operacje I/O zwalniają GVL, umożliwiając nakładanie się okresów oczekiwania.
- Praca Ruby typu CPU-bound nie jest wykonywana równolegle na wielu rdzeniach.
- Do uzyskania prawdziwej równoległości należy użyć procesów lub Ractorów.
Następnie przyjrzymy się fiberom, które zapewniają lekką współbieżność kooperatywną.
Często zadawane pytania
Czy lekcja „Wyjaśnienie GVL” jest bezpłatna?
Tak — pełny tekst „Wyjaśnienie GVL” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Ruby Academy, przejdź na CoddyKit PRO. Kurs Ruby Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Wyjaśnienie GVL”?
Dlaczego wątki są ograniczone Ćwiczysz Ruby Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Ruby Academy?
Nie wymagamy żadnego doświadczenia. Ruby Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Wyjaśnienie GVL”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Ruby Academy?
Tak. Każda lekcja Ruby Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.