Aplicativos em execução mais lenta com vários encadeamentos

0

Eu tenho um servidor de 40 núcleos executando o Ubuntu 14.04 LTS. Eu estou usando um aplicativo com capacidade de multithreading. Acho que executar o aplicativo com números crescentes de encadeamentos melhora o tempo de execução até que eu ultrapasse um certo número, ponto no qual os tempos de execução começam a aumentar novamente. Esse número de thread está muito abaixo do número de núcleos que eu tenho. Aqui estão alguns exemplos (estes são tempos "reais"):

8 threads: 1m45.992s
16 threads: 1m7.494s
24 threads: 1m45.174s
32 threads: 3m10.819s
40 threads: 6m12.194s
80 threads: 25m22.937s

Não estou ficando sem memória (apenas 4 Gb de 128 Gb usados) e nenhuma troca está sendo usada. Nenhum outro processo com uso significativo da CPU está sendo executado durante esses testes.

Curiosamente, quando executo uma versão do mesmo aplicativo compilada da mesma fonte no OS X com os mesmos dados no meu PowerMac com 8 núcleos, obtenho uma melhoria constante no tempo de execução de até 16 threads com apenas alguns (poucos segundos) desaceleração em 32 e 64 threads, então eu não acredito que é um problema com o software de aplicação. De fato, quando eu uso outro aplicativo com capacidade multithread com função semelhante à primeira no servidor Ubuntu, vejo resultados semelhantes, embora não tão dramáticos:

16 threads: 4m4.795s
40 threads: 2m31.430s
60 threads: 3m7.007s
80 threads: 5m6.946s 

Geralmente, tenho que executar essas análises sequencialmente em centenas de conjuntos de dados, portanto, qualquer ganho em eficiência pode fazer uma grande diferença. Minha pergunta é se isso pode estar relacionado a um problema de configuração de software do sistema versus um problema com o meu hardware. Qualquer pensamento sobre onde começar a procurar resolver este problema e obter todos os benefícios de todos os meus processadores seria muito apreciado.

Obrigado.

    
por Egon 02.06.2016 / 21:38

1 resposta

2

Você provavelmente está atingindo pontos de contenção no código, como o bloqueio (por meio de futexes ou similares) em que ocorre a serialização do código e, portanto, interrompe o dimensionamento de desempenho.

Além disso, uma CPU x86 pode ter N núcleos, cada um com 2 segmentos cada, mas isso não lhe dá um desempenho de 2 x N, já que um hyperthread é executado quando determinados blocos de execução estão disponíveis. Acredito que para um único processador x86 com soquete pode-se obter até 30% de desempenho extra com um hyperthread.

Além disso, você pode estar recebendo contenção na memória, seja no cache (L1, L2 ou L3) ou até mesmo na própria memória. Então você pode estar atingindo limitações no throughput, no cache stall ou no TLB.

Com o processo N > N CPUs, você vai acabar com mais processos do que pode ser executado, por isso, o agendador tem que realizar mais trabalho em antecipar processos executáveis e isso é outra penalidade que entra em desempenho.

Você pode obter métricas de desempenho de baixo nível usando ferramentas como perf. Instale-o com:

sudo apt-get install linux-tools 

E execute seu aplicativo com perf para obter algumas medidas de desempenho:

perf stat your-program

Você pode fazer uma análise mais detalhada usando o registro de desempenho e o relatório de desempenho, por exemplo

sudo perf record your-program
sudo perf report

Como alternativa, execute seu programa e, enquanto ele estiver em execução, use perf top para obter uma visualização interativa em tempo real da atividade do sistema:

sudo perf top

Espero que isso lhe dê uma ideia de onde o gargalo está ocorrendo.

    
por Colin Ian King 03.06.2016 / 00:00