Quantas CPUs devem ser utilizadas com o Hyperthreading?

22

Digamos que eu tenha uma CPU de servidor com 18 núcleos, com hyperthreading ativado, o que significa que eu posso ver 36 cpus no htop.

Para utilizar totalmente a CPU e não afetar o desempenho de thread único, devo ter como objetivo que todos os 36 "núcleos" sejam executados a 100%, e os núcleos HT farão menos trabalho e ainda reportarão 100%, ou isso significaria o os núcleos "completos" já estão sendo interrompidos pela tarefa em seu "núcleo HT" e, portanto, realizando menos trabalhos de thread único?

Estou ciente de que existem muitas variáveis ​​que afetam o desempenho do HT, só quero saber o que os medidores de CPU significam ao lidar com o HT.

Tassadar
fonte
6
O Hyperthreading realmente não oferece o dobro da CPU. Pense nisso mais como uma CPU lê em dois programas e, sempre que um programa estiver prestes a fazer algo que levará vários ciclos, ou quando não estiver usando todos os recursos (somadores, multiplicadores, carregadores etc.), ele mudará para o outro programa para que possa usá-los. Portanto, ver 100% de todos os threads requer uma feliz coincidência de programas compatíveis executados em um núcleo.
simpleuser
4
Devido a esse design, o hyperthreading funciona bem com cargas de trabalho mistas. Por exemplo, um hipervisor em que todas as VMs executam serviços diferentes. Nesse tipo de cenário, provavelmente nem é necessário testar. Para cargas de trabalho mais homogêneas, geralmente é necessário testar.
Michael Hampton

Respostas:

14

Se é permitido que o segundo núcleo virtual contribua quando o primeiro seria bloqueado, é melhor que não , então você realiza (pelo menos) um pouco de trabalho extra.

A questão é: quando ter dois threads diferentes faz com que um funcione pior? A previsão do ramo e as dependências entre as instruções não serão alteradas. Aguardando acesso à memória agora ... os dois threads competem pelo acesso à memória, tanto na utilização do cache quanto na largura de banda.

Se você tem algumas CPUs executando com HT e outras não, isso também significa que você atribuirá threads específicos a um tipo ou outro? Acho que não: seus programas executam seus threads em núcleos virtuais aleatórios. Então, como a divisão da configuração ajuda? Como cada CPU possui seu próprio cache, o único efeito é devido à largura de banda da memória e ao ônus da coerência do cache.

Em geral, você chega a um ponto em que ter algo mais a fazer pode ser mais caro do que deixar algumas unidades de execução da CPU ociosas. Isso não depende diretamente do número de threads, mas do que os threads estão fazendo e da arquitetura detalhada da memória e das nuances de desempenho dos vários componentes.

Não existe uma resposta simples. Mesmo com um programa específico em mente, a máquina pode ser diferente da das pessoas que relatam suas próprias experiências.

Você deve tentar e medir o que é mais rápido, com esse trabalho específico nessa máquina exata. E mesmo assim, isso pode mudar com as atualizações de software e a mudança de uso ao longo do tempo.

Dê uma olhada no volume 3 da magnum opus da Anger . Se você observar atentamente algum processador específico, poderá encontrar recursos limitantes no pipeline profundo de muitas etapas necessárias para executar o código. Você precisa encontrar um caso em que o comprometimento excessivo faça com que ele seja executado mais lentamente, em vez de não levar mais trabalho. Em geral, isso significaria algum tipo de cache; e onde o recurso é compartilhado entre threads.


O que significa o medidor de CPU: ele relata o tempo todo que não é gasto executando o encadeamento ocioso. Os dois encadeamentos lógicos atribuídos a um núcleo não ficarão ociosos, mesmo que o trabalho real realizado em um deles possa ser pequeno. O tempo gasto com o pipeline travou por alguns ciclos até que os resultados estejam prontos, a memória é buscada, as operações atômicas são protegidas etc. etc. também não fazem com que o encadeamento seja arquivado como "não pronto", para que não fique ocioso, e o tempo ainda aparece como em uso. Esperar na RAM não será exibido como ocioso. Somente algo como E / S fará com que o encadeamento bloqueie e pare o tempo de carregamento. Um mutex de sistema operacional em geral fará isso, mas com o surgimento de sistemas multicore, isso não é mais certo, pois um "spinlock" não fará com que o encadeamento volte à prateleira.

Portanto, um medidor de CPU de 100% não significa que tudo corre bem, se a CPU geralmente fica presa à espera de memória. Um número menor de núcleos lógicos mostrando 90% poderia muito bem estar realizando mais trabalho, pois termina o processamento de números e agora está aguardando no disco.

Portanto, não se preocupe com o medidor de CPU. Olhe para o progresso real feito, única .

JDługosz
fonte
23

Os medidores de CPU são muito ruins para dizer a você quanto mais desempenho você pode extrair de suas CPUs com hyperthread. Para isso, você deve executar seus próprios benchmarks com várias taxas de assinatura física por núcleo. Existem algumas cargas de trabalho que funcionam melhor com o HT completamente desativado, portanto inclua esse caso também em seus testes. Pode ser 1: 2 (36 trabalhadores paralelos), ou 1: 1,5, ou até 1: 2,5! Depende da sua carga de trabalho.

Mais detalhadamente, o HT é implementado no silício de maneira a reduzir o tempo que o processador passa ocioso quando um contexto precisa ser alternado ou uma predição de ramificação falha. Isso facilita atingir 100% de uso da unidade de execução do que com truques puros do sistema operacional. O HT evoluiu desde sua introdução, e há mais paralelismo nos chips modernos do que aqueles que estávamos usando há 10 anos.

Existem dois perfis de execução que afetarão onde está o ponto ideal de excesso de assinatura:

  • Longa duração de execução . Se seus funcionários executarem minutos ou horas antes da reciclagem, como grandes trabalhos de renderização ou modelagem de ambiente, você obterá um desempenho de núcleo único mais eficiente por trabalhador. Isso diminuirá sua proporção.
  • Curta duração de execução . Se seus funcionários alternarem em segundos ou pequenos minutos, como threads de aplicativos da Web, a sobrecarga envolvida na ativação de um novo processo significa que sua proporção será maior.
sysadmin1138
fonte
Minutos pequenos? Você quer dizer alguns minutos?
Ismael Miguel
Bastante. 1 a 5 ou mais. A 120 segundos por trabalhador com 18 trabalhadores, você está entregando um novo a cada sete segundos. Muito disso se resume ao cache da localidade.
sysadmin1138
1
Você não entendeu .. Você está dizendo "pequenos minutos" no seu segundo ponto. Os minutos sempre têm o mesmo "tamanho", que é de 60 segundos. Às vezes 61 segundos.
Ismael Miguel
4

Você deve ver todos os 36 núcleos em execução a 100% - supondo que o software possa fazer isso (o que não é trivial - a programação pode ser complicada com muitos núcleos, portanto, quedas abaixo de 100% são aceitáveis).

Obviamente, quando você "divide" um minério com hyperthreading, o significado desses 200% não é "2x100% - no trabalho realizado. Mas isso é invisível a qualquer medição realizada (proveniente da utilização da CPU e sem nenhum conceito de trabalho realizado). A quantidade de trabalho realizado depende do que é o trabalho - em algum lugar acima de 1,5 x o trabalho sem hiper-segmentação é esperado na maioria das vezes.

TomTom
fonte
3

A maneira como o hyperthreading é implementado varia de acordo com o uarch específico da CPU. De Nehalem a Skylake, a Intel reduziu significativamente as partes compartilhadas de proporção fixa (ou seja: 50/50) do oleoduto, indo para estruturas compartilhadas dinamicamente.

De qualquer forma, em termos gerais, ativar o HT levou a uma execução de thread único ligeiramente mais lenta, mas devido à maneira como o agendador do Linux funciona, isso só acontece quando o número ou o thread em execução é maior que o número de núcleos físicos. Como em tais situações (quando threads> núcleos), você normalmente valoriza a taxa de transferência total da máxima importância, o hyperthreading permanece uma vitória líquida.

Como isso é possível? O ponto principal a entender é que a CPU não apresenta os núcleos físicos e os virtuais como núcleos iguais, mas expõe os últimos de uma maneira que o planejador do Linux pode evitar agendá-los se houver outros núcleos físicos disponíveis. Em outras palavras, ele primeiro usa todos os núcleos físicos, depois começa a usar o virtual.

Isso significa que, geralmente, o HyperThreading é um recurso muito valioso (outros processadores, como o Power8, usa técnicas SMT ainda mais profundas) e que, para maximizar o rendimento, você deve habilitá-lo, carregando a CPU com pelo menos um encadeamento por núcleo virtual ou físico. Para um exemplo prático, para extrair o desempenho completo de uma CPU de 18 núcleos, você deve usar pelo menos 36 threads.

Existem duas exceções:

  1. se tudo o que você deseja é minimizar a latência de um conjunto limitado de threads (em que threads <núcleos físicos), você pode desativar o HT
  2. CPU muito antiga (Pentium4 e, de maneira bem menor, Nehalem) possui regras de partição inflexíveis que forçam a CPU a dividir muitos recursos importantes na proporção 50/50, independentemente do status / carregamento do segundo encadeamento. Nesse caso, você teve que fazer um benchmark do seu caso de uso para garantir que a taxa de transferência adicionada valha o desempenho significativamente menor do encadeamento único.
shodanshok
fonte