O que exatamente faz C ++ profiling (google cpu perf ferramentas) medida?
-
05-07-2019 - |
Pergunta
I tentar começar com o Google Ferramentas de Perf ao perfil algumas aplicações de uso intensivo da CPU. É um cálculo estatístico que despeja cada passo para um arquivo usando `ofstream'. Eu não sou um especialista em C ++, então eu estou tendo incomodando encontrar o gargalo. Minha primeira passagem dá resultados:
Total: 857 samples 357 41.7% 41.7% 357 41.7% _write$UNIX2003 134 15.6% 57.3% 134 15.6% _exp$fenv_access_off 109 12.7% 70.0% 276 32.2% scythe::dnorm 103 12.0% 82.0% 103 12.0% _log$fenv_access_off 58 6.8% 88.8% 58 6.8% scythe::const_matrix_forward_iterator::operator* 37 4.3% 93.1% 37 4.3% scythe::matrix_forward_iterator::operator* 15 1.8% 94.9% 47 5.5% std::transform 13 1.5% 96.4% 486 56.7% SliceStep::DoStep 10 1.2% 97.5% 10 1.2% 0x0002726c 5 0.6% 98.1% 5 0.6% 0x000271c7 5 0.6% 98.7% 5 0.6% _write$NOCANCEL$UNIX2003
Isto é surpreendente, uma vez que todo o cálculo verdadeira ocorre em SliceStep :: DoStep. O "_write $ UNIX2003" (onde posso descobrir o que é isso?) Parece estar vindo de escrever o arquivo de saída. Agora, o que me confunde é que se eu comentar todas as afirmações outfile << "text"
e pprof executar, 95% está em SliceStep::DoStep
e `_write $ UNIX2003' vai embora. No entanto a minha aplicação não acelerar, medida pelo tempo total. A coisa toda acelera menos de 1 por cento.
O que eu estou ausente?
Adicionado:
A saída pprof sem as declarações outfile <<
é:
Total: 790 samples 205 25.9% 25.9% 205 25.9% _exp$fenv_access_off 170 21.5% 47.5% 170 21.5% _log$fenv_access_off 162 20.5% 68.0% 437 55.3% scythe::dnorm 83 10.5% 78.5% 83 10.5% scythe::const_matrix_forward_iterator::operator* 70 8.9% 87.3% 70 8.9% scythe::matrix_forward_iterator::operator* 28 3.5% 90.9% 78 9.9% std::transform 26 3.3% 94.2% 26 3.3% 0x00027262 12 1.5% 95.7% 12 1.5% _write$NOCANCEL$UNIX2003 11 1.4% 97.1% 764 96.7% SliceStep::DoStep 9 1.1% 98.2% 9 1.1% 0x00027253 6 0.8% 99.0% 6 0.8% 0x000274a6
Este parece ser o que eu esperaria, só que eu não vejo nenhum aumento visível de desempenho (0,1 segundo em um segundo cálculo 10). O código é essencialmente:
ofstream outfile("out.txt");
for loop:
SliceStep::DoStep()
outfile << 'result'
outfile.close()
Update: sincronismo I usando boost :: timer, começando onde o profiler começa e termina onde termina. Não uso tópicos ou fantasia nada.
Solução
De meus comentários:
Os números que você recebe do seu digamos profiler, que o programa deve ser em torno de 40% mais rápido, sem as instruções de impressão.
O tempo de execução, no entanto, permanece quase o mesmo.
Obviamente, uma das medidas deve estar errado. Isso significa que você tem que fazer mais e melhores medidas.
Em primeiro lugar, sugiro começar com outra ferramenta fácil: o comando tempo. Este deve obter uma idéia aproximada onde seu tempo é gasto.
Não Se os resultados ainda são conclusivos você precisa de um testcase melhor:
- Use um problema maior
- Faça um aquecimento antes de medir. Fazer alguns laços e iniciar qualquer medição depois (no mesmo processo).
Tiristan: É tudo no usuário. O que estou fazendo é bastante simples, eu acho que ... Será que o fato de que o arquivo é aberto o tempo todo nada média?
Isso significa que o profiler é errado.
Impressão 100000 linhas para o console usando resultados python em algo como:
for i in xrange(100000):
print i
Para consolar:
time python print.py
[...]
real 0m2.370s
user 0m0.156s
sys 0m0.232s
Versus:
time python test.py > /dev/null
real 0m0.133s
user 0m0.116s
sys 0m0.008s
Meu ponto é: Suas medidas internas e tempo mostrar que você não ganhar nada com a desativação de saída. Google Perf Tools diz que deveria. Quem está errado?
Outras dicas
_write $ UNIX2003 é, provavelmente referindo-se ao write
chamada de sistema POSIX, que saídas para o terminal. I / O é muito lento em comparação com quase qualquer outra coisa, por isso faz sentido que seu programa está gastando muito tempo lá se você estiver escrevendo um pouco de saída.
Eu não tenho certeza por que seu programa não vai acelerar quando você remove a saída, mas eu realmente não posso dar um palpite sobre apenas as informações que você deu. Seria bom para ver algum do código, ou mesmo a saída perftools quando a instrução cout é removida.
Google perftools coleta amostras da pilha de chamadas, então o que você precisa é obter alguma visibilidade sobre aqueles.
De acordo com o documento, você pode exibir o gráfico de chamadas na declaração ou granularidade endereço. Isso deve dizer-lhe o que você precisa saber.