Desativar hyperthreading no Linux (sem acesso ao BIOS)

26

Eu tenho um sistema executando um aplicativo de negociação financeira em uma instalação remota. Não tenho acesso à OIT / DRAC, mas preciso desativar o hyperthreading. O sistema executa CPUs hexagonais Intel Westmere 3.33GHz X5680. Posso reiniciar, mas quero garantir que o sistema não ative o hyperthreading devido a problemas de desempenho. Existe uma maneira limpa de fazer isso no Linux?

Edit: A nohtdiretiva adicionada à linha de comando de inicialização do kernel não funcionou. O mesmo para RHEL.

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

ewwhite
fonte

Respostas:

21

Você pode fazer isso em tempo de execução, se desejar. Encontrei uma boa solução descrita aqui: http://www.absolutelytech.com/2011/08/01/how-to-disable-cpu-cores-in-linux/

Etapa 1: identifique as CPUs Linux que você deseja desligar:

cat /proc/cpuinfo

Procure as CPUs que possuem o mesmo "núcleo id", você deseja desligar um de cada par.

Etapa 2: Desligue as CPUs hyperthreading (no meu caso, as quatro últimas do total de 8 "CPUs" vistas pelo 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

Você pode configurar um script para executar logo após o início do sistema.

ahus1
fonte
11
Funciona quase como eu esperava. os núcleos virtuais estão desativados; agora, quando executo um thread que consome CPU, ele carrega o núcleo físico em 100%. Porém, o uso sysbench --num-threads=1 --test=cpu runcom diferentes num-threads e o HT ativado e desativado diz que desabilitar o HT diminui o desempenho quando há muitos threads, e mesmo se houver apenas um thread, não há benefício em desativar o HT. Então, sugiro deixar como está: é ótimo.
Sergey P. tcp azure
Você saberia qual é o comando para ativá-los novamente? O link no início da sua resposta está morto ~. Obrigado!
user189035
@ user189035: em echo 1vez de echo 0ativá-los novamente.
Peter Cordes
@ SergeyP.akaazure, acho que para um aplicativo de serviços financeiros, o principal motivo para desativar o HT não é o desempenho, mas a segurança.
Simon Richter
@SimonRichter Na época em que essa pergunta foi originalmente escrita, era de fato desempenho. O SMT / HT não era tão bom em algumas cargas de trabalho em CPUs daquela época. A coisa Meltdown / Spectre, e os ataques Foreshadow mais recentes, aconteceram anos depois.
Michael Hampton
14

Um script para desativar o hyperthreading na inicialização da máquina ...

Para desativar o hyperthreading, incluo um script na máquina /etc/rc.local. Não é exatamente limpo, mas é fácil de instalar, independente da arquitetura da CPU e deve funcionar em qualquer distribuição Linux moderna.

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;    

Como isso funciona?

As informações e os controles do kernel do Linux podem ser acessados ​​como arquivos no diretório / sys nas modernas distribuições linux. Por exemplo:

/ sys / devices / system / cpu / cpu3 contém as informações e controles do kernel da CPU lógica 3.

cat / sys / devices / system / cpu / cpu3 / topology / core_id mostrará o número principal a que esta cpu lógica pertence.

eco "0"> / sys / devices / system / cpu / cpu3 / online permite desativar a cpu lógica 3.

Por que isso funciona?

Não sei exatamente o porquê ... mas o sistema se torna mais responsivo com o hyperthreading desativado (no meu notebook i5 e nos enormes servidores Xeon com mais de 60 núcleos). Eu acho que isso tem a ver com caches por CPU, alocação de memória por CPU, alocação de agendador de CPU e iterações complexas de prioridades de processo. Eu acho que os benefícios do hyperthreading são superados pela complexidade de criar agendadores de CPU que sabem usá-lo.

Para mim, o problema com o hyperthreading é: se eu iniciar tantos threads intensivos em CPU quanto núcleos lógicos, terei alternâncias de contexto rápidas para as tarefas intensivas em CPU, mas caras para as tarefas em segundo plano, pois o hyperthreading totalmente consumido pelo tarefas intensivas da CPU. Por outro lado, se eu iniciar tantos threads com muita CPU quanto núcleos físicos, não terei alternâncias de contexto para essas tarefas e alternâncias rápidas de contexto para as tarefas em segundo plano. Parece bom, mas as tarefas em segundo plano encontrarão processadores lógicos gratuitos e serão executadas quase imediatamente. É como se tivessem desempenho em tempo real (agradável -20).

No primeiro cenário, o hyperthreading é útil, as tarefas em segundo plano usarão alternâncias caras de contexto, porque eu estimei o hyperthreading com o processamento normal. O segundo é inaceitável, porque até 50% do meu poder da CPU é priorizado nas tarefas em segundo plano.

As tarefas "intensivas em CPU" que estou falando são servidores de autorização e mineração de dados de inteligência artificial (meu trabalho). Renderização do Blender em computadores e clusters baratos (para esboçar minha futura casa).

Além disso, isso é adivinhação.

Tenho a impressão de que é melhor, mas talvez não.

Lucas
fonte
Eu acho que meu scriptlet é um pouco mais fácil de seguir.
Paul M
9

Para kernels realmente antigos (Linux 2.6.9 ou mais), anexe o parâmetro noht ao kernel na inicialização.

Esta opção de linha de comando do kernel foi removida desde pelo menos o Linux 2.6.18 .


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

Se você estiver usando o lilo, edite o arquivo /etc/lilo.conf (e execute o lilo depois) ou se estiver usando o grub, edite o seu /boot/grub/menu.lst.

rems
fonte
Isso é funcionalmente equivalente a desativar o HT no BIOS?
ewwhite
Não sei ao certo, mas sim, espero que o noht seja equivalente a desativá-lo no BIOS.
rems
2
Este é um sistema Gentoo. Eu tentei a nohtentrada na linha de comando do grub kernel. O sistema não honrou o nohtcomando. O mesmo para RHEL. Veja: bugzilla.redhat.com/show_bug.cgi?id=440321#c9
ewwhite
11
Isso é obsoleto desde pelo menos o Linux 2.6.18 . A nohtopção do kernel foi removida. Isso é lamentável, porque o Linux permite uma solução alternativa para algumas erratas do Haswell perf-counter (BJ122, BV98, HSD29) somente se o HT estiver ativado , e isso acontece antes que o initramfs seja carregado.
Peter Cordes
9

Você pode usar o "thread_siblings_list" para cada núcleo para desativar o segundo núcleo no par HT.

O pipeline de comando a seguir é hacky, não otimizado e é feito dessa maneira, para facilitar a compreensão.

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 )

portanto, pegue todas as listas de irmãos de threads, extraia a segunda CPU para cada par, obtenha uma lista exclusiva e desative-as.

Isso faz sentido?

se eu fizer "cat / proc / cpuinfo" depois de executar o procedimento acima, o número de núcleos será reduzido pela metade.

Paul M
fonte
Esta é uma ótima resposta. Eu tive que modificá-lo da seguinte maneira para trabalhar para meus propósitos: echo 0 > /sys/devices/system/cpu/cpu$X/onlinetorna - seecho 0 | sudo tee /sys/devices/system/cpu/cpu$X/online
carbocation
5

Os kernels mais recentes fornecem um controle SMT (multithreading simultâneo).

Você pode verificar o estado do SMT com;

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

Mude o estado com

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

As opções são;

  • em
  • fora
  • forceoff

Nós testamos isso com o Linux Kernel 4.4.0

Nick Bascombe-Fox
fonte
Oi Nick e bem-vindo ao site. As informações sobre testes (e versão) são bastante valiosas.
kubanczyk
Excelente, testado no Ubuntu 16.04.6 LTS
Elder Geek
4

A resposta de Lukas é boa, mas não funciona realmente para desativar o HT, porque o ID principal não pode servir para a identificação de irmãos HT. Este script funciona:

#!/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
fonte
seu script é uma variação minha. teríamos que verificar o que acontece se você tiver várias CPUs, apenas para ter certeza.
Paul M
@PaulM Foi exatamente onde eu testei e usei para meus propósitos: sistema Haswell de 2 soquetes.
Anton
0

Eu tive que esperar até poder entrar na OIT / Drac. Os parâmetros de inicialização do kernel não funcionam nas distribuições atuais do Linux.

ewwhite
fonte
0

No pacote libsmbios-bin (Debian, Ubuntu, etc), você tem os binários isCmosTokenActive e activeCmosToken. Juntamente com a lista de tokens , você pode tentar algo como isto:

# 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

Em seguida, ative o 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

Agora, a grande questão é se você simplesmente precisa de uma reinicialização para que isso entre em vigor ou se é necessário um ciclo de energia completo. Experimente e veja como vai!

svenx
fonte
0

Com base nas informações fornecidas por Paul M aqui, eu as "script" desta maneira:

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'

Claro que não está desativando o hyper-threading no mesmo sentido que mexer com o BIOS faria , basicamente, apenas diz ao agendador de tarefas do kernel para não usar alguns núcleos, porque sabemos que eles são falsos.

O software que assumiu com base no estado /procou /syssubsistema anterior ainda pode estar executando abaixo do ideal ou até falhar devido a essa alteração no tempo de execução, portanto, sua reinicialização pode ser necessária. Por exemplo, notei que irqbalanceestava propenso a falhar nessas circunstâncias.

poige
fonte
0

Desativar HT:

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

Ativar HT:

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

Nota: Isso realmente não desabilita o HyperThreading, mas desativa os núcleos "falsos", obtendo quase o mesmo resultado.

Zibri
fonte
Gosto da maneira como você está usando tee, mas isso ainda deixa de fornecer uma resposta real à pergunta. Esses comandos se aplicam apenas a configurações específicas de hardware e podem ter efeitos indesejados em outras configurações de hardware. E uma explicação do que esses comandos fazem é completamente ausente.
kasperd
Como 0 significa desativado e 1 significa ativado, achei fácil entender que o primeiro desativa 4 núcleos (dos 8 falsos em um quandocore com o hyperthreading ativado) e o segundo os ativa novamente ... Se você possui um DUAL o núcleo desses números deve ser {3,4} em vez de {4..7} Se você usar um octacore, ele deve ser {8..15}
Zibri
0

Tópico antigo, mas tinha motivos para tentar este experimento. Primeiro, não tenho certeza de que desabilitar as CPUs (um pouco falsas) em tempo de execução é realmente equivalente à desabilitação do Hyperthreading na inicialização. Dito isso, vi um pequeno aumento de desempenho em nosso aplicativo. (Mas não o suficiente para manter.)

Utilizou o valor thread_siblings (comum a CPUs com hyperthread) como uma chave para ativar / desativar:

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 

Tente o comando sem o sudo sh final para verificar se está correto.

Preston L. Bannister
fonte