Hyperthreading unter Linux deaktivieren (kein Zugriff auf das BIOS)

26

Ich habe ein System, auf dem eine Finanzhandelsanwendung in einer Remote-Einrichtung ausgeführt wird. Ich habe keinen Zugriff auf die ILO / DRAC, muss aber das Hyperthreading deaktivieren. Auf dem System werden Intel Westmere 3,33 GHz X5680-Hex-Core-CPUs ausgeführt. Ich kann neu starten, möchte aber sicherstellen, dass das System das Hyperthreading aufgrund von Leistungsproblemen nicht aktiviert. Gibt es eine saubere Möglichkeit, dies von Linux aus zu tun?

Bearbeiten: Die nohtAnweisung, die der Kernel-Boot-Befehlszeile hinzugefügt wurde, funktionierte nicht. Gleiches gilt für RHEL.

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

ewwhite
quelle

Antworten:

21

Sie können dies zur Laufzeit tun, wenn Sie möchten. Ich habe eine nette Lösung gefunden, die hier beschrieben wurde: http://www.absolutelytech.com/2011/08/01/how-to-disable-cpu-cores-in-linux/

Schritt 1: Identifizieren Sie die Linux-CPUs, die Sie ausschalten möchten:

cat /proc/cpuinfo

Suchen Sie nach den CPUs mit der gleichen "Core-ID", die Sie von jedem Paar ausschalten möchten.

Schritt 2: Schalten Sie die Hyperthreading-CPUs aus (in meinem Fall die letzten vier der insgesamt 8 "CPUs", die von Linux gesehen werden)

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

Sie können sich ein Skript einrichten, das Sie direkt nach dem Systemstart ausführen.

ahus1
quelle
1
Es funktioniert fast so, wie ich es erwartet hatte. Virtuelle Kerne sind deaktiviert. Wenn ich jetzt einen CPU-verbrauchenden Thread ausführe, wird der physische Kern zu 100% geladen. Die Verwendung von sysbench --num-threads=1 --test=cpu runHT mit verschiedenen num-Threads und aktiviertem und deaktiviertem HT bedeutet jedoch, dass das Deaktivieren von HT die Leistung verringert, wenn viele Threads vorhanden sind. Auch wenn nur ein Thread vorhanden ist, hat das Deaktivieren von HT keinen Vorteil. Ich empfehle daher, es so zu belassen, wie es ist: es ist optimal.
Sergey P. aka azure
Möchten Sie wissen, wie der Befehl lautet, um sie wieder einzuschalten? Der Link am Anfang Ihrer Antwort ist tot ~. Vielen Dank!
User189035
@ user189035: echo 1anstatt echo 0sie wieder einzuschalten .
Peter Cordes
@ SergeyP.akaazure, ich denke für eine Finanzdienstleistungsanwendung ist der Hauptgrund für das Ausschalten von HT nicht die Leistung, sondern die Sicherheit.
Simon Richter
@SimonRichter Zu der Zeit, als diese Frage ursprünglich geschrieben wurde, war es in der Tat Leistung. SMT / HT war bei einigen Workloads auf CPUs dieser Ära bei weitem nicht so gut. Das Meltdown / Spectre-Ding und die jüngeren Foreshadow-Angriffe ereigneten sich Jahre später.
Michael Hampton
14

Ein Skript zum Deaktivieren von Hyperthreading beim Systemstart ...

Um das Hyperthreading zu deaktivieren, füge ich ein Skript auf der Maschine /etc/rc.local hinzu. Es ist nicht sehr sauber, aber einfach zu installieren, unabhängig von der CPU-Architektur und sollte auf jeder modernen Linux-Distribution funktionieren.

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;    

Wie funktioniert das?

Auf Informationen und Steuerelemente des Linux-Kernels kann in modernen Linux-Distributionen als Datei im Verzeichnis / sys zugegriffen werden. Beispielsweise:

/ sys / devices / system / cpu / cpu3 enthält die Kernelinformationen und Steuerelemente für die logische CPU 3.

cat / sys / devices / system / cpu / cpu3 / topology / core_id zeigt die Core-Nummer an, zu der diese logische CPU gehört.

echo "0"> / sys / devices / system / cpu / cpu3 / online ermöglicht das Deaktivieren der logischen CPU 3.

Warum funktioniert es?

Ich weiß nicht genau, warum ... aber das System reagiert mit abgeschaltetem Hyperthreading schneller (auf meinem i5-Notebook und massiven Xeon-Servern mit über 60 Kernen). Ich vermute, das hat mit CPU-Caches, CPU-Speicherzuweisung, CPU-Scheduler-Zuweisung und komplexen Iterationen der Prozessprioritäten zu tun. Ich denke, die Vorteile von Hyperthreading werden durch die Komplexität der Erstellung von CPU-Schedulern überstrapaziert, die wissen, wie man es verwendet.

Für mich ist das Problem beim Hyperthreading: Wenn ich so viele CPU-intensive Threads starte, wie ich logische Kerne habe, habe ich schnelle Kontextwechsel für die CPU-intensiven Tasks, aber teure für die Hintergrundtasks, da das Hyperthreading von den vollständig in Anspruch genommen wird CPU-intensive Aufgaben. Wenn ich dagegen so viele CPU-intensive Threads starte, wie ich physische Kerne habe, gibt es keine Kontextwechsel zu diesen Aufgaben und schnelle Kontextwechsel für die Hintergrundaufgaben. Scheint gut zu sein, aber die Hintergrundaufgaben werden freie logische Prozessoren finden und fast sofort ausgeführt. Es ist, als wären sie Echtzeit-Performace (nett -20).

Im ersten Szenario handelt es sich beim Hyperthreading um Uselles. Bei den Hintergrundaufgaben werden teure Kontextwechsel verwendet, da ich das Hyperthreading mit der normalen Verarbeitung maximal genutzt habe. Die zweite ist nicht zu korrigieren, da bis zu 50% meiner CPU-Leistung für die Hintergrundaufgaben priorisiert werden.

Die "CPU-intensiven" Aufgaben, von denen ich spreche, sind Data Mining mit künstlicher Intelligenz und Berechtigungsserver (meine Arbeit). Mixer-Rendering in billigen Computern und Clustern (um mein zukünftiges Haus zu skizzieren).

Auch das ist eine Vermutung.

Ich habe den Eindruck, dass es besser ist, aber es kann nicht.

Lucas
quelle
Ich denke, mein Scriptlet ist etwas einfacher zu befolgen.
Paul M
9

Hängen Sie bei sehr alten Kerneln (Linux 2.6.9 oder höher) den Parameter noht beim Booten an den Kernel an.

Diese Kernel-Befehlszeilenoption wurde seit mindestens Linux 2.6.18 entfernt .


Von 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. 

Wenn du lilo verwendest, bearbeite deine /etc/lilo.conf (und starte danach lilo) oder wenn du grub verwendest, bearbeite deine /boot/grub/menu.lst.

rems
quelle
Entspricht dies funktional der Deaktivierung von HT im BIOS?
Ewwhite
Ich weiß das nicht genau, aber ich würde erwarten, dass es nicht gleichbedeutend ist, wenn man es im BIOS deaktiviert.
Rems
2
Dies ist ein Gentoo-System. Ich habe den nohtEintrag in der Befehlszeile des Grub-Kernels ausprobiert . Das System hat den nohtBefehl nicht eingehalten . Gleiches gilt für RHEL. Siehe: bugzilla.redhat.com/show_bug.cgi?id=440321#c9
ewwhite
1
Dies ist seit mindestens Linux 2.6.18 veraltet . Die nohtKernel-Option wurde entfernt. Dies ist bedauerlich, da Linux eine Problemumgehung für einige Haswell-Leistungsindikator-Errata (BJ122, BV98, HSD29) nur dann ermöglicht, wenn HT aktiviert ist , und dies geschieht, bevor initramfs überhaupt geladen wird.
Peter Cordes
9

Sie können die "thread_siblings_list" für jeden Kern verwenden, um den zweiten Kern im HT-Paar auszuschalten.

Die folgende Befehlspipeline ist hacky, nicht optimiert und wurde hoffentlich auf diese Weise erstellt, um das Verständnis zu erleichtern.

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 )

Nehmen Sie also alle Thread-Geschwisterlisten, extrahieren Sie die zweite CPU für jedes Paar, erstellen Sie eine eindeutige Liste, und deaktivieren Sie sie dann.

Macht das Sinn?

Wenn ich nach dem Ausführen des obigen Befehls "cat / proc / cpuinfo" ausführe, halbiert sich die Anzahl der Kerne.

Paul M
quelle
Das ist eine großartige Antwort. Ich musste es wie folgt ändern, um für meine Zwecke zu arbeiten: echo 0 > /sys/devices/system/cpu/cpu$X/onlinewirdecho 0 | sudo tee /sys/devices/system/cpu/cpu$X/online
Carbocation
5

Neuere Kernel bieten eine SMT-Steuerung (Simultaneous Multithreading).

Sie können den Status von SMT mit überprüfen.

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

Ändern Sie den Zustand mit

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

Optionen sind;

  • auf
  • aus
  • Immer aus

Wir haben dies mit Linux Kernel 4.4.0 getestet

Nick Bascombe-Fox
quelle
Hallo Nick und willkommen auf der Seite. Die Informationen zu Tests (und Versionen) sind sehr wertvoll.
Kubanczyk
Ausgezeichnet, getestet auf Ubuntu 16.04.6 LTS
Elder Geek
4

Lukas 'Antwort ist nett, funktioniert aber nicht wirklich zum Deaktivieren von HT, da die Kern-ID nicht zur Identifizierung von HT-Geschwistern dienen kann. Dieses Skript funktioniert stattdessen:

#!/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
quelle
Ihr Skript ist eine Variation von mir. wir müssten überprüfen, was passiert, wenn Sie mehrere CPUs haben, nur um sicherzugehen.
Paul M
@PaulM Genau hier habe ich es getestet und für meine Zwecke verwendet: 2-Socket-Haswell-System.
Anton
0

Ich musste warten, bis ich bei der ILO / Drac einsteigen konnte. Die Kernel-Boot-Parameter funktionieren auf aktuellen Linux-Distributionen nicht.

ewwhite
quelle
0

Im Paket libsmbios-bin (Debian, Ubuntu usw.) haben Sie die Binärdateien isCmosTokenActive und activateCmosToken. Zusammen mit der Token-Liste können Sie dann Folgendes ausprobieren:

# 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

Aktivieren Sie dann das Token CPU_Hyperthreading_Disable:

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

Überprüfen:

# 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

Die große Frage ist nun, ob Sie einfach einen Neustart benötigen, damit dies wirksam wird, oder ob ein vollständiger Aus- und Wiedereinschalten erforderlich ist. Probieren Sie es aus und sehen Sie, wie es geht!

svenx
quelle
0

Basierend auf den Informationen, die Paul M hier zur Verfügung gestellt hat, würde ich es folgendermaßen "skripten":

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'

Natürlich wird das Hyper-Threading nicht in demselben Sinne deaktiviert, wie das Basteln mit dem BIOS . Im Grunde wird nur der Kernel-Taskplaner angewiesen, einige Kerne nicht zu verwenden, da wir wissen, dass es sich um gefälschte Kerne handelt.

Software, deren Annahme auf dem vorherigen Status /procoder /sysSubsystem basiert, wird möglicherweise immer noch nicht optimal ausgeführt oder schlägt aufgrund dieser Laufzeitänderung sogar fehl, sodass möglicherweise ein Neustart erforderlich ist. Zum Beispiel habe ich bemerkt irqbalance, dass es unter diesen Umständen leicht zu Fehlern kommt.

Poige
quelle
0

HT deaktivieren:

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

HT aktivieren:

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

Hinweis: Dies deaktiviert HyperThreading nicht wirklich, aber sie deaktivieren die "gefälschten" Kerne, die fast das gleiche Ergebnis erzielen.

Zibri
quelle
Ich mag die Art und Weise, wie Sie sie verwenden tee, aber dies ist immer noch nicht die richtige Antwort auf die Frage. Diese Befehle gelten nur für bestimmte Hardwarekonfigurationen und können unbeabsichtigte Auswirkungen auf andere Hardwarekonfigurationen haben. Und eine Erklärung, was diese Befehle tun, fehlt völlig.
Kasperd
Da 0 aus und 1 ein bedeutet, fand ich es leicht verständlich, dass der erste 4 Kerne ausschaltet (von den gefälschten 8 bei einem Quandocore mit Hyperthreading) und der zweite sie wieder einschaltet ... Wenn Sie ein DUAL haben Im Kern muss diese Zahl {3,4} anstelle von {4..7} sein. Wenn Sie einen Oktacore verwenden, muss sie {8..15}
lauten
0

Altes Thema, hatte aber Grund, dieses Experiment zu versuchen. Erstens bin ich mir überhaupt nicht sicher, ob das Deaktivieren der (leicht gefälschten) CPUs zur Laufzeit wirklich dem Deaktivieren von Hyperthreading beim Booten entspricht. Trotzdem habe ich in unserer Anwendung eine kleine Leistungssteigerung festgestellt. (Aber nicht genug zum behalten.)

Verwendete den thread_siblings- Wert (der bei Hyperthread-CPUs üblich ist) als Schlüssel zum Aktivieren / Deaktivieren:

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 

Versuchen Sie den Befehl ohne das endgültige sudo sh , um die Richtigkeit zu überprüfen.

Preston L. Bannister
quelle