Deshabilite hyperthreading desde Linux (sin acceso a BIOS)

26

Tengo un sistema que ejecuta una aplicación de comercio financiero en una instalación remota. No tengo acceso a la OIT / DRAC, pero necesito deshabilitar hyperthreading. El sistema ejecuta CPUs Intel Westmere 3.33GHz X5680 de núcleo hexagonal. Puedo reiniciar, pero quiero asegurarme de que el sistema no permita el hyperthreading debido a problemas de rendimiento. ¿Hay una manera limpia de hacer esto desde Linux?

Editar: la nohtdirectiva agregada a la línea de comando de arranque del núcleo no funcionó. Lo mismo para RHEL.

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

ewwhite
fuente

Respuestas:

21

Puede hacerlo en tiempo de ejecución si lo desea. Encontré una buena solución descrita aquí: http://www.absolutelytech.com/2011/08/01/how-to-disable-cpu-cores-in-linux/

Paso 1: identifique las CPU de Linux que desea apagar:

cat /proc/cpuinfo

Busque las CPU que tienen la misma "identificación de núcleo", desea desactivar uno de cada par.

Paso 2: apague las CPU hyperthreading (en mi caso, las últimas cuatro del total de 8 "CPU" vistas por 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

Puede configurar un script que ejecute justo después de iniciar el sistema.

ahus1
fuente
1
Funciona casi como esperaba. los núcleos virtuales están deshabilitados, ahora cuando ejecuto un subproceso que consume CPU, carga el núcleo físico en un 100%. Pero el uso sysbench --num-threads=1 --test=cpu runcon diferentes hilos numéricos y HT activado y desactivado dice que deshabilitar HT disminuye el rendimiento cuando hay muchos hilos, e incluso si solo hay un hilo no hay ningún beneficio en desactivar HT. Así que sugiero dejarlo como está: es óptimo.
Sergey P. aka azure
¿Sabrías cuál es el comando para volver a encenderlos? El enlace al comienzo de tu respuesta está muerto ~. ¡Gracias!
user189035
@ user189035: en echo 1lugar de echo 0volver a encenderlos.
Peter Cordes
@ SergeyP.akaazure, creo que para una aplicación de servicios financieros, la razón principal para desactivar HT no es el rendimiento, sino la seguridad.
Simon Richter
@SimonRichter En el momento en que esta pregunta se escribió originalmente, en realidad era rendimiento. SMT / HT no era tan bueno en algunas cargas de trabajo en las CPU de esa época. Lo de Meltdown / Spectre y los ataques Foreshadow más recientes ocurrieron años después.
Michael Hampton
14

Un script para deshabilitar hyperthreading en el inicio de la máquina ...

Para deshabilitar hyperthreading, incluyo un script en la máquina /etc/rc.local. No es exactamente limpio, pero es fácil de instalar, independiente de la arquitectura de la CPU y debería funcionar en cualquier distribución moderna de Linux.

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;    

¿Cómo funciona esto?

Se puede acceder a la información y los controles del kernel de Linux como archivos en el directorio / sys en las distribuciones modernas de Linux. Por ejemplo:

/ sys / devices / system / cpu / cpu3 contiene la información del núcleo y los controles para la CPU lógica 3.

cat / sys / devices / system / cpu / cpu3 / topology / core_id mostrará el número central al que pertenece esta CPU lógica.

echo "0"> / sys / devices / system / cpu / cpu3 / online permite deshabilitar la CPU lógica 3.

Por que funciona

No sé exactamente por qué ... pero el sistema se vuelve más receptivo con hyperthreading apagado (en mi computadora portátil i5 y servidores Xeon masivos con más de 60 núcleos). Supongo que eso tiene que ver con cachés por CPU, asignación de memoria por CPU, asignación del planificador de CPU y iteraciones complejas de prioridades de proceso. Creo que los beneficios de hyperthreading son mayores que la complejidad de hacer programadores de CPU que saben cómo usarlo.

Para mí, el problema con hyperthreading es: si inicio tantos subprocesos intensivos en CPU como núcleos lógicos, tendré cambios rápidos de contexto para las tareas intensivas en CPU, pero costosos para las tareas en segundo plano ya que el hyperthreading totalmente consumido por el CPU tareas intensivas. Por otro lado, si inicio tantos subprocesos intensivos en CPU como núcleos físicos, no tendré cambios de contexto para esas tareas y cambios rápidos de contexto para las tareas en segundo plano. Parece bueno, pero las tareas en segundo plano encontrarán procesadores lógicos libres y se ejecutarán casi inmediatamente. Es como si fueran en tiempo real (bonito -20).

En el primer escenario, el hyperthreading es uselles, las tareas en segundo plano utilizarán costosos cambios de contexto porque maximicé el hyperthreading con el procesamiento normal. El segundo es inaceptable porque hasta el 50% de la potencia de mi CPU tiene prioridad para las tareas en segundo plano.

Las tareas "intensivas en CPU" de las que estoy hablando son servidores de autorización y minería de datos de inteligencia artificial (mi trabajo). Representación de Blender en computadoras y clústeres baratos (para dibujar mi futura casa).

Además, esto es conjeturas.

Tengo la impresión de que es mejor, pero puede que no.

Lucas
fuente
Creo que mi scriptlet es un poco más fácil de seguir.
Paul M
9

Para núcleos realmente antiguos (Linux 2.6.9 más o menos), agregue el parámetro noht al núcleo en el arranque.

Esta opción de línea de comandos del núcleo se ha eliminado desde al menos Linux 2.6.18 .


De 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 usa lilo edite /etc/lilo.conf (y ejecute lilo después) o si usa grub, edite su /boot/grub/menu.lst.

rems
fuente
¿Es esto funcionalmente equivalente a deshabilitar HT en el BIOS?
ewwhite
No lo sé con seguridad, pero sí, esperaría que noth sea equivalente a deshabilitarlo en el BIOS.
rems
2
Este es un sistema Gentoo. Intenté la nohtentrada en la línea de comando del núcleo grub. El sistema no cumplió con el nohtcomando. Lo mismo para RHEL. Ver: bugzilla.redhat.com/show_bug.cgi?id=440321#c9
ewwhite
1
Esto es obsoleto desde al menos Linux 2.6.18 . La nohtopción del núcleo fue eliminada. Esto es desafortunado, porque Linux habilita una solución alternativa para algunas erratas de contador de rendimiento Haswell (BJ122, BV98, HSD29) solo si HT está activado , y esto sucede antes de que se inicie initramfs.
Peter Cordes
9

Puede usar "thread_siblings_list" para cada núcleo para desactivar el segundo núcleo en el par HT.

La siguiente línea de comandos es hacky, no está optimizada y se hace de esta manera con la esperanza de que sea más fácil de entender.

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 )

entonces, tome todas las listas de hermanos de subprocesos, extraiga la segunda CPU para cada par, obtenga una lista única y luego apáguelos.

¿Esto tiene sentido?

si hago "cat / proc / cpuinfo" después de ejecutar lo anterior, la cantidad de núcleos se reduce a la mitad.

Paul M
fuente
Esta es una respuesta genial. Tuve que modificar de la siguiente manera al trabajo para mis propósitos: echo 0 > /sys/devices/system/cpu/cpu$X/onlinese convierte enecho 0 | sudo tee /sys/devices/system/cpu/cpu$X/online
carbocatión
5

Los núcleos más nuevos proporcionan un control de subprocesamiento múltiple simultáneo (SMT).

Puede verificar el estado de SMT con;

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

Cambiar el estado con

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

Las opciones son;

  • en
  • apagado
  • forzar fuera

Hemos probado esto con Linux Kernel 4.4.0

Nick Bascombe-Fox
fuente
Hola Nick y bienvenido al sitio. La información sobre las pruebas (y la versión) es bastante valiosa.
kubanczyk
Excelente, probado en Ubuntu 16.04.6 LTS
Elder Geek
4

La respuesta de Lukas es buena, pero en realidad no funciona para deshabilitar HT porque el ID del núcleo no puede servir para identificar a los hermanos HT. Este script funciona en su lugar:

#!/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
fuente
Tu guión es una variación de la mía. Tendríamos que comprobar qué sucede si tiene varias CPU, solo para estar seguros.
Paul M
@PaulM Ahí es exactamente donde lo probé y lo usé para mis propósitos: sistema Haswell de 2 sockets.
Anton
0

Tuve que esperar hasta poder ingresar a la OIT / Drac. Los parámetros de arranque del kernel no funcionan en las distribuciones actuales de Linux.

ewwhite
fuente
0

En el paquete libsmbios-bin (Debian, Ubuntu, etc.), tiene los binarios isCmosTokenActive y enableCmosToken. Junto con la lista de tokens , puede intentar algo como esto:

# 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

Luego active el token CPU_Hyperthreading_Disable:

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

Verificar:

# 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

Ahora, la gran pregunta es si simplemente necesita reiniciar para que esto surta efecto, o si se requiere un ciclo de energía completo. ¡Pruébalo y mira cómo va!

svenx
fuente
0

Según la información proporcionada por Paul M aquí, lo "guionaría" de esta manera:

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'

Por supuesto , no está desactivando el hiperprocesamiento en el mismo sentido que lo haría con el BIOS , básicamente solo le dice al programador de tareas del núcleo que no use algunos núcleos porque sabemos que son falsos.

El software que hizo su suposición basándose en el estado anterior /proco en el /syssubsistema aún podría estar funcionando por debajo del óptimo o incluso fallar debido a este cambio en el tiempo de ejecución, por lo que podría ser necesario reiniciarlo. Por ejemplo, me di cuenta de que irqbalanceera propenso a fallar en esas circunstancias.

poige
fuente
0

Deshabilitar HT:

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

Habilitar HT:

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

Nota: Esto realmente no deshabilita HyperThreading pero deshabilita los núcleos "falsos" obteniendo casi el mismo resultado.

Zibri
fuente
Me gusta la forma en que está usando tee, pero esto aún no proporciona una respuesta real a la pregunta. Esos comandos solo se aplican a configuraciones de hardware específicas y pueden tener efectos no deseados en otras configuraciones de hardware. Y una explicación de lo que hacen esos comandos está completamente ausente.
Kasperd
Dado que 0 significa apagado y 1 significa encendido, pensé que era fácil entender que el primero apaga 4 núcleos (del falso 8 en un quandocore con hyperthreading activado) y el segundo los vuelve a encender ... Si tiene un DUAL ese número debe ser {3,4} en lugar de {4..7} Si usa un octacore, debe ser {8..15}
Zibri
0

Viejo tema, pero tenía motivos para probar este experimento. Primero, no estoy del todo seguro de que deshabilitar las CPU (ligeramente falsas) en tiempo de ejecución sea realmente equivalente a deshabilitar Hyperthreading en el arranque. Dicho esto, vi un pequeño aumento de rendimiento en nuestra aplicación. (Pero no lo suficiente como para mantenerlo).

Usó el valor thread_siblings (común a las CPU con hipertrama) como clave para habilitar / deshabilitar:

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 

Pruebe el comando sin el sudo sh final para verificar que sea correcto.

Preston L. Bannister
fuente