개인적 도전으로 π의 가치를 얻는 가장 빠른 방법을 찾고 있습니다. 보다 구체적으로, 나는 #define
상수를 사용 M_PI
하거나 숫자를 하드 코딩 하지 않는 방법을 사용 하고 있습니다.
아래 프로그램은 내가 아는 다양한 방법을 테스트합니다. 인라인 어셈블리 버전은 이론 상으로는 가장 빠른 옵션이지만 명확하게 이식 할 수는 없습니다. 다른 버전과 비교하기 위해 기준으로 포함 시켰습니다. 내 테스트에서 기본 제공되는 4 * atan(1)
버전은 GCC 4.2에서 자동으로 atan(1)
상수로 접 히기 때문에 버전이 가장 빠릅니다 . 으로 -fno-builtin
지정된의 atan2(0, -1)
버전은 빠른입니다.
주요 테스트 프로그램 ( 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;
}
그리고 fldpi.c
x86 및 x64 시스템에서만 작동 하는 인라인 어셈블리 ( ) :
double
fldpi()
{
double pi;
asm("fldpi" : "=t" (pi));
return pi;
}
그리고 테스트하고있는 모든 구성을 빌드하는 빌드 스크립트 ( 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
다양한 컴파일러 플래그 사이의 테스트 외에도 (최적화가 다르기 때문에 32 비트를 64 비트와 비교했지만) 테스트 순서를 전환하려고 시도했습니다. 그러나 여전히 atan2(0, -1)
버전은 항상 맨 위에 나옵니다.