* 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

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS