Qual é a maneira mais rápida de encontrar o máximo de dois carros alegóricos em C ++?

votos
1

Qual é a maneira mais rápida de encontrar o máximo de dois carros alegóricos:

a)

y = std::max(x1, x2);

b)

if (x1 > x2)
    y = x1;
else
    y = x2;

c)

y = x1 > x2 ? x1 : x2;

obrigado

Publicado 19/05/2009 em 14:40
fonte usuário
Em outras línguas...                            


13 respostas

votos
24

Aqui está uma pergunta diferente

Porque você acha que uma pequena otimização, tais importa no contexto maior do seu programa?

Acho que é altamente improvável que um micro-otimização como este terá um impacto perceptível no seu programa. Você nunca deveria micro-otimizar assim a menos que um profiler mostrou especificamente que isso seja um problema.

EDIT Adicionando alguns esclarecimentos enterrado nos comentários

A razão não há grande resposta a esta pergunta é que o desempenho desse código é altamente dependente ...

  1. A maneira em que ele é usado em seu programa
  2. O compilador específico que você está usando
  3. As opções de otimização passado para o compilador
  4. A arquitetura especial que você está executando o código em
  5. Muitas outras coisas muito pequenas que não foram incluídos na pergunta

Mesmo se toda esta informação foi incluída, as nossas respostas seria palpites na melhor das hipóteses. A única maneira de responder a esta pergunta é sacar um profiler e descobrir o que é mais rápido.

No entanto, este é quase certamente não vale o esforço. Micro-otimização de um pequeno pedaço de seu programa como quase certamente não vai acrescentar quaisquer benefícios preformance perceptíveis ao seu código. Em geral, é uma péssima idéia para otimizar código como este a menos que o profiler especificamente lhe diz que é um problema. Caso contrário, você vai gastar muito tempo otimizando algo para nenhum benefício percievable.

Sim, existem casos em que tal otimização poderiam ser importantes. Mas isso seria apenas em muito especiais circunstâncias em que o código era uma parte de um loop muito apertado altamente chamado. No entanto, a única maneira de identificar esse código é usar um profiler.

Respondeu 19/05/2009 em 14:44
fonte usuário

votos
4

O3 Dual core Macbook Pro de 2,4 GHz

std :: max (x1, x2) Time: 4,19488 RMAAx de: 4,19613 se Time: 4,18775? Time: 4,18831

std :: max (x1, x2) Time: 4,1836 RMAAx de: 4,18274 se Time: 4,18603? Time: 4,18857

std :: max (x1, x2) Time: 4,18714 RMAAx de: 4,18759 se Time: 4,19752? Time: 4,19797

std :: max (x1, x2) Time: 4,1926 RMAAx de: 4,19293 se Time: 4,19334? Time: 4,19626

std :: max (x1, x2) Time: 4,18963 RMAAx de: 4,19628 se Time: 4,19253? Time: 4,19107

#include <iostream>

using namespace std;

int main (int argc, char * const argv[]) {

    uint64_t iterations = 10000000000;
    float x1 = 3455.232;
    float x2 = 7456.856;
    float y = 0;

    for (int count = 0; count < 5; ++count)
    {       
        clock_t begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            y = std::max(x1, x2);
        }

        std::cout << "std::max(x1, x2) Time: " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;


        begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            y = x1;
            if (y < x2)
                y = x2;
        }

        std::cout << "RMAAx's : " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;


        begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            if (x1 > x2)
                y = x1;
            else
                y = x2;
        }

        std::cout << "if Time: " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;


        begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            y = x1 > x2 ? x1 : x2;
        }

        std::cout << "? Time: " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;
    }

    return 0;
}
Respondeu 19/05/2009 em 16:03
fonte usuário

votos
4

Você pode verificá-la a si mesmo em seu sistema.

Eu fiz isso para você no gcc - redhat. Os resultados sobre o meu sistema, para 100.000 execuções com x1 = 432.943,5 e x2 = 434.232,9

a) ~ 1200 SU b) ~ 600 SU c) ~ 600 SU

EDIT: Com -O2 otimização eu tenho os mesmos resultados em todos os 3 casos: ~ 110 SU.

Claro, o resultado real depende de muitos fatores em seu problema e sistema específico.

Respondeu 19/05/2009 em 14:45
fonte usuário

votos
4

É compilador específico, mas eu suspeito que o resultado é o mesmo. Ter um olhar para a saída de montagem do compilador.

Respondeu 19/05/2009 em 14:45
fonte usuário

votos
3

Intel x 86 tem instruções (FCOMI / FCOMIP / FUCOMI / FUCOMIP) que fornecem rápida comparação de valores de ponto flutuante. Seu processador pode ter tais instruções, também. O truque é descobrir o que C ++ para escrever, a fim de maximizar as chances de seu compilador usando essas instruções em vez de fazer algo mais lento, mas mais genérico.

A sugestão otimista é usar std :: max (float, float) na esperança de que alguém ignorado aqueles que zombam "microbenchmark" e "otimização prematura" e tem feito a pesquisa necessária para fornecer uma especialização para std :: max (float , float) que irá utilizar instruções especializadas do seu hardware.

Respondeu 19/05/2009 em 20:24
fonte usuário

votos
2

Primeiro, como já foi dito, o perfil de seu código e fazer absoluta certeza de que isso é algo que vale a pena otimizar. Se for, continue a ler: você pode fazê-lo sem ramificação. Veja Abaixo FCMP: Condicional movimentos para sem agências matemática para obter mais detalhes.

Respondeu 19/05/2009 em 16:44
fonte usuário

votos
2

Referência-los e descobrir.

Respondeu 19/05/2009 em 14:46
fonte usuário

votos
2

A única maneira de realmente saber é medi-los. Eles podem variar de compilador para compilador ou plataforma para plataforma.

Executar um loop de cada um para 100.000 ou 500.000 iterações e comparar os tempos de execução total.

Respondeu 19/05/2009 em 14:45
fonte usuário

votos
2

Mesma observação como de costume, quando se trata de "mais rápida". Você quis medir o tempo de execução de vocês cálculo de valor máximo, relatou para o resto do tempo de execução do processo? Será que esta decisão "otimização" têm um impacto significativo sobre o tempo de execução do seu aplicativo?

Tenho 99% de certeza que a diferença entre suas propostas não vale a pena considerar.

Respondeu 19/05/2009 em 14:45
fonte usuário

votos
2

B e C se compilar o mesmo, pelo menos em teoria. I escolher aqueles porque a menos que std::maxé não uma chamada de função (por exemplo, uma macro), esses seriam os mais rápidos.

Editar Aparentemente, std::maxé uma chamada de função de modelo como seu formulário C. http://www.cplusplus.com/reference/algorithm/max/

Respondeu 19/05/2009 em 14:42
fonte usuário

votos
1

E desta forma pode ser melhor?

y = x1;
if (y < x2)
    y = x2;

Removendo a condição mais pode ser melhor interpretado pelo compilador.

Edit1: Se o benchmarking não se esqueça de fazer metade o teste com maior x1 então x2 e a outra metade com x2 maior. Caso contrário, os resultados não refletem casos reais.

Edit2: Microoptimazions são de alguma forma útil se você trabalha em sistemas embarcados com 1 ou 2 k de memória. E também, seu um problema interessante para pensar por que os horários são diferentes em cada caso.

Respondeu 19/05/2009 em 14:48
fonte usuário

votos
0

Na presença de um otimizador decente, eles são equivalentes.

Respondeu 19/05/2009 em 22:51
fonte usuário

votos
0

É comum #define, quer b ou c como uma macro, e usar isso em todo o código. Note que isto só funciona na maioria dos casos, e vai morrer se você passar em um x ou y argumento modificado por um operador ou função chamada não-idempotent com efeitos colaterais. Por exemplo:

#define MAX(x,y) (((x) < (y)) ? (y) : (x))
...
MAX(i++, ++j); //won't work properly, the ++'s will get executed twice.
MAX(changeKSomehow(k), changeLSomehow(L)); //won't work, the functions will get called twice.

Acontece que std :: max, pelo menos para GNU libstdc ++, é implementado quase idêntica, e usa a inlinedica. O compilador deve ser capaz de tomar a dica quando for o caso (quando o operador <leva algumas instruções suficientes para não causar uma enorme quantidade de I $ pressão se embutido).

Respondeu 19/05/2009 em 14:48
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more