Chcemy zaktualizować system operacyjny na naszych serwerach z Ubuntu 10.04 LTS do Ubuntu 12.04 LTS. Niestety, wydaje się, że opóźnienie uruchomienia wątku, który stał się gotowy do uruchomienia, znacznie wzrosło z jądra 2.6 do jądra 3.2. W rzeczywistości trudno uwierzyć w liczby latencji, które otrzymujemy.
Powiem bardziej szczegółowo o teście. Mamy program, który uruchamia dwa wątki. Pierwszy wątek pobiera bieżący czas (w taktach przy użyciu RDTSC), a następnie co sekundę sygnalizuje zmienną warunkową. Drugi wątek czeka na zmienną warunkową i budzi się, gdy zostanie zasygnalizowana. Następnie pobiera aktualny czas (w taktach przy użyciu RDTSC). Różnica między czasem w drugim wątku a czasem w pierwszym wątku jest obliczana i wyświetlana na konsoli. Po tym drugi wątek jeszcze raz czeka na zmienną warunku. Zostanie ponownie zasygnalizowany przez pierwszy wątek po około drugim przejściu.
Tak więc, w skrócie, otrzymujemy w rezultacie wątek do komunikacji między wątkami za pośrednictwem pomiaru opóźnień zmiennych warunkowych raz na sekundę.
W jądrze 2.6.32 to opóźnienie jest gdzieś w granicach 2,8-3,5 nas, co jest rozsądne. W jądrze 3.2.0 to opóźnienie wzrosło do około 40-100 us. Wykluczyłem wszelkie różnice sprzętowe między dwoma hostami. Działają na identycznym sprzęcie (procesory z podwójnym gniazdem X5687 {Westmere-EP} pracujące z częstotliwością 3,6 GHz z hiperwątkowością, prędkością skoku i wyłączonymi wszystkimi stanami C). Aplikacja testowa zmienia koligację wątków, aby uruchamiać je na niezależnych rdzeniach fizycznych tego samego gniazda (tj. Pierwszy wątek jest uruchamiany na rdzeniu 0, a drugi na rdzeniu 1), więc nie ma odbijania wątków rdzenie lub odbijanie / komunikacja między gniazdami.
Jedyną różnicą między tymi dwoma hostami jest to, że na jednym działa Ubuntu 10.04 LTS z jądrem 2.6.32-28 (szybka zmiana kontekstu), a na drugim działa najnowszy Ubuntu 12.04 LTS z jądrem 3.2.0-23 (powolny kontekst Skrzynka z wyłącznikami). Wszystkie ustawienia BIOS i sprzęt są identyczne.
Czy zaszły jakieś zmiany w jądrze, które mogłyby wyjaśnić to absurdalne spowolnienie czasu, w którym zaplanowano uruchomienie wątku?
Aktualizacja: Jeśli chcesz uruchomić test na swoim hoście i kompilacji systemu Linux, opublikowałem kod do wklejania do wglądu. Połącz z:
g++ -O3 -o test_latency test_latency.cpp -lpthread
Uruchom z (zakładając, że masz co najmniej dwurdzeniowy box):
./test_latency 0 1 # Thread 1 on Core 0 and Thread 2 on Core 1
Aktualizacja 2 : Po długich przeszukiwaniu parametrów jądra, postach na temat zmian w jądrze i osobistych badaniach, zorientowałem się, na czym polega problem i opublikowałem rozwiązanie jako odpowiedź na to pytanie.
źródło
/proc/sys/kernel/*
może zadziałać? Jeśli znajdziesz coś, co działa, umieść tę konfigurację/etc/sysctl.conf
lub plik,/etc/sysctl.d/
aby zachować ją po ponownym uruchomieniu.Odpowiedzi:
Rozwiązanie problemu z wydajnością budzenia złego wątku w najnowszych jądrach wiąże się z przejściem na
intel_idle
sterownik cpuidle zacpi_idle
, sterownik używany w starszych jądrach. Niestetyintel_idle
sterownik ignoruje konfigurację BIOS-u użytkownika dla stanów C i tańczy do własnej melodii . Innymi słowy, nawet jeśli całkowicie wyłączysz wszystkie stany C w BIOS-ie twojego komputera (lub serwera), ten sterownik nadal będzie wymuszał ich włączenie w okresach krótkiej nieaktywności, które prawie zawsze mają miejsce, chyba że syntetyczny test porównawczy zużywający cały rdzeń (np. ) biegnie. Możesz monitorować przejścia stanu C, a także inne przydatne informacje związane z częstotliwościami procesora, używając wspaniałego narzędzia Google i7z na większości kompatybilnych urządzeń.Aby zobaczyć, który sterownik cpuidle jest obecnie aktywny w twojej konfiguracji, po prostu znajdź
current_driver
plik wcpuidle
sekcji w/sys/devices/system/cpu
następujący sposób:Jeśli chcesz, aby Twój nowoczesny system operacyjny Linux miał jak najmniejsze opóźnienie przełączania kontekstu, dodaj następujące parametry rozruchowe jądra, aby wyłączyć wszystkie te funkcje oszczędzania energii:
W systemie Ubuntu 12.04 możesz to zrobić, dodając je do
GRUB_CMDLINE_LINUX_DEFAULT
wpisu/etc/default/grub
i uruchamiającupdate-grub
. Parametry rozruchu do dodania to:Oto krwawe szczegóły dotyczące tego, co robią trzy opcje rozruchu:
Ustawienie
intel_idle.max_cstate
na zero albo przywróci sterownik cpuidle doacpi_idle
(przynajmniej zgodnie z dokumentacją opcji), albo całkowicie go wyłączy. Na moim komputerze jest całkowicie wyłączony (tj. Wyświetleniecurrent_driver
pliku w/sys/devices/system/cpu/cpuidle
daje wyjścienone
). W tym przypadku druga opcja rozruchu nieprocessor.max_cstate=0
jest konieczna. Jednak dokumentacja stwierdza, że ustawienie max_cstate na zero dlaintel_idle
sterownika powinno przywrócić system operacyjny doacpi_idle
sterownika. Dlatego na wszelki wypadek wstawiłem drugą opcję rozruchu.processor.max_cstate
Opcja określa maksymalny stan C dlaacpi_idle
kierowcy do zera, mam nadzieję, że wyłączenie go również. Nie mam systemu, na którym mógłbym to przetestować, ponieważintel_idle.max_cstate=0
całkowicie wyłącza sterownik cpuidle na całym dostępnym mi sprzęcie. Jednakże, jeśli instalacja nie powracają z wamiintel_idle
, abyacpi_idle
tylko z pierwszej opcji bootowania, proszę dać mi znać, jeśli druga opcja,processor.max_cstate
nie to, co zostało udokumentowane zrobić w komentarzach, tak że mogę zaktualizować tę odpowiedź.Wreszcie ostatni z trzech parametrów,
idle=poll
to prawdziwa świnia mocy. Wyłączy C1 / C1E, co spowoduje usunięcie ostatniego pozostałego bitu opóźnienia kosztem znacznie większego zużycia energii, więc używaj tego tylko wtedy, gdy jest to naprawdę konieczne. Dla większości będzie to przesada, ponieważ opóźnienie C1 * nie jest aż tak duże. Używając mojej aplikacji testowej działającej na sprzęcie, który opisałem w pierwotnym pytaniu, opóźnienie wzrosło z 9 do 3 nas. Jest to z pewnością znacząca redukcja w przypadku aplikacji wrażliwych na duże opóźnienia (np. Handel finansowy, precyzyjna telemetria / śledzenie, akwizycja danych o wysokiej częstotliwości itp.), Ale może nie być warta poniesionych strat energii elektrycznej w przypadku zdecydowanej większości aplikacje komputerowe. Jedynym sposobem, aby mieć pewność, jest profilowanie poprawy wydajności aplikacji w porównaniu zAktualizacja:
Po dodatkowych testach z różnymi
idle=*
parametrami odkryłem, że ustawienieidle
na,mwait
jeśli jest obsługiwane przez twój sprzęt, jest znacznie lepszym pomysłem. Wydaje się, że użycieMWAIT/MONITOR
instrukcji pozwala procesorowi wejść do C1E bez żadnego zauważalnego opóźnienia dodawania do czasu wybudzania wątku. Dziękiidle=mwait
temu uzyskasz niższą temperaturę procesora (w porównaniu doidle=poll
), mniejsze zużycie energii i nadal zachowasz doskonałe niskie opóźnienia pętli bezczynności odpytywania. Dlatego mój zaktualizowany zalecany zestaw parametrów rozruchowych dla niskiego opóźnienia wątku procesora w oparciu o te ustalenia to:Użycie
idle=mwait
zamiast zamiastidle=poll
może również pomóc w zainicjowaniu Turbo Boost (pomagając procesorowi utrzymać się poniżej jego TDP [Thermal Design Power]) i hiperwątkowości (dla której MWAIT jest idealnym mechanizmem, który nie zużywa całego fizycznego rdzenia, a jednocześnie unikanie wyższych stanów C). Jednak nie zostało to jeszcze udowodnione w testach, które będę nadal robić.Aktualizacja 2:
Opcja
mwait
idle została usunięta z nowszych jąder 3.x (podziękowania dla użytkownika ck_ za aktualizację). To daje nam dwie możliwości:idle=halt
- Powinien działać równie dobrzemwait
, ale przetestuj, aby upewnić się, że tak jest w przypadku twojego sprzętu.HLT
Instrukcja jest niemal równoznaczne zMWAIT
z nutą państwowej 0. Problem tkwi w tym, że przerwanie jest wymagane, aby wydostać się z państwa HLT, podczas zapisu do pamięci (lub przerwanie) może być używany, aby wydostać się z państwa MWAIT. W zależności od tego, czego używa jądro Linuksa w swojej pętli bezczynności, może to zwiększyć wydajność MWAIT. Tak więc, jak powiedziałem, przetestuj / profil i zobacz, czy spełnia twoje potrzeby dotyczące opóźnienia ...i
idle=poll
- Opcja o najwyższej wydajności kosztem mocy i ciepła.źródło
Być może to, co stało się wolniejsze, to futex, element składowy zmiennych warunkowych. To rzuci trochę światła:
następnie
który pokaże mikrosekundy potrzebne dla interesujących wywołań systemowych, posortowane według czasu.
W jądrze 2.6.32
W jądrze 3.1.9
Znalazłem ten 5-letni raport o błędzie, który zawiera test wydajności „ping ponga”, który porównuje
Musiałem dodać
w celu kompilacji, co zrobiłem za pomocą tego polecenia
W jądrze 2.6.32
W jądrze 3.1.9
Dochodzę do wniosku, że przełączanie kontekstu między jądrem 2.6.32 a 3.1.9 rzeczywiście zwolniło, chociaż nie tak bardzo, jak obserwuje się w jądrze 3.2. Zdaję sobie sprawę, że to jeszcze nie odpowiada na twoje pytanie, będę dalej kopać.
Edycja: Odkryłem, że zmiana priorytetu procesu w czasie rzeczywistym (obu wątków) poprawia wydajność w wersji 3.1.9, aby dopasować ją do wersji 2.6.32. Jednak ustawienie tego samego priorytetu na 2.6.32 powoduje spowolnienie ... idź do figury - przyjrzę się temu bardziej.
Oto moje wyniki teraz:
W jądrze 2.6.32
W jądrze 3.1.9
źródło
Możesz również zobaczyć procesory klikające w dół w nowszych procesach i jądrach Linuksa ze względu na sterownik pstate , który jest oddzielny od c- States . Więc dodatkowo, aby to wyłączyć, należy wykonać następujący parametr jądra:
intel_pstate=disable
źródło