Kişisel bir meydan okuma olarak π değerini elde etmenin en hızlı yolunu arıyorum. Daha spesifik olarak, #define
sabitleri kullanmayı M_PI
veya içindeki sayıyı sabit kodlamayı içermeyen yollar kullanıyorum .
Aşağıdaki program bildiğim çeşitli yolları test ediyor. Satır içi montaj sürümü, teorik olarak, açıkça taşınabilir olmasa da, en hızlı seçenektir. Diğer sürümlerle karşılaştırmak için bir temel olarak ekledim. Testlerimde, yerleşik olarak, 4 * atan(1)
sürüm GCC 4.2'de en hızlıdır, çünkü otomatik atan(1)
olarak bir sabite katlanır . İle -fno-builtin
belirtilen, atan2(0, -1)
sürüm en hızlı.
İşte ana test programı ( 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;
}
Ve fldpi.c
yalnızca x86 ve x64 sistemleri için çalışacak satır içi montaj öğeleri ( ):
double
fldpi()
{
double pi;
asm("fldpi" : "=t" (pi));
return pi;
}
Ve test ettiğim tüm yapılandırmaları oluşturan bir derleme ( 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
Çeşitli derleyici bayrakları arasında test dışında (optimizasyonlar farklı olduğu için 32-bit'i 64-bit ile de karşılaştırdım), testlerin sırasını değiştirmeyi de denedim. Ama yine de, atan2(0, -1)
sürüm her seferinde hala zirveye çıkıyor.