Wyłącz hiperwątkowanie z poziomu systemu Linux (brak dostępu do systemu BIOS)

26

Mam system z uruchomioną aplikacją do handlu finansami na zdalnym obiekcie. Nie mam dostępu do ILO / DRAC, ale muszę wyłączyć hyperthreading. System obsługuje sześciordzeniowe procesory Intel Westmere 3.33GHz X5680. Mogę zrestartować komputer, ale chcę się upewnić, że system nie włączy hiperwątkowania z powodu problemów z wydajnością. Czy istnieje czysty sposób na zrobienie tego z poziomu Linuksa?

Edycja: nohtDyrektywa dodana do wiersza komend rozruchu jądra nie działała. To samo dla RHEL.

Zobacz: https://bugzilla.redhat.com/show_bug.cgi?id=440321#c9

ewwhite
źródło

Odpowiedzi:

21

Możesz to zrobić w czasie wykonywania, jeśli chcesz. Znalazłem fajne rozwiązanie opisane tutaj: http://www.absolutelytech.com/2011/08/01/how-to-disable-cpu-cores-in-linux/

Krok 1: Zidentyfikuj procesory z Linuksem, które chcesz wyłączyć:

cat /proc/cpuinfo

Poszukaj procesorów, które mają ten sam „identyfikator rdzenia”, chcesz wyłączyć jedną z każdej pary.

Krok 2: Wyłącz procesory hyperthreading (w moim przypadku ostatnie cztery z wszystkich 8 „CPU” widzianych przez Linux)

echo 0 > /sys/devices/system/cpu/cpu4/online
echo 0 > /sys/devices/system/cpu/cpu5/online
echo 0 > /sys/devices/system/cpu/cpu6/online
echo 0 > /sys/devices/system/cpu/cpu7/online

Możesz skonfigurować sobie skrypt, który uruchamiasz zaraz po uruchomieniu systemu.

ahus1
źródło
1
Działa prawie tak, jak się spodziewałem. rdzenie wirtualne są wyłączone, teraz gdy wykonam jeden wątek zużywający procesor, ładuje rdzeń fizyczny o 100%. Ale używanie sysbench --num-threads=1 --test=cpu runz różnymi numerami wątków i włączonymi i wyłączonymi HT mówi, że wyłączenie HT zmniejsza wydajność, gdy jest wiele wątków, a nawet jeśli jest tylko jeden wątek, nie ma korzyści z wyłączenia HT. Sugeruję więc pozostawić to tak, jak jest: jest optymalne.
Sergey P. aka lazur
Czy wiesz, jakie jest polecenie, aby je ponownie włączyć? Link na początku twojej odpowiedzi jest martwy ~. Dzięki!
user189035 30.10.16
@ user189035: echo 1zamiast echo 0włączać je ponownie.
Peter Cordes
@ SergeyP.akaazure, myślę, że w przypadku aplikacji usług finansowych głównym powodem wyłączenia HT nie jest wydajność, ale bezpieczeństwo.
Simon Richter,
@SimonRichter W momencie, gdy pytanie było pierwotnie napisane, rzeczywiście było to przedstawienie. SMT / HT nie był tak dobry w przypadku niektórych obciążeń procesorów tej epoki. Sprawa Meltdown / Spectre i nowsze ataki Foreshadow miały miejsce wiele lat później.
Michael Hampton
14

Skrypt wyłączający hyperthreading podczas uruchamiania komputera ...

Aby wyłączyć hyperthreading, dołączam skrypt na komputerze /etc/rc.local. Nie jest wyjątkowo czysty, ale jest łatwy w instalacji, niezależny od architektury procesora i powinien działać na każdej nowoczesnej dystrybucji Linuksa.

nano /etc/rc.local

    # place this near the end before the "exit 0"

    for CPU in /sys/devices/system/cpu/cpu[0-9]*; do
        CPUID=$(basename $CPU)
        echo "CPU: $CPUID";
        if test -e $CPU/online; then
                echo "1" > $CPU/online; 
        fi;
        COREID="$(cat $CPU/topology/core_id)";
        eval "COREENABLE=\"\${core${COREID}enable}\"";
        if ${COREENABLE:-true}; then        
                echo "${CPU} core=${CORE} -> enable"
                eval "core${COREID}enable='false'";
        else
                echo "$CPU core=${CORE} -> disable"; 
                echo "0" > "$CPU/online"; 
        fi; 
    done;    

Jak to działa

Informacje i kontrolki jądra systemu Linux są dostępne jako pliki w katalogu / sys w nowoczesnych dystrybucjach linuksa. Na przykład:

/ sys / devices / system / cpu / cpu3 zawiera informacje o jądrze i kontrolki dla logicznego procesora 3.

cat / sys / devices / system / cpu / cpu3 / topology / core_id pokaże numer rdzenia, do którego należy ta logiczna jednostka centralna.

echo "0"> / sys / devices / system / cpu / cpu3 / online pozwala wyłączyć logiczne procesor 3.

Dlaczego to działa?

Nie wiem dokładnie, dlaczego ... ale system staje się bardziej responsywny po wyłączeniu hyperthreadingu (na moim notebooku i5 i ogromnych serwerach Xeon z ponad 60 rdzeniami). Myślę, że ma to związek z buforami na procesor, alokacją pamięci na procesor, alokacją harmonogramu procesora i złożonymi iteracjami priorytetów procesu. Myślę, że korzyści płynące z hiperwątkowania są przeważające ze względu na złożoność tworzenia harmonogramów procesorów, które wiedzą, jak z niego korzystać.

Dla mnie problem z hyperthreadingiem jest taki: jeśli zacznę tyle wątków intensywnie obciążających procesor, ile mam rdzeni logicznych, będę miał szybkie przełączniki kontekstu dla zadań intensywnie obciążających procesor, ale drogie dla zadań w tle, ponieważ hiperwątkowanie całkowicie pochłania intensywne zadania procesora. Z drugiej strony, jeśli rozpocznę tyle wątków intensywnie obciążających procesor, ile mam rdzeni fizycznych, nie będę mieć przełączników kontekstowych na te zadania i szybkich przełączników kontekstowych dla zadań w tle. Wydaje się dobre, ale zadania w tle znajdą wolne procesory logiczne i będą działać prawie bez przeszkód. To tak, jakby występowali w czasie rzeczywistym (ładne -20).

W pierwszym scenariuszu hyperthreading jest bezużyteczny, zadania w tle będą wykorzystywać drogie przełączniki kontekstu, ponieważ maksymalizowałem hyperthreading przy normalnym przetwarzaniu. Drugi jest niedopuszczalny, ponieważ do 50% mojej mocy procesora ma priorytet w zadaniach w tle.

Zadania „intensywnie obciążające procesor”, o których mówię, to wyszukiwanie danych i serwery autoryzacji sztucznej inteligencji (moja praca). Renderowanie blendera w tanich komputerach i klastrach (naszkicować mój przyszły dom).

To także zgadywanie.

Mam wrażenie, że jest lepiej, ale może nie.

Lucas
źródło
Myślę, że mój skryptlet jest trochę łatwiejszy do naśladowania.
Paul M
9

W przypadku naprawdę starych jąder (Linux 2.6.9 lub podobny ), dołącz parametr noht do jądra podczas uruchamiania.

Ta opcja wiersza polecenia jądra została usunięta od co najmniej Linuksa 2.6.18 .


From http://www.faqs.org/docs/Linux-HOWTO/BootPrompt-HOWTO.html :

The `noht' Argument

This will disable hyper-threading on intel processors that have this feature. 

Jeśli używasz lilo, edytuj /etc/lilo.conf (i uruchom lilo później) lub jeśli używasz gruba, edytuj plik /boot/grub/menu.lst.

rems
źródło
Czy to funkcjonalnie odpowiada wyłączeniu HT w BIOS-ie?
ewwhite
Nie wiem tego na pewno, ale tak, nie spodziewałbym się, że nic nie będzie równoznaczne z wyłączeniem go w systemie BIOS.
rems
2
To jest system Gentoo. Próbowałem nohtwpisu w wierszu poleceń jądra grub. System nie dotrzymał nohtpolecenia. To samo dla RHEL. Zobacz: bugzilla.redhat.com/show_bug.cgi?id=440321#c9
ewwhite
1
Jest to przestarzałe, ponieważ przynajmniej Linux 2.6.18 . Opcja nohtjądra została usunięta. Jest to niefortunne, ponieważ Linux umożliwia obejście niektórych błędów erraty licznika Haswell (BJ122, BV98, HSD29) tylko wtedy, gdy HT jest włączony , i dzieje się to przed załadowaniem initramfs.
Peter Cordes
9

Możesz użyć „Thread_siblings_list” dla każdego rdzenia, aby wyłączyć drugi rdzeń w parze HT.

Poniższy potok poleceń jest zhackowany, niezoptymalizowany i ma nadzieję, że w ten sposób będzie łatwiejszy do zrozumienia.

cat /sys/devices/system/cpu/cpu*/topology/thread_siblings_list | \
awk -F, '{print $2}' | \
sort -n | \
uniq | \
( while read X ; do echo $X ; echo 0 > /sys/devices/system/cpu/cpu$X/online ; done )

więc weź wszystkie listy rodzeństwa wątków, wyodrębnij drugi procesor dla każdej pary, uzyskaj unikalną listę, a następnie wyłącz je.

Czy to ma sens?

jeśli zrobię „cat / proc / cpuinfo” po uruchomieniu powyższego, liczba rdzeni zostanie zmniejszona o połowę.

Paul M.
źródło
To świetna odpowiedź. Musiałem go zmodyfikować w następujący sposób, aby działał dla moich celów: echo 0 > /sys/devices/system/cpu/cpu$X/onlinestaje sięecho 0 | sudo tee /sys/devices/system/cpu/cpu$X/online
carbocation
5

Nowsze jądra zapewniają kontrolę równoczesnego wielowątkowości (SMT).

Możesz sprawdzić stan SMT za pomocą;

cat /sys/devices/system/cpu/smt/active

Zmień stan za pomocą

echo off > /sys/devices/system/cpu/smt/control

Dostępne opcje;

  • na
  • poza
  • forceoff

Przetestowaliśmy to z jądrem Linux 4.4.0

Nick Bascombe-Fox
źródło
Cześć Nick i witam na stronie. Informacje o testach (i wersji) są dość cenne.
kubańczyk
Doskonały, testowany na Ubuntu 16.04.6 LTS
Starszy Geek
4

Odpowiedź Lukasa jest miła, ale tak naprawdę nie działa w celu wyłączenia HT, ponieważ identyfikator rdzenia nie może służyć do identyfikacji rodzeństwa HT. Ten skrypt działa zamiast tego:

#!/bin/bash
for CPU in /sys/devices/system/cpu/cpu[0-9]*; do
    CPUID=`basename $CPU | cut -b4-`
    echo -en "CPU: $CPUID\t"
    [ -e $CPU/online ] && echo "1" > $CPU/online
    THREAD1=`cat $CPU/topology/thread_siblings_list | cut -f1 -d,`
    if [ $CPUID = $THREAD1 ]; then
        echo "-> enable"
        [ -e $CPU/online ] && echo "1" > $CPU/online
    else
        echo "-> disable"
        echo "0" > $CPU/online
    fi
done
Anton
źródło
twój skrypt jest moją odmianą. musielibyśmy sprawdzić, co się stanie, jeśli masz wiele procesorów, dla pewności.
Paul M
@PaulM Właśnie tam przetestowałem i użyłem go do swoich celów: 2-gniazdowy system Haswell.
Anton
0

Musiałem czekać, aż będę mógł dostać się do ILO / Drac. Parametry rozruchowe jądra nie działają w bieżących dystrybucjach systemu Linux.

ewwhite
źródło
0

W pakiecie libsmbios-bin (Debian, Ubuntu itp.) Masz pliki binarne isCmosTokenActive i ActivCmosToken. Razem z listą tokenów możesz wypróbować coś takiego:

# isCmosTokenActive 0x00d1 # CPU_Hyperthreading_Enable
[...] Type 0x00d1  Location 0x46 AND(fe) OR(0)  BITFIELD: 1
# isCmosTokenActive 0x00d2 # CPU_Hyperthreading_Disable
[....] Type 0x00d2  Location 0x46 AND(fe) OR(1)  BITFIELD: 0

Następnie aktywuj token CPU_Hyperthreading_Disable:

# activateCmosToken 0x00d2 # CPU_Hyperthreading_Disable
[...] Type 0x00d2  Location 0x46 AND(fe) OR(1)  BITFIELD: 1

Zweryfikować:

# isCmosTokenActive 0x00d1 # CPU_Hyperthreading_Enable
[...] Type 0x00d1  Location 0x46 AND(fe) OR(0)  BITFIELD: 0
# isCmosTokenActive 0x00d2 # CPU_Hyperthreading_Disable
[...] Type 0x00d2  Location 0x46 AND(fe) OR(1)  BITFIELD: 1

Teraz najważniejsze pytanie brzmi, czy po prostu potrzebujesz restartu, aby to zadziałało, czy też wymagany jest pełny cykl zasilania. Wypróbuj i zobacz, jak idzie!

svenx
źródło
0

Na podstawie informacji dostarczonych tutaj przez Paula M „skrypty” to w ten sposób:

fgrep , /sys/devices/system/cpu/cpu*/topology/thread_siblings_list |
cut -d, -f2 | sort -u |
sudo xargs -rI, sh -c 'echo 0 > /sys/devices/system/cpu/cpu,/online'

Oczywiście nie wyłącza hiperwątkowości w tym samym sensie, co robiłoby to majsterkowanie w BIOS-ie , w zasadzie mówi tylko programowi zadań jądra, aby nie używał niektórych rdzeni, ponieważ wiemy, że są fałszywe.

Oprogramowanie, które przyjęło swoje założenie na podstawie poprzedniego stanu /proclub /syspodsystemu, może nadal działać nieoptymalnie lub nawet zawieść z powodu tej zmiany w czasie wykonywania, więc może być konieczne jego ponowne uruchomienie. Na przykład zauważyłem, irqbalanceże w takich okolicznościach był podatny na porażkę.

poige
źródło
0

Wyłącz HT:

echo 0 |sudo tee /sys/devices/system/cpu/cpu{4..7}/online

Włącz HT:

echo 1 |sudo tee /sys/devices/system/cpu/cpu{4..7}/online

Uwaga: To tak naprawdę nie wyłącza HyperThreading, ale wyłącza „fałszywe” rdzenie, uzyskując prawie taki sam wynik.

Zibri
źródło
Podoba mi się sposób, w jaki korzystasz tee, ale nadal nie zapewnia to prawdziwej odpowiedzi na pytanie. Te polecenia mają zastosowanie tylko do określonych konfiguracji sprzętowych i mogą mieć niezamierzony wpływ na inne konfiguracje sprzętowe. A wyjaśnienie tego, co robią te polecenia, jest całkowicie nieobecne.
kasperd
Ponieważ 0 oznacza wyłączenie, a 1 oznacza włączenie, pomyślałem, że łatwo było zrozumieć, że pierwsze wyłącza 4 rdzenie (z fałszywej 8 w quandocore z włączonym hyperthreading), a drugie włącza je z powrotem ... Jeśli masz DUAL rdzeń, liczba ta musi wynosić {3,4} zamiast {4..7} Jeśli używasz ośmiornicy, musi to być {8..15}
Zibri
0

Stary temat, ale miał powód, by spróbować tego eksperymentu. Po pierwsze, nie jestem wcale pewien, czy wyłączenie (nieco fałszywych) procesorów w czasie wykonywania jest naprawdę równoważne wyłączeniu funkcji Hyperthreading przy starcie. To powiedziawszy, zauważyłem niewielki wzrost wydajności w naszej aplikacji. (Ale to za mało, aby zachować.)

Użył thread_siblings wartości (wspólny dla hyperthreaded CPU) jako klucz włączyć / wyłączyć:

for i in /sys/devices/system/cpu/cpu[0-9]* 
do echo "$(cat $i/topology/thread_siblings) $i" 
done | 
awk '{v = (a[$1] ? 0 : 1); a[$1] = 1; print "echo " v " > " $2 "/online"}' | 
sudo sh 

Spróbuj wykonać polecenie bez ostatniego sudo sh, aby sprawdzić poprawność.

Preston L. Bannister
źródło