Les Solutions sont les bienvenus dans toutes les langues. :-) Je suis à la recherche de la façon la plus rapide pour obtenir la valeur de π, comme un défi personnel. Plus précisément, je suis en utilisant des moyens qui n'impliquent pas l'aide d' #define
d des constantes comme M_PI
, ou de coder en dur le nombre.
Le programme de tests ci-dessous les différentes façons que je connais. La ligne la version de l'assembly est, en théorie, l'option la plus rapide, bien que manifestement pas portable; je l'ai inclus comme une base de référence pour comparer les autres versions contre. Dans mes tests, avec built-ins, l' 4 * atan(1)
version est plus rapide sur GCC 4.2, parce que l'auto-plis de l' atan(1)
dans une constante. Avec -fno-builtin
spécifié, l' atan2(0, -1)
version est la plus rapide.
Voici le principal programme de tests (pitimes.c
):
#include <math.h>
#include <stdio.h>
#include <time.h>
#define ITERS 10000000
#define TESTWITH(x) { \
diff = 0.0; \
time1 = clock(); \
for (i = 0; i < ITERS; ++i) \
diff += (x) - M_PI; \
time2 = clock(); \
printf("%s\t=> %e, time => %f\n", #x, diff, diffclock(time2, time1)); \
}
static inline double
diffclock(clock_t time1, clock_t time0)
{
return (double) (time1 - time0) / CLOCKS_PER_SEC;
}
int
main()
{
int i;
clock_t time1, time2;
double diff;
/* Warmup. The atan2 case catches GCC's atan folding (which would
* optimise the ``4 * atan(1) - M_PI'' to a no-op), if -fno-builtin
* is not used. */
TESTWITH(4 * atan(1))
TESTWITH(4 * atan2(1, 1))
#if defined(__GNUC__) && (defined(__i386__) || defined(__amd64__))
extern double fldpi();
TESTWITH(fldpi())
#endif
/* Actual tests start here. */
TESTWITH(atan2(0, -1))
TESTWITH(acos(-1))
TESTWITH(2 * asin(1))
TESTWITH(4 * atan2(1, 1))
TESTWITH(4 * atan(1))
return 0;
}
Et la ligne d'assemblage des trucs (fldpi.c
), en notant qu'il ne fonctionne que pour les systèmes x86 et x64:
double
fldpi()
{
double pi;
asm("fldpi" : "=t" (pi));
return pi;
}
Et un script de construction qui s'appuie toutes les configurations, je suis mise à l'essai (build.sh
):
#!/bin/sh
gcc -O3 -Wall -c -m32 -o fldpi-32.o fldpi.c
gcc -O3 -Wall -c -m64 -o fldpi-64.o fldpi.c
gcc -O3 -Wall -ffast-math -m32 -o pitimes1-32 pitimes.c fldpi-32.o
gcc -O3 -Wall -m32 -o pitimes2-32 pitimes.c fldpi-32.o -lm
gcc -O3 -Wall -fno-builtin -m32 -o pitimes3-32 pitimes.c fldpi-32.o -lm
gcc -O3 -Wall -ffast-math -m64 -o pitimes1-64 pitimes.c fldpi-64.o -lm
gcc -O3 -Wall -m64 -o pitimes2-64 pitimes.c fldpi-64.o -lm
gcc -O3 -Wall -fno-builtin -m64 -o pitimes3-64 pitimes.c fldpi-64.o -lm
En dehors de tests entre les différents drapeaux du compilateur (j'ai comparé 32 bits, contre 64 bits aussi, parce que les optimisations sont différents), j'ai aussi essayé en changeant l'ordre des tests autour de. L' atan2(0, -1)
version vient toujours top de tous les temps.