ES-BASIC #13

  • (by K, 2019.11.21)

はじめに

(19-3) 結果のまとめ

言語処理系のインストールサイズタイプ実行時間GCC x64 -O3比備考
GCC x64 8.1.0 -O3449256KBコンパイラ言語1.115秒1.00倍これはコンパイル時間を含んでいません。ちなみにコンパイル時間は0.37秒でした(これは複数回試した最小値です)。
ES-BASIC ver.0.1b 64bit版102KBスクリプト言語1.270秒1.14倍これはJITコンパイル時間を含んでいます。GCCに対して、1.14倍くらいの時間がかかっていることになります。
Ruby 2.6.4p104 x6475323KBスクリプト言語76.102秒68.2倍
Python 3.7.485771KBスクリプト言語344.891秒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

こめんと欄


コメントお名前NameLink

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-11-21 (木) 20:36:18 (16d)