* ES-BASIC #13 -(by [[K]], 2019.11.21) ** はじめに -このページは[[esbasic0012]]の続きです。 ** (19-3) 結果のまとめ |言語|処理系のインストールサイズ|タイプ|実行時間|GCC x64 -O3比|備考| |GCC x64 8.1.0 -O3|RIGHT:449256KB|コンパイラ言語|RIGHT:1.115秒|RIGHT:1.00倍|これはコンパイル時間を含んでいません。ちなみにコンパイル時間は0.37秒でした(これは複数回試した最低値です)。| |GCC x64 8.1.0 -O3|RIGHT:449256KB|コンパイラ言語|RIGHT:1.115秒|RIGHT:1.00倍|これはコンパイル時間を含んでいません。ちなみにコンパイル時間は0.37秒でした(これは複数回試した最小値です)。| |ES-BASIC ver.0.1b 64bit版|RIGHT:102KB|スクリプト言語|RIGHT:1.270秒|RIGHT:1.14倍|これはJITコンパイル時間を含んでいます。GCCに対して、1.14倍くらいの時間がかかっていることになります。| |Ruby 2.6.4p104 x64|RIGHT:75323KB|スクリプト言語|RIGHT:76.102秒|RIGHT:68.2倍|| |Python 3.7.4|RIGHT:85771KB|スクリプト言語|RIGHT:344.891秒|RIGHT:309倍|| ** (19-4) gcc x64 8.1.0 -O3 -gccでは以下の「19-1d.c」が最も高速に計算できたので、このコードで処理時間を測定しました。 // "19-1d.c" #include <stdio.h> #include <time.h> int main() { int n, sn, h = 0; long long x, y, cx, cy, zx, zy, xx, yy, xx0; for (y = -125152; y > -211168; y -= 224) { for (x = 4673760; x < 4788448; x += 224) { sn = 7152; for (cx = x - 224; cx < x; cx += 56) { xx0 = (cx * cx) >> 24; for (cy = y + 224; cy > y; cy -= 56) { zy = cy; zx = cx; xx = xx0; yy = (cy * cy) >> 24; n = -446; do { zy = (zy * zx) >> 23; zx = xx + cx - yy; zy = zy + cy; n++; if (n >= 0) goto skip; xx = (zx * zx) >> 24; yy = (zy * zy) >> 24; } while (xx + yy <= 0x4000000); sn += n; skip: ; } } h += sn >> 4; } } printf("h=%d\n", h); printf("time=%.3f[sec]\n", (float) clock() / CLOCKS_PER_SEC); return 0; // dummy } -これを実行すると、手元の環境では以下のようになりました。 h=28656617 time=1.115[sec] ** (19-5) ES-BASIC ver.0.1b 64ビット版 -ES-BASICでは以下のコードで処理時間を測定しました。 1 $DI=R07; // R07を自由に使いたいときは事前にこれを実行する必要がある 2 ALIAS ZX:R01, ZY:R03, XX:R06, YY:R07, CX:R08, CY:R09, XX0:R10, N:R11, SN:R12, X:R13, Y:R14, H:R15 3 H=0 4 FORNE Y=_125152,_211168,_224 5 FORNE X=4673760,4788448,224 6 SN=7152; // 447*16 7 FORNE CX=X-224,X,56 8 XX0=CX*:CX>>24 9 FORNE CY=Y+224,Y,_56 10 ZY=CY 11 ZX=CX 12 XX=XX0 13 YY=CY*:CY>>24 14 N=_446 15 DOLOOP 16 ZY=ZY*:ZX>>23 17 ZX=XX+CX-YY 18 ZY=ZY+CY 19 N=N+1 20 IF >=0 GOTO SKIP 21 XX=ZX*:ZX>>24 22 YY=ZY*:ZY>>24 23 ENDDO XX+YY<=0X4000000 24 SN=SN+N 25 LABEL SKIP 26 NEXT 27 NEXT 28 SN=SN>>4 29 H=H+SN 30 NEXT 31 NEXT 32 PRINT H -実行結果は以下のようになります。 28656617 (1.270[sec]) -ちなみにこのプログラムでは、R00とR02の利用を避けて、さらに乗算に A*:B>>C 形式を使うことで、32ビット版のES-BASICでも同じ結果が得られるようになっています(内部では、IMULを使って結果をEDX:EAXに生成した後、SHRD EAX,EDX,24でシフトしている)。でも32ビット版では速度が落ちて、1.899秒くらいはかかります。 ** (19-6) Ruby 2.6.4p104 x64 -Rubyでは浮動小数点演算を使ったほうが高速だったので、19-1eのアルゴリズムを使いました。 start_time = Time.now h = 0 y = -125152 C24 = 1.0 / 16777216.0 while y > -211168 do x = 4673760 while x < 4788448 do sn = 7152 ix = x - 224 while ix < x do cx = ix * C24 xx0 = cx * cx iy = y + 224 while iy > y do cy = iy * C24 zy = cy zx = cx xx = xx0 yy = cy * cy n = -446 begin zy = zy * zx * 2.0 zx = xx + cx - yy zy = zy + cy n += 1 break if n >= 0 xx = zx * zx yy = zy * zy end while xx + yy <= 4.0 sn += n iy -= 56 end ix += 56 end h += sn >> 4 x += 224 end y -= 224 end p h p Time.now - start_time -実行結果は以下のようになりました。 28654722 76.1023528 ** (19-7) Python 3.7.4 -Pythonでも浮動小数点演算を使ったほうが高速だったので、19-1eのアルゴリズムを使いました。 import time start = time.time() h = 0 C24 = 1.0 / 16777216.0 y = -125152 while y > -211168: x = 4673760 while x < 4788448: sn = 7152 ix = x - 224 while ix < x: cx = ix * C24 xx0 = cx * cx iy = y + 224 while iy > y: cy = iy * C24 zy = cy zx = cx xx = xx0 yy = cy * cy n = -446 while xx + yy <= 4.0: zy = zy * zx * 2.0 zx = xx + cx - yy zy = zy + cy n += 1 if n >= 0: break xx = zx * zx yy = zy * zy sn += n iy -= 56 ix += 56 h += sn >> 4 x += 224 y -= 224 print(h) print(time.time() - start) -実行結果は以下のようになりました。 28654722 344.89172649383545 * こめんと欄 #comment