chibicc compiler を6800向けに改造する (12) savage benchmark

BASICMASTER, 昔のパソコン

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