Désactiver l'hyperthreading depuis Linux (pas d'accès au BIOS)

26

J'ai un système exécutant une application de trading financier dans une installation distante. Je n'ai pas accès à l'OIT / DRAC, mais je dois désactiver l'hyperthreading. Le système utilise des processeurs hex-core Intel Westmere 3,33 GHz X5680. Je peux redémarrer, mais je veux m'assurer que le système n'active pas l'hyperthreading en raison de problèmes de performances. Existe-t-il un moyen propre de le faire à partir de Linux?

Edit: La nohtdirective ajoutée à la ligne de commande de démarrage du noyau n'a pas fonctionné. Idem pour RHEL.

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

ewwhite
la source

Réponses:

21

Vous pouvez le faire au moment de l'exécution si vous le souhaitez. J'ai trouvé une belle solution décrite ici: http://www.absolutelytech.com/2011/08/01/how-to-disable-cpu-cores-in-linux/

Étape 1: Identifiez les CPU Linux que vous souhaitez désactiver:

cat /proc/cpuinfo

Recherchez les processeurs qui ont le même "core id", vous souhaitez désactiver l'un de chaque paire.

Étape 2: désactivez les processeurs hyperthreading (dans mon cas, les quatre derniers des 8 processeurs totaux vus par 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

Vous pouvez configurer vous-même un script que vous exécutez juste après le démarrage du système.

ahus1
la source
1
Cela fonctionne presque comme je m'y attendais. les cœurs virtuels sont désactivés, maintenant lorsque j'exécute un thread consommant du processeur, il charge le cœur physique de 100%. Mais l'utilisation sysbench --num-threads=1 --test=cpu runavec différents threads numériques et HT activés et désactivés indique que la désactivation de HT diminue les performances lorsqu'il existe de nombreux threads, et même s'il n'y a qu'un seul thread, il n'y a aucun avantage à désactiver HT. Je suggère donc de le laisser tel quel: c'est optimal.
Sergey P. aka azur
Savez-vous quelle est la commande pour les réactiver? Le lien au début de votre réponse est mort ~. Merci!
user189035
@ user189035: echo 1au lieu de echo 0devrait les réactiver .
Peter Cordes
@ SergeyP.akaazure, je pense que pour une application de services financiers, la principale raison de désactiver HT n'est pas la performance, mais la sécurité.
Simon Richter
@SimonRichter Au moment où cette question a été rédigée à l'origine, il s'agissait bien de performances. SMT / HT n'était pas aussi bon pour certaines charges de travail sur les processeurs de cette époque. La chose Meltdown / Spectre et les attaques Foreshadow les plus récentes se sont produites des années plus tard.
Michael Hampton
14

Un script pour désactiver l'hyperthreading au démarrage de la machine ...

Pour désactiver l'hyperthreading, j'inclus un script sur la machine /etc/rc.local. Il n'est pas extrêmement propre, mais il est facile à installer, indépendamment de l'architecture du processeur et devrait fonctionner sur n'importe quelle distribution Linux moderne.

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;    

Comment ça marche?

Les informations et les contrôles du noyau Linux sont accessibles sous forme de fichiers dans le répertoire / sys sur les distributions Linux modernes. Par exemple:

/ sys / devices / system / cpu / cpu3 contient les informations et les contrôles du noyau pour le cpu logique 3.

cat / sys / devices / system / cpu / cpu3 / topology / core_id affichera le numéro de cœur auquel appartient ce cpu logique.

echo "0"> / sys / devices / system / cpu / cpu3 / online permet de désactiver le cpu logique 3.

Pourquoi ça marche?

Je ne sais pas exactement pourquoi ... mais le système devient plus réactif avec l'hyperthreading (sur mon ordinateur portable i5 et les serveurs Xeon massifs avec plus de 60 cœurs). Je suppose que cela a à voir avec les caches par processeur, l'allocation de mémoire par processeur, l'allocation du planificateur de processeur et les itérations complexes des priorités de processus. Je pense que les avantages de l'hyperthreading sont plus importants que la complexité de la création d'ordonnanceurs cpu qui savent comment l'utiliser.

Pour moi, le problème avec l'hyperthreading est: si je démarre autant de threads gourmands en CPU que j'ai de cœurs logiques, j'aurai des changements de contexte rapides pour les tâches gourmandes en CPU, mais coûteux pour les tâches d'arrière-plan, car l'hyperthreading est totalement consommé par le tâches intensives du processeur. D'un autre côté, si je démarre autant de threads gourmands en CPU que j'ai de cœurs physiques, je n'aurai aucun changement de contexte pour ces tâches et des changements de contexte rapides pour les tâches d'arrière-plan. Cela semble bien, mais les tâches d'arrière-plan trouveront des processeurs logiques gratuits et s'exécuteront presque immédiatement. C'est comme s'ils étaient des performances en temps réel (nice -20).

Dans le premier scénario, l'hyperthreading est uselle, les tâches en arrière-plan utiliseront des commutateurs de contexte coûteux car j'ai optimisé l'hyperthreading avec le traitement normal. La seconde est inacceptable car jusqu'à 50% de ma puissance de processeur est priorisée pour les tâches d'arrière-plan.

Les tâches "intensives en CPU" dont je parle sont les serveurs d'exploration de données et d'autorisation d'intelligence artificielle (mon travail). Rendu Blender dans des ordinateurs bon marché et des clusters (pour esquisser ma future maison).

C'est aussi une conjecture.

J'ai l'impression que c'est mieux, mais ce n'est peut-être pas le cas.

Lucas
la source
Je pense que mon scriptlet est un peu plus facile à suivre.
Paul M
9

Pour les noyaux vraiment anciens (Linux 2.6.9 ou plus), ajoutez le paramètre noht au noyau au démarrage.

Cette option de ligne de commande du noyau a été supprimée depuis au moins Linux 2.6.18 .


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

Si vous utilisez lilo, éditez /etc/lilo.conf (et exécutez lilo par la suite) ou si vous utilisez grub, éditez votre /boot/grub/menu.lst.

rems
la source
Est-ce fonctionnellement équivalent à désactiver HT dans le BIOS?
ewwhite
Je ne le sais pas avec certitude, mais oui, je m'attendrais à ce que noht soit équivalent à le désactiver sur le BIOS.
rems
2
Ceci est un système Gentoo. J'ai essayé l' nohtentrée dans la ligne de commande du noyau grub. Le système n'a pas honoré la nohtcommande. Idem pour RHEL. Voir: bugzilla.redhat.com/show_bug.cgi?id=440321#c9
ewwhite
1
Ceci est obsolète depuis au moins Linux 2.6.18 . L' nohtoption du noyau a été supprimée. C'est malheureux, car Linux permet une solution de contournement pour certains errata de compteur de performances Haswell (BJ122, BV98, HSD29) uniquement si HT est activé , et cela se produit avant même que initramfs ne soit chargé.
Peter Cordes
9

Vous pouvez utiliser la "thread_siblings_list" pour chaque cœur pour désactiver le deuxième cœur de la paire HT.

Le pipeline de commandes suivant est hacky, non optimisé et fait de cette façon, espérons-le, pour le rendre plus facile à comprendre.

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 )

prenez donc toutes les listes de frères et sœurs de threads, extrayez le deuxième processeur pour chaque paire, obtenez une liste unique, puis désactivez-les.

Est-ce que ça a du sens?

si je fais "cat / proc / cpuinfo" après avoir exécuté ce qui précède, le nombre de cœurs est divisé par deux.

Paul M
la source
C'est une excellente réponse. J'ai dû le modifier comme suit pour travailler à mes fins: echo 0 > /sys/devices/system/cpu/cpu$X/onlinedevientecho 0 | sudo tee /sys/devices/system/cpu/cpu$X/online
carbocation
5

Les noyaux plus récents fournissent un contrôle SMT (Simultaneous Multithreading).

Vous pouvez vérifier l'état de SMT avec;

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

Changez l'état avec

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

Les options sont;

  • sur
  • de
  • forceoff

Nous l'avons testé avec Linux Kernel 4.4.0

Nick Bascombe-Fox
la source
Salut Nick et bienvenue sur le site. Les informations sur les tests (et la version) sont très utiles.
kubanczyk
Excellent, testé sur Ubuntu 16.04.6 LTS
Elder Geek
4

La réponse de Lukas est agréable mais ne fonctionne pas vraiment pour désactiver HT car l'ID de base ne peut pas servir à l'identification des frères et sœurs HT. Ce script fonctionne à la place:

#!/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
la source
votre script est une variante du mien. nous devrons vérifier ce qui se passe si vous avez plusieurs processeurs, juste pour être sûr.
Paul M
@PaulM C'est exactement là que j'ai testé et utilisé à mes fins: système Haswell à 2 prises.
Anton
0

J'ai dû attendre de pouvoir entrer au BIT / Drac. Les paramètres de démarrage du noyau ne fonctionnent pas sur les distributions Linux actuelles.

ewwhite
la source
0

Dans le paquet libsmbios-bin (Debian, Ubuntu, etc.), vous avez les binaires isCmosTokenActive et activateCmosToken. Avec la liste des jetons , vous pouvez ensuite essayer quelque chose comme ceci:

# 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

Activez ensuite le jeton CPU_Hyperthreading_Disable:

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

Vérifier:

# 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

Maintenant, la grande question est de savoir si vous avez simplement besoin d'un redémarrage pour que cela prenne effet, ou si un cycle d'alimentation complet est requis. Essayez-le et voyez comment ça se passe!

svenx
la source
0

Sur la base des informations fournies par Paul M ici, je le "script" de cette façon:

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'

Bien sûr, cela ne désactive pas l'hyper-threading dans le même sens que le bricolage avec le BIOS , fondamentalement, cela indique uniquement au planificateur de tâches du noyau de ne pas utiliser certains cœurs, car nous savons qu'ils sont faux.

Un logiciel qui a fait son hypothèse en fonction de l'état précédent du sous-système /procou de son /syssous-système peut encore fonctionner sous-optimal ou même échouer en raison de ce changement d'exécution, de sorte que son redémarrage peut être nécessaire. Par exemple, j'ai remarqué qu'il irqbalanceétait susceptible d'échouer dans ces circonstances.

poige
la source
0

Désactiver HT:

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

Activer HT:

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

Remarque: Cela ne désactive pas vraiment HyperThreading mais désactive les "faux" cœurs obtenant presque le même résultat.

Zibri
la source
J'aime la façon dont vous utilisez tee, mais cela ne répond toujours pas à une vraie réponse à la question. Ces commandes ne s'appliquent qu'à des configurations matérielles spécifiques et peuvent avoir des effets inattendus sur d'autres configurations matérielles. Et une explication de ce que font ces commandes est complètement absente.
kasperd
Puisque 0 signifie éteint et 1 signifie allumé, j'ai pensé qu'il était facile de comprendre que le premier éteint 4 cœurs (des faux 8 sur un quandocore avec hyperthreading activé) et le second les rallume ... Si vous avez un DUAL noyau, ce nombre doit être {3,4} au lieu de {4..7} Si vous utilisez un octacore, il doit être {8..15}
Zibri
0

Vieux sujet, mais avait raison d'essayer cette expérience. Tout d'abord, je ne suis pas du tout certain que la désactivation des CPU (légèrement faux) au moment de l'exécution soit vraiment équivalente à la désactivation de l'hyperthreading au démarrage. Cela dit, j'ai vu une petite augmentation des performances dans notre application. (Mais pas assez pour garder.)

Utilisé la valeur thread_siblings (commune aux CPU hyperthreadés) comme clé pour activer / désactiver:

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 

Essayez la commande sans le dernier sudo sh pour vérifier qu'elle est correcte.

Preston L. Bannister
la source