* 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ではスコアの精度が落ちてしまうので、やむを得ないということで勘弁してください。
--しかしこの処理内容の増強を行わないと、速すぎる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を使えば速くできますが)。


* こめんと欄
#comment

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