Le code suivant compilé avec clang
est de près de 60 fois plus rapide que celui compilé avecgcc
avec les mêmes options de compilation (soit -O2
ou -O3
):
#include <iostream>
#include <math.h>
#include <chrono>
#include <limits>
long double func(int num)
{
long double i=0;
long double k=0.7;
for(int t=1; t<num; t++){
for(int n=1; n<16; n++){
i += pow(k,n);
}
}
return i;
}
int main()
{
volatile auto num = 3000000; // avoid constant folding
std::chrono::time_point<std::chrono::system_clock> start, end;
start = std::chrono::system_clock::now();
auto i = func(num);
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed = end-start;
std::cout.precision(std::numeric_limits<long double>::max_digits10);
std::cout << "Result " << i << std::endl;
std::cout << "Elapsed time is " << elapsed.count() << std::endl;
return 0;
}
J'ai testé avec trois gcc
versions 4.8.4/4.9.2/5.2.1
et deux clang
versions 3.5.1/3.6.1
et voici les horaires sur ma machine (pour gcc 5.2.1
et clang 3.6.1
):
Timing -O3
:
gcc: 2.41888s
clang: 0.0396217s
Timing -O2
:
gcc: 2.41024s
clang: 0.0395114s
Timing -O1
:
gcc: 2.41766s
clang: 2.43113s
Il semble donc que, gcc
ne permet pas d'optimiser cette fonction à tous, même à des niveaux d'optimisation. L'assemblée de la sortie de l' clang
est presque autour de 100 lignes de plus de gcc
et je ne pense pas qu'il est nécessaire de le poster ici, tout ce que je peux dire, c'est que, en gcc
assemblée de sortie, il est un appel à l' pow
qui n'apparaît pas dans clang
de l'assemblée, sans doute parce qu' clang
il optimise pour un tas de intrinsèques des appels.
Puisque les résultats sont identiques (i.e. i = 6966764.74717416727754
), la question est:
- Pourquoi peut -
gcc
pas d'optimiser cette fonction lors de l'clang
peut? - Modifier la valeur de
k
de1.0
etgcc
devient aussi rapide, est-il une arithmétique à virgule flottante question qu'gcc
ne peut de by-pass?
J'ai essayé d' static_cast
ing et activé les mises en garde pour voir si il n'y avait aucun problème avec les conversions implicites, mais pas vraiment.
Mise à jour: Pour être complet voici les résultats pour -Ofast
gcc: 0.00262204s
clang: 0.0013267s
Le point est que, gcc
ne permet pas d'optimiser le code en O2/O3
niveaux, et j'ai peut-être incorrect, mais pas de corps utilise -Ofast
pour la presse/le niveau de production de code.