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.

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top