2014-10-24 22 views
7

Si consideri il seguente codice:Perché sqrt in ambito globale è molto più lento di std :: sqrt in MinGW?

#include <cmath> 
#include <cstdio> 

const int COUNT = 100000000; 

int main() 
{ 
    double sum = 0; 
    for (int i = 1; i <= COUNT; ++i) 
     sum += sqrt(i); 
    printf("%f\n", sum); 
    return 0; 
} 

Corre 5.5s sul mio computer. Tuttavia, se cambio sqrt in std::sqrt, verrà eseguito solo 0,7 s.

so che se uso sqrt, sto usando la funzione di libreria C, e se uso std::sqrt, sto usando quello in <cmath>.

Ma <cmath> non definisce uno per int, e se cambio il tipo di i in double, che verrà eseguito per la parità di velocità. Quindi il compilatore non sta ottimizzando per int. Questo sembra accadere solo a sqrt in Windows.

Quindi perché è std::sqrt molto più veloce di sqrt, ma non altre funzioni? E perché in Linux non lo sono?

+2

Flag di ottimizzazione? – Columbo

+0

Qual è la versione del compilatore e questo è MinGW (.org) o MinGW-w64? – rubenvb

+8

C++ 11 aggiunge il supporto per argomenti interi a 'std: sqrt': http://en.cppreference.com/w/cpp/numeric/math/sqrt –

risposta

6

Questa è la situazione tipica in cui l'interruttore -fdump-tree-* può dare alcune indicazioni su ciò che sta accadendo:

g++ -fdump-tree-optimized example1.cc 

e si ottiene il file example1.cc.165t.optimized. Da qualche parte dentro:

<bb 3>: 
_5 = (double) i_2; 
_6 = sqrt (_5); 
sum_7 = sum_1 + _6; 
i_8 = i_2 + 1; 

Il compilatore (gcc v4.8.3) sta facendo i conti con double s.

Sostituzione sqrt con std::sqrt quello che si ottiene è:

<bb 3>: 
_5 = std::sqrt<int> (i_2); 
sum_6 = sum_1 + _5; 
i_7 = i_2 + 1; 

Ora si usa un sovraccarico di sqrt diverso per gli interi (i_2 è int e sum_6 è double).

Come dice Mike Seymour in un comment, GCC utilizza il nuovo overload indipendentemente dal fatto che si specifichi C++ 11.

In ogni caso sotto Linux non c'è una differenza di prestazioni sensata tra le due implementazioni.

In Windows (MinGW) questo è diverso dal sqrt(double) calls into msvcrt.