Por que ter mais núcleos mais rápidos torna meu software multithreaded mais lento?

2

Estou com um comportamento bizarro no dimensionamento de um aplicativo C ++ multiprocesso / multithread. O aplicativo contém 10 processos separados, comunicando-se através de Sockets de Domínio Unix e cada um tendo ~ 100 threads fazendo IO e vários processos nesse IO. O sistema é OLTP e o tempo do processo de transação é crítico. O IPC IO é baseado na serialização do boost usando sockets de domínio zmq over unix (ele é rápido o suficiente em todos os benchmarks em nosso servidor local, dois xeons antigos com 24 núcleos). Agora, observamos desempenho insanamente baixo em sistemas com maior número de núcleos!

1x Intel® Xeon® X5650 - virtual - 6 núcleos - o TPS é ~ 150 (esperado)
1x Intel® Xeon® E5-4669 v4 - dedicado - 32 núcleos - TPS é ~ 700 (esperado)
2x Intel® Xeon® E5-2699 v4 - dedicado - 88 núcleos - TPS é ~ 90 (deveria ter sido ~ 2000)

A execução de vários benchmarks no terceiro servidor mostra a potência perfeitamente normal do processador. largura de banda de memória e latência parecem normais.

htop mostra tempos muito altos no kernel (a parte vermelha). Então, nosso primeiro palpite foi que algumas chamadas de sistema demoram muito tempo para serem realizadas, ou fizemos algo errado no código multi-threaded. (Veja a figura abaixo) perf top reporta uma rotina systemcall / kernel específica ( native_queued_spin_lock_slowpath ) para levar cerca de 40% do tempo do kernel (veja abaixo Image) que não temos idéia do que faz.

No entanto, outra observação muito estranha é esta:

diminuir a contagem de núcleos atribuídos a processos, faz com que o sistema utilize melhor os núcleos (mais partes verdes, maior uso de cpu) e faz todo o software (todos os 10 processos) rodar muito mais rápido (TPS é ~ 400).

Então, quando executamos os processos com taskset -cp 0-8 service , atingimos ~ 400 TPS.

Como você pode explicar por que diminuir o número de CPUs atribuídas de 88 para 8 faz com que o sistema funcione 5 vezes mais rápido, ainda que 1/4 do desempenho esperado em 88 núcleos?

Informação adicional:
SO: Debian 9.0 amd64
Kernel: 4.9.0

    
por sorush-r 05.07.2018 / 10:26

3 respostas

3

Claro que parece um efeito NUMA quando vários sockets degradam drasticamente o desempenho.

perf é muito útil. Já no relatório perf, você pode ver native_queued_spin_lock_slowpath tendo 35%, o que parece ser uma grande quantidade de sobrecarga para seu código de simultaneidade. A parte complicada é visualizar o que está chamando, se você não conhece muito bem o código de simultaneidade.

Eu recomendaria a criação de gráficos de chama a partir da amostragem de CPU do sistema . Início rápido:

git clone https://github.com/brendangregg/FlameGraph  # or download it from github
cd FlameGraph
perf record -F 99 -a -g -- sleep 60
perf script | ./stackcollapse-perf.pl > out.perf-folded
./flamegraph.pl out.perf-folded > perf-kernel.svg

No gráfico resultante, procure os "platôs" mais altos. Quais indicam funções com o tempo mais exclusivo.

Estou ansioso para saber quando o pacote bpfcc-tools está no Debian estável, ele permitirá a coleta dessas pilhas "dobradas" diretamente com menos sobrecarga.

O que você faz com isso depende do que você encontra. Saiba qual seção crítica está sendo protegida por um bloqueio. Compare a pesquisa existente em sincronização escalável em hardware moderno. Por exemplo, uma apresentação do Kit de Concorrência observa que diferentes implementações de spinlock têm propriedades diferentes .

    
por 06.07.2018 / 14:53
2

Eu diria que isso é um "problema" de hardware. Você sobrecarrega o subsistema IO e é desses reis que mais paralelismo o torna mais lento (como discos).

As principais indicações são:

  • ~ 100 encadeamentos para IO
  • Você não diz nada sobre IO. Isso é típico de uma área inexperiente pessoas ignoram e nunca falam sobre. Típico para bancos de dados "ah, eu tenho muito, mas eu não digo que eu corro de um disco lento de grande capacidade, porque eu estou lento".
por 05.07.2018 / 10:56
1

Como os fabricantes de software são mais preguiçosos para fazer otimizações de vários núcleos.

Os designers de software raramente projetam software que possa usar os recursos completos de hardware de um sistema. Alguns softwares muito bem escritos podem ser considerados bons é o software de mineração de moedas, já que muitos deles são capazes de usar o poder de processamento da placa de vídeo próximo ao seu nível máximo (ao contrário dos jogos, que nunca chegam perto de usar o verdadeiro poder de processamento de uma GPU).

Uma coisa semelhante é válida para muitos softwares hoje em dia. Eles nunca se incomodam em fazer otimizações de múltiplos núcleos, portanto, o desempenho será melhor quando o software for executado com menos núcleos configurados em velocidade mais alta em comparação com núcleos de velocidade mais baixa. No caso de núcleos mais e mais rápidos, isso não pode ser uma vantagem o tempo todo pelo mesmo motivo: código mal escrito. O programa tentará dividir suas sub-tarefas em muitos núcleos e isso realmente atrasará o processamento geral.

    
por 05.07.2018 / 10:38