ES-BASIC #9

  • (by K, 2019.10.10)

(11-1) ベンチマーク#2

  • esbasic0007でのベンチマークはなかなか現実的で、我ながらうまいと思ったのですが、一点だけ気に入らないことがあります。
  • それは「もし私がこのプログラムを高速化しようと思ったら、真っ先に画面左下の三角のゾーンとか、そのそばのやや大きい黒い円の部分(1.5個くらいある)については、まじめに演算せずにn=447を返すようにする」ということです。
    • http://k.osask.jp/files/esb20190827b.png
  • http://k.osask.jp/files/esb20191016a.png
  • そんな「簡単にできる高速化」すらやらずに、「esbasic0007がベンチマークとしていい基準だ」とか言っていたら、うぬぼれでしかないのではないかと。
  • ということで、この高速化を導入してみました。
  • 高速化したら2倍くらい速くなってしまってベンチマークとしてつまらなくなってしまったので、処理内容を16倍にして、結果的にesbasic0007と比較して8倍くらいの負荷のベンチマークになっています。
    • 一応理屈の上では演算制度が16倍に高まったことになっているのですが、画像にすると正直ほとんど差はありません。そういう意味では無駄な計算をやっているとも言えます。
    • しかしこの処理内容の増強を行わないと、速すぎるCPUではスコアの精度が落ちてしまうので、やむを得ないということで勘弁してください。

(11-2) C言語版(32bit向け)

  • もちろんC++もこれで行けます。
    #include <stdio.h>
    #include <time.h>
    
    #define MAX 447
    #define STEP (14.0 / 0x100000)
    #define DN 16
    
    int main()
    {
        int x, y, n, sx, sy, sn, h = 0, t;
        double zx, zy, cx, cy, xx, yy;
        for (y = 0; y < 384; y++) {
            for (x = 0; x < 512; x++) {
                if (y >= 137) {
                    n = 447;
                    if (x * 154 + 57600 < (y << 8)) goto n447;
                    t = x - 245; xx = t * t; t = y - 314; yy = t * t; if (xx + yy < 2400) goto n447;
                    t = x -   3; xx = t * t; t = y - 178; yy = t * t; if (xx + yy < 1700) goto n447;
                }
                sn = 0;
                for (sx = 0; sx < DN; sx++) {
                    cx = (double) 0x4750 / 0x10000 + (x * DN + sx) * (STEP / DN);
                    for (sy = 0; sy < DN; sy++) {
                        cy = (double) 0x1e8 / 0x10000 + (y * DN + sy) * (STEP / DN);
                        zx = zy = 0;
                        for (n = 0; n < MAX; n++) {
                            xx = zx * zx;
                            yy = zy * zy;
                            if (xx + yy > 4) break;
                            zy = zx * zy * 2 - cy;
                            zx = xx - yy + cx;
                        }
                        sn += n;
                    }
                }
            //  n = sn / (DN * DN);
                n = sn >> 8;
    n447:
                h += n; // 表示の代わりに集計
            }
        }
        printf("%d\n", h);
        printf("(%.3f[sec])\n", clock() / (double) CLOCKS_PER_SEC);
        return 0;
    }
  • これで計算すると h=28654534 になります。
  • if (y >= 137) { ... } を書かずに計算させると演算時間が2倍くらいになります。それでももちろん h=28654534 になります。

(11-4) C言語版(64bit向け)

  • もちろんC++もこれで行けます。
    #include <stdio.h>
    #include <time.h>
    
    #define MAX 447
    #define DN 16
    
    int main()
    {
        long long x, y, sx, sy, zx, zy, cx, cy, xx, yy, t;
        int n, sn, h = 0;
        for (y = 0; y < 384; y++) {
            for (x = 0; x < 512; x++) {
                if (y >= 137) {
                    n = 447;
                    if (x * 154 + 57600 < (y << 8)) goto n447;
                    t = x - 245; xx = t * t; t = y - 314; yy = t * t; if (xx + yy < 2400) goto n447;
                    t = x -   3; xx = t * t; t = y - 178; yy = t * t; if (xx + yy < 1700) goto n447;
                }
                sn = 0;
                for (sx = 0; sx < DN; sx++) {
                    cx = (x * 16 + sx) * 14 + 4673536;
                    for (sy = 0; sy < DN; sy++) {
                        cy = (y * 16 + sy) * 14 + 124928;
                        zx = zy = 0;
                        for (n = 0; n < MAX; n++) {
                            xx = (zx * zx) >> 24;
                            yy = (zy * zy) >> 24;
                            if (xx + yy > 0x4000000) break;
                            zy = (zx * zy) >> 23;
                            zx = xx - yy + cx;
                            zy = zy - cy;
                        }
                        sn += n;
                    }
                }
            //  n = sn / (DN * DN);
                n = sn >> 8;
    n447:
                h += n; // 表示の代わりに集計
            }
        }
        printf("%d\n", h);
        printf("(%.3f[sec])\n", clock() / (double) CLOCKS_PER_SEC);
        return 0;
    }
  • 結果としては当然のことながら(11-3)と同じく28656170 が表示されます。
  • 32bitのC/C++では、いろいろ工夫してもdoubleを使った場合よりも速くすることはできませんでした(インラインアセンブラでIMUL+SHRDを使えば速くできますが)。

こめんと欄


コメントお名前NameLink

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