ฉันกำลังมองหาวิธีที่เร็วที่สุดที่จะได้รับคุณค่าของπซึ่งเป็นความท้าทายส่วนบุคคล โดยเฉพาะอย่างยิ่งฉันใช้วิธีการที่ไม่เกี่ยวข้องกับการใช้#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)
รุ่นยังคงออกมาด้านบนทุกครั้ง