O mesmo hardware / software, diferença significativa no desempenho

3

Introdução

Eu tenho dois conjuntos de máquinas, conjunto A e conjunto B , aparentemente com a mesma configuração de hardware / software, mas com uma diferença significativa no desempenho. Máquinas no conjunto B são x4 mais rápidas que as máquinas no conjunto A. No entanto, se eu reinicializar uma máquina no conjunto A , ela é inexplicavelmente iniciada funcionando como esperado, como máquinas no conjunto B. Não consigo encontrar uma explicação para esse comportamento.

Configuração de hardware

  • Intel S2600KP platform
  • Processador duplo E5-2630v3 , 8 núcleos físicos, frequência base de 2,4 GHz, frequência Turbo de 3,2 GHz.
  • 8x8GB RAM DDR4 , 2133Mhz, um módulo por canal
  • Nenhuma das máquinas possui eventos SEL registrados pelo BMC que podem apontar para problemas de hardware.
  • Nenhum da máquina está acionando qualquer Exceção de Checagem de Máquina durante toda a duração dos benchmarks.

Todos os componentes de hardware são idênticos em Model / Part Number.

Configurações e software

  • A versão do BIOS e as configurações do BIOS são idênticas, por exemplo, HT está ativado, Turbo Boost está ativado. Veja o link para detalhes.

  • As máquinas estão executando a mesma 64 bits versão de Red Hat 6 com o kernel 2.6.32-504 .

O problema

As máquinas em ambos os conjuntos estão inativas, mas, seja qual for a carga que eu tente executar, obtenho resultados muito diferentes em termos de desempenho. Por uma questão de simplicidade, vou executar todos os benchmarks no núcleo 0. O resultado é reproduzível em todos os núcleos (ambos processadores).

Defina A

[root@SET_A ~]# uptime
 11:48:40 up 51 days, 19:34,  2 users,  load average: 0.00, 0.00, 0.00

[root@SET_A ~]#  taskset -c 0 sh -c 'time echo "scale=5000; a(1)*4" | bc -l > /dev/null'

real    0m43.751s
user    0m43.742s
sys     0m0.005s

Conjunto B

[root@SET_B ~]# uptime
11:50:00 up 15 days, 19:43,  1 user,  load average: 0.00, 0.00, 0.00

[root@SET_B ~]# taskset -c 0 sh -c 'time echo "scale=5000; a(1)*4" | bc -l > /dev/null'

real    0m18.648s
user    0m18.646s
sys     0m0.004s

Observações

turbostatos reporta o núcleo 0 como estando no estado C0 Consumption e no estado P0 Performance com a Freqüência Turbo habilitada para toda a duração do benchmark.

Defina A

[root@SET_A ~]# turbostat  -i 5
pk cor CPU    %c0  GHz  TSC SMI    %c1    %c3    %c6    %c7 CTMP PTMP   %pc2   %pc3   %pc6   %pc7  Pkg_W RAM_W PKG_% RAM_%
             3.15 3.18 2.39   0   3.26   0.00  93.59   0.00   40   46  49.77   0.00   0.00   0.00  46.45 22.41  0.00  0.00
 0   0   0  99.99 3.19 2.39   0   0.01   0.00   0.00   0.00   40   46   0.00   0.00   0.00   0.00  29.29 12.75  0.00  0.00

Conjunto B

[root@SET_B ~]# turbostat  -i 5
pk cor CPU    %c0  GHz  TSC SMI    %c1    %c3    %c6    %c7 CTMP PTMP   %pc2   %pc3   %pc6   %pc7  Pkg_W RAM_W PKG_% RAM_%
             3.14 3.18 2.39   0   3.27   0.00  93.59   0.00   38   40  49.81   0.00   0.00   0.00  46.12 21.49  0.00  0.00
 0   0   0  99.99 3.19 2.39   0   0.01   0.00   0.00   0.00   38   40   0.00   0.00   0.00   0.00  32.27 13.51  0.00  0.00

Referência de referência simplificada

Para simplificar o benchmark o máximo possível (sem FP, com menos acessos à memória possível), escrevi o seguinte código de 32 bits.

.text
.global _start

_start:
      movl    $0x0, %ecx
oloop:
      cmp $0x2, %ecx
      je end
      inc %ecx
      movl    $0xFFFFFFFF,%eax
      movl    $0x0, %ebx
loop: cmp     %eax, %ebx
      je      oloop
      inc     %ebx
      jmp     loop

end:
      mov $1, %eax
      int $0x80
.data
value:
        .long 0

Ele simplesmente incrementa um registro de 0 a 0xFFFFFFFF duas vezes, nada mais.

Defina A

[root@SET_A ~]# md5sum simple.out 
30fb3a645a8a0088ff303cf34cadea37  simple.out
[root@SET_A ~]# time taskset -c 0 ./simple.out

real    0m10.801s
user    0m10.804s
sys     0m0.001s

Conjunto B

[root@SET_B ~]# md5sum simple.out 
30fb3a645a8a0088ff303cf34cadea37  simple.out
[root@SET_B ~]# time taskset -c 0 ./simple.out

real    0m2.722s
user    0m2.724s
sys     0m0.000s

x4 diferença para incrementar um registro.

Mais observações com o benchmark simplificado

Durante o benchmark, o número de interrupções é o mesmo em ambas as máquinas, ~1100 intr/s (reportado com mpstat). Estas são principalmente Interrupções do Temporizador Local em CPU0 , então basicamente não há diferença na fonte de interrupção.

Defina A

[root@SET_A ~]# mpstat -P ALL -I SUM 1
01:00:35 PM  CPU    intr/s
01:00:36 PM  all   1117.00

Conjunto B

[root@SET_B ~]# mpstat -P ALL -I SUM 1
01:04:50 PM  CPU    intr/s
01:04:51 PM  all   1112.00

Para P-States e C-States tem o mesmo que acima.

análise perf

Defina A

 Performance counter stats for 'taskset -c 0 ./simple.out':

        41,383,515 instructions:k            #    0.00  insns per cycle         [71.42%]
    34,360,528,207 instructions:u            #    1.00  insns per cycle         [71.42%]
            63,675 cache-references                                             [71.42%]
             6,365 cache-misses              #    9.996 % of all cache refs     [71.43%]
    34,439,207,904 cycles                    #    0.000 GHz                     [71.44%]
    34,400,748,829 instructions              #    1.00  insns per cycle         [71.44%]
    17,186,890,732 branches                                                     [71.44%]
               143 page-faults                                                 
                 0 migrations                                                  
             1,117 context-switches                                            

      10.905973410 seconds time elapsed

Conjunto B

 Performance counter stats for 'taskset -c 0 ./simple.out':

        11,112,919 instructions:k            #    0.00  insns per cycle         [71.41%]
    34,351,189,050 instructions:u            #    3.99  insns per cycle         [71.44%]
            32,765 cache-references                                             [71.46%]
             3,266 cache-misses              #    9.968 % of all cache refs     [71.47%]
     8,600,461,054 cycles                    #    0.000 GHz                     [71.46%]
    34,378,806,261 instructions              #    4.00  insns per cycle         [71.41%]
    17,192,017,836 branches                                                     [71.37%]
               143 faults                                                      
                 2 migrations                                                  
               281 context-switches                                            

       2.740606064 seconds time elapsed

Observações

  • O número de instruções de espaço do kernel é diferente devido aos caminhos de controle que levam a uma reprogramação. Não há chamadas do sistema envolvidas além de um% final% co_de. Claramente, o número de opções de contexto é maior para o Conjunto A.
  • Há também uma pequena diferença nas instruções de espaço do usuário ( sys_exit ). Isso pode ser causado pela mesma razão acima? Instruções que levam a um reagendamento que são contabilizadas como espaço do usuário. Ou instruções em contexto de interrupção?
  • O número total de instruções para o Conjunto A é ~10M maior, mas o número de 0.06% é o dobro. Isso é esperado? Uma verificação rápida na configuração do cache leva ao mesmo resultado. O cache está habilitado corretamente ( L3 cache references , CD é 0) e a configuração CR0: 0x80050033 é idêntica.
  • Provavelmente, o valor mais interessante é o instr por ciclo. 1 inst por ciclo no Conjunto A, 4 inst por ciclo no Conjunto B .

Perguntas finais

  • Existe um motivo óbvio que pode explicar essa diferença no desempenho?

  • Por que as máquinas no Conjunto A estão sendo executadas a 1 instr por ciclo, enquanto as máquinas no Conjunto B estão sendo executadas a 4 instr por ciclo, considerando o fato de que a configuração de hardware / software é idêntica?

  • Por que reinicializar uma máquina parece corrigir esse comportamento? Como explicado na introdução, se eu reinicializar uma máquina no Conjunto A, ela será executada conforme o esperado.

A causa aqui é ou muito trivial que eu senti falta ou muito complexa que realmente não pode ser explicada. Espero que seja o primeiro, qualquer sugestão / ajuda / sugestão seja apreciada.

    
por Marco Guerri 04.04.2015 / 14:09

1 resposta

1

É claro que seria ótimo se alguém pudesse dar uma resposta que permita corrigir seu problema imediatamente. Mas temo que não haja uma resposta óbvia. Mas pode haver algumas instruções para atacar o problema que ainda não foi tentado:

  1. Sob a hipótese de que algumas de suas máquinas mostram o comportamento e outras nunca, é possível concluir problemas sutis de hardware (esporádicos, indetectáveis por meio de diagnósticos do sistema). A hipótese contrária seria que isso pode acontecer com qualquer uma das suas máquinas.

    • Etapa 1: certifique-se de que todas as peças das máquinas possam ser rastreadas no que está por vir.
    • Etapa 2: escolha algumas das máquinas supostamente "boas" e execute-as com os discos rígidos de algumas máquinas "ruins" e veja se o efeito é exibido.
    • Etapa 3: etapa de controle. Execute máquinas "ruins" com os discos rígidos de "boas" e veja se o problema é exibido.

Se o efeito também aparecer em máquinas "boas", deve haver diferenças sutis na instalação (conteúdo HD) ou o disco rígido é o problema.

Se o efeito nunca aparecer em máquinas "boas", a teoria do "problema de hardware sutil" é confirmada.

  1. Procure pelas diferenças que "real e claramente não podem causar isso - nunca!". Há uma história sobre o engenheiro da GM que foi enviado para investigar por que um carro da GM não liga quando um dono desse carro comprou sorvete de morango, mas nunca quando ele comprou baunilha em uma loja ... No seu caso, olhe para onde boas e más máquinas são colocadas. Mais ventilação da sala, menos? Mais perto de algumas janelas e luz solar direta? Mais perto / mais distante de algumas instalações elétricas (climatização, ...)? Redes de fornecimento de energia diferentes do edifício? Mais coisas conectadas a alguns caminhos de controle de energia / USV? ... Pode não parecer razoável à primeira vista o que eu sugiro aqui, mas ei - o seu problema é bastante esporádico, certo? (50 dias de atividade e suas máquinas "turn" durante esse período ..).

Coloque as boas máquinas nos locais físicos das ruins e veja o que acontece.

  1. Alguns de meus dias de trabalho mais dolorosos como engenheiro de software incorporado vieram de pessoas trocando "equipamentos idênticos" em minha mesa de trabalho ... e eu gastando meio dia - meia semana tentando descobrir por que minhas coisas não estão funcionando como fazia antes de eu ter partido para a noite ... Às vezes até as menores revisões de algum componente (ou versão de software / configuração nele) podem ter alguns efeitos observáveis. Em alguns dos meus casos ao longo dessa linha, nem mesmo o fabricante estava ciente dessas mudanças "sem importância" - às vezes apenas em alguns layouts de PCB ou uma mudança do fornecedor de capacitores para uma segunda fonte ...

O passo 1 deve ajudar a encontrar diferenças sutis, identificando quais de suas máquinas funcionam e quais não funcionam. O passo 3 é sobre encontrar a explicação.

  1. Tente avaliar o "MTBF" e analise-o para um padrão. Como você pode ver claramente quando uma máquina começa a desacelerar, você pode medir o tempo médio que leva a máquina para ir devagar. Então, pode ser perspicaz se máquinas diferentes tiverem tempos diferentes para falhar, se os horários estiverem agrupados em torno de um valor ou se não houver nenhum padrão (totalmente aleatório quando isso acontecer) ...
por 04.04.2015 / 19:01