Tôi đang tìm cách nhanh nhất để đạt được giá trị của π, như một thách thức cá nhân. Cụ thể hơn, tôi đang sử dụng những cách không liên quan đến việc sử dụng các #define
hằng số như M_PI
hoặc mã hóa cứng số.
Chương trình dưới đây kiểm tra những cách khác nhau mà tôi biết. Về lý thuyết, phiên bản lắp ráp nội tuyến là tùy chọn nhanh nhất, mặc dù rõ ràng không thể mang theo được. Tôi đã đưa nó làm cơ sở để so sánh với các phiên bản khác. Trong các thử nghiệm của tôi, với các phần dựng sẵn, 4 * atan(1)
phiên bản nhanh nhất trên GCC 4.2, vì nó tự động gập lại atan(1)
thành một hằng số. Với -fno-builtin
chỉ định, atan2(0, -1)
phiên bản là nhanh nhất.
Đây là chương trình thử nghiệm chính ( 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;
}
Và công cụ lắp ráp nội tuyến ( fldpi.c
) sẽ chỉ hoạt động cho các hệ thống x86 và x64:
double
fldpi()
{
double pi;
asm("fldpi" : "=t" (pi));
return pi;
}
Và một tập lệnh xây dựng xây dựng tất cả các cấu hình tôi đang thử nghiệm ( 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
Ngoài việc kiểm tra giữa các cờ trình biên dịch khác nhau (tôi cũng đã so sánh 32 bit với 64 bit vì các tối ưu hóa khác nhau), tôi cũng đã thử chuyển đổi thứ tự của các thử nghiệm xung quanh. Tuy nhiên, atan2(0, -1)
phiên bản vẫn xuất hiện trên đầu mỗi lần.