Goroutines na tym samym thread

0

Mam aplikacje, w której używam goroutines, komunikują się one między sobą za pomocą chaneli, proste obliczenia. Wrzucam ja na kubernetesa gdzie mam ustawione 1CPU - jeśli dobrze rozumiem jest to jeden thread. I tutaj jest wszystko spoko. Jak dodam kolejne CPU, to nie widzę jednak przyspieszenia znaczącego. I jeśli dobrze to rozumiem to to co się dzieje, to scheduler rozdziela gorutyny między dwa thready. No i tutaj moc golanga idzie się paść, bo i tak trzeba między threadami przeskakiwać. Jest jakaś możliwość, by wszystkie konkretne gorutyny, które się ze sobą komunikują były odpalane na tym samym threadzie? Nie wiem czy dobrze to wyjaśniłem, o co mi chodzi. Mam nadzieję, że ktoś złapie :P Z tego co wiem w Rust Actix da się coś takiego zrobić.

0
Dregorio napisał(a):

Mam aplikacje, w której używam goroutines, komunikują się one między sobą za pomocą chaneli, proste obliczenia. Wrzucam ja na kubernetesa gdzie mam ustawione 1CPU - jeśli dobrze rozumiem jest to jeden thread

Runtime go tworzy ileśtam wątków systemowych, które procesują gorutyny. Teoretycznie nie ma limitu wątków, które runtime może stworzyć. Jest za to limit aktywnych wątków, które mogą się wykonywać w tym samym czasie. Owy limit można zmienić na przykład przez zmienną środowiskową GOMAXPROCS. Domyślnie wartość zmiennej to ilość CPU.

Dregorio napisał(a):

No i tutaj moc golanga idzie się paść, bo i tak trzeba między threadami przeskakiwać.

A możesz wytłumaczyć dlaczego tak uważasz? Ten problem powinien być już rozwiązany od go 1.5.

Dokument: "Go 1.5 GOMAXPROCS Default":

(...) It is much cheaper to switch between two goroutines in the same thread than to switch between two goroutines in different threads.

Goroutine scheduling affinity and other improvements to the scheduler have largely addressed the problem, by keeping goroutines that are concurrent but not parallel in the same thread.

0

@nalik: Chyba się zgubiłem. Na jednym wątku jak tworzy ileś wątków systemowych? Czy ja źle rozumiem co oznacza 1CPU na kubernetesie albo źle rozumiem pojęcie wątku? Limit wątków jest bo są one zależne od hardware, nie ma limitu gorutyn (teoretycznie, bo są zależne od runtime)

Edit.
Znam GOMAXPROCS, z jakiegoś powodu jednak tych faktów nie połączyłem ze sobą

Edit2.
Jeśli dobrze rozumiem, jak mam 2CPU i ustawie GOMAXPROC, to jeden thread będzie sobie praktycznie nieużywany. No bo jak wszystkie goroutyny mają być na jednym, a main() jest gorutyna, i wszystkie handlery są. To nagle nie opłaca mi się dodawać CPU

1

Być może masz jakieś braki z rozumienia H/W i systemów operacyjnych. Jest wątek sprzętowy i wątek systemowy. Ustawienie k8s dotyczy wątków sprzętowych dostępnych dla uruchomionego kontenera/poda. Z kolei wątki używane przez runtime go to oczywiście wątki systemowe. To czy wątki utworzone przez runtime go będą w pełni wykorzystane zależy od decyzji podjętych przez scheduler go, bo to on decyduj jak rozdystrybuować gorutyny.

Wątek systemowy to jednostka egzekucji kodu w jednym procesie zarządzana przez jądro systemu. System dzieli czas CPU pomiędzy procesy i wątki dzięki takim technikom jak wywłaszczanie oraz przełączanie kontekstu. Na systemie z jednym CPU i jednym rdzeniem jak najbardziej można mieć wielowątkowe aplikacji.

0

Dzięki. Wygląda na to, że.musze odświeżyć wiedzę ze studiów.

BTW. Czytam sobie o tym GOMAXPROC i jeśli dobrze rozumiem to jeśli ustawie na 1. To będzie on odpalał wszystkie goroutyny na jednym wątku, ale jak przyjdzie jakąś operacja I/O to wtedy wrzuci to na nowy wątek. Co dla mnie by było ok.

Edit.

Na systemie z jednym CPU i jednym rdzeniem jak najbardziej można mieć wielowątkowe aplikacji.

No tak, ale context switching będzie bardzo kosztowny.

0

BTW. Czytam sobie o tym GOMAXPROC i jeśli dobrze rozumiem to jeśli ustawie na 1. To będzie on odpalał wszystkie goroutyny na jednym wątku, ale jak przyjdzie jakąś operacja I/O to wtedy wrzuci to na nowy wątek. Co dla mnie by było ok.

@Dregorio: operacje IO dzieją się tak jakby w tyle. Poczytaj jak działa np. https://man7.org/linux/man-pages/man7/epoll.7.html . Generalnie twój program może spokojnie jechać na jednym CPU i obsługiwać bardzo dużo połączeń IO na raz. Inaczej to wygląda, gdy wykonujesz jakieś ciężkie obliczenia: wtedy im więcej wątków tym lepiej

0

Jak dodam kolejne CPU, to nie widzę jednak przyspieszenia znaczącego

Znaczące przyspieszenie zobaczysz tylko i wyłącznie wtedy gdy będziesz wykonywał operacje typu cpu-bound. Dla operacji IO-bound jeden wątek często wystarcza każdemu (ala jeszcze do niedawna NodeJS).

Nie powinieneś ingerować w bebechy Go typu scheduler. One powinny być transparentne dla twojego programu. Można sobie wyobrazić że za rok pojawi się nowy lepszy scheduler z szeregiem nowych ustawień i innym zachowaniem. Lepiej ograniczyć się do abstrakcji które oferuje sam język (go routines) i nie zaglądać pod maskę.

Również: https://stackoverflow.com/questions/19758961/is-it-possible-to-force-a-go-routine-to-be-run-on-a-specific-cpu

1 użytkowników online, w tym zalogowanych: 0, gości: 1