chibicc compiler を6800向けに改造する (12) savage benchmark
savage benchmark というベンチマークテストがある。初出は Dr. Dobb’s Journal, Number 83, September 1983, p. 120。
下記の演算をを2500回繰り返す。
2乗とsqrtは逆演算、lnとexpも逆演算、atanとtanも逆演算なので、結果はa+1に戻るのが正しい。 2500回後の結果は2500になるのが数学的には正しい。
a=tan(atan(exp(ln(sqrt(a*a)))))+1
savage benchmark 初出
DDJには BASIC と PL/Iのリストが掲載された。 今では PL/I は、ほぼ聞かないけど、当時は有力な言語であった。情報処理試験でも選択できた。
下記はBASICのリスト。
Dr. Dobb’s Journal, Number 83, September 1983, p. 120
各機種での実行結果。ハードウェア演算(上段)は高速で精度が高いが、ソフトウェア版(下段)は10倍以上遅いし、精度も悪い。
上段のPL/Iだけ精度が悪いのは、float bin (24) の指定のせいだと思う。
Dr. Dobb’s Journal, Number 83, September 1983, p. 120
BASICMASTER L2 BASICで実行してみた
FORの終値は数値の方が速いはず、とか高速化できる場所はあるけど、とりあえず掲載プログラムに準じたリストにした。
100 REM TIME AND GENERAL ACCURARY TEST PROGRAM 110 TIME=0 120 L=2500 130 A=1 140 FOR I=1 TO L-1 150 A=TAN(ATN(EXP(LOG(SQR(A*A)))))+1 160 NEXT I 170 PRINT "A=";A 180 PRINT TIME
エミュレーター bm2 で実行。596秒。10分弱である。速度は遅い。精度はソフトウェア演算としては良い方である。
BASICMASTERの変数は、指数8bit+符号1bit+仮数31bitの40bit(5バイト)。しかも、演算時は48bit仮数で計算するので精度が高い。
(24bit仮数では10進7.22桁の精度しかなく、当時の電卓の8桁に負けるから、というのをどこかで読んだ気がする。31bitあれば、9.33桁になる)
DDJのは8086/8085 5MHzなのでクロック差が大きい。
gccで実行
doubleで実行すると、a = 2500.000000 。誤差は1e7の桁以下である。%.16fで表示すると、a = 2500.0000000011773409 で誤差はかなり小さい。
aの型をfloatにして、関数をfloat型に差し替えると、a = 2477.244141。
for (i = 1; i < n; i++) { a = tanf(atanf(expf(logf(sqrtf(a*a))))) + 1.0; } printf("a = %f\n", a);
途中結果を見ると、a=3の時点で誤差が発生し始めていて、徐々に増えていくのがわかる。
1: 2.000000 2: 3.000000 3: 4.000001 4: 5.000000 5: 6.000001 6: 7.000000 7: 8.000001 8: 8.999998 9: 9.999994 10: 10.999995
chibicc 6800で実行
いまのところIEEE 32bit floatしかないので、精度はそれなりである。 a = 2535.322753 で多めに出ている。
先頭部分。gccと比べると1桁以上悪い。初等関数の精度が悪いのだが、改善が難しい。
速度はMC6800 1MHz換算で352秒、2MHzなら176秒。当時のコンパイラよりも少し精度が良く、速度は遅い。トレードオフの選択が難しい。
1: 1.999999 2: 3.000000 3: 4.000002 4: 5.000002 5: 6.000011 6: 7.000023 7: 8.000022 8: 9.000026 9: 10.000030 10: 11.000052
ディスカッション
コメント一覧
まだ、コメントがありません