esbasic0007
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
* ES-BASIC #7
-(by [[K]], 2019.09.21)
** (9-1) ベンチマーク#1
-ES-BASICが他の言語と比べてどのくらい速いのか、もしくはど...
-それで世間の人はどんなプログラムで比較しているのかなと思...
--[1]再帰を使いまくってfibo(42)を計算する。
--[2]あえて収束の悪い級数を使って(arctan(1)の級数展開)...
--[3]単純な10億回ループ。
--[4]自然数を与えたときに、その平方根までの奇数で割り算し...
-これらのベンチマークは以下の問題があると思いました。
--[1]フィボナッチ数を計算するのなら、普通は再帰なんか使わ...
--[2]普通、円周率を計算するのには、もっと収束の速い級数を...
--[3]単純10億回ループは、まあ最速なアルゴリズムではあると...
--[4]単に素数探しをしたいだけなら、エラトステネスのふるい...
-ということで、まともなアルゴリズムを使っているのにそれな...
-私の手元でベンチマークしたらこんな感じです:
|言語|処理時間|備考|
|Python 3.7.4|RIGHT:324.276秒|コードは(9-5)|
|Ruby 2.6.4|RIGHT:98.800秒|コードは(9-6)|
|ES-BASIC (32bit)|RIGHT:2.906秒|コードは(9-3)、JITコンパ...
|gcc(C言語)(32bit)|RIGHT:1.954秒|コードは(9-2)、もちろん...
|ES-BASIC (32bit、レジスタ変数利用)|RIGHT:1.820秒|コード...
|gcc(C言語)(64bit)|RIGHT:1.195秒|コードは(9-4)、もちろん...
-ちなみにこのベンチマークプログラムは、以下の画像の各ピク...
--http://k.osask.jp/files/esb20190827b.png
** (9-2) C言語版(32bit向け)
-もちろんC++もこれで行けます。
#include <stdio.h>
#include <time.h>
#define MAX 447
#define STEP (14.0 / 0x100000)
#define DN 4
int main()
{
int x, y, n, sx, sy, sn, h = 0;
double zx, zy, cx, cy, xx, yy;
for (y = 0; y < 384; y++) {
for (x = 0; x < 512; x++) {
sn = 0;
for (sx = 0; sx < DN; sx++) {
cx = (double) 0x4750 / 0x10000 + (x * DN...
for (sy = 0; sy < DN; sy++) {
cy = (double) 0x1e8 / 0x10000 + (y *...
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 >> 4;
h += n; // 表示の代わりに集計
}
}
printf("%d\n", h);
printf("(%.3f[sec])\n", clock() / (double) CLOCKS_PE...
return 0;
}
-うまく実行できると 28654738 が表示されると思いますが、浮...
** (9-3) ES-BASIC版(32bit向け)
-ES-BASICは現状のバージョンでは浮動小数点演算をサポートし...
-ES-BASICでも定数に名前を付ける機能(ALIAS命令)を持って...
1 H=0
2 FOR Y=0,383
3 FOR X=0,511
4 SN=0
5 FOR SX=0,3
6 CX=(X*4+SX)*56+4673536
7 FOR SY=0,3
8 CY=(Y*4+SY)*56+124928
9 ZX=0
10 ZY=0
11 FOR N=0,446
12 XX=ZX*>>ZX,24; // これはZXとZXをIMULで計...
13 YY=ZY*>>ZY,24
14 T=XX+YY
15 IF T>0X4000000 GOTO SKIP
16 ZY=ZY*>>ZX,23
17 ZX=XX-YY+CX
18 ZY=ZY-CY
19 NEXT
20 LABEL SKIP
21 SN=SN+N
22 NEXT
23 NEXT
24 N=SN>>4; // N=SN/16 (N=0...447)
25 H=H+N; // 表示の代わりに集計
26 NEXT
27 NEXT
28 PRINT H
-これは実行すると 28656617 という結果になります。オリジナ...
** (9-4) C言語版(64bit向け)
-もちろんC++もこれで行けます。
-ES-BASICでは「浮動小数点演算が使えないから」という理由で...
#include <stdio.h>
#include <time.h>
#define MAX 447
#define DN 4
int main()
{
long long x, y, sx, sy, zx, zy, cx, cy, xx, yy;
int n, sn, h = 0;
for (y = 0; y < 384; y++) {
for (x = 0; x < 512; x++) {
sn = 0;
for (sx = 0; sx < DN; sx++) {
cx = (x * 4 + sx) * 56 + 4673536;
for (sy = 0; sy < DN; sy++) {
cy = (y * 4 + sy) * 56 + 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 >> 4;
h += n; // 表示の代わりに集計
}
}
printf("%d\n", h);
printf("(%.3f[sec])\n", clock() / (double) CLOCKS_PE...
return 0;
}
-結果としては当然のことながら(9-3)と同じく28656617 が表示...
-32bitのC/C++では、いろいろ工夫してもdoubleを使った場合よ...
** (9-5) Python版
-私はPython初心者なので、もっといい書き方があるかもしれま...
import time
start = time.time()
h = 0
CX0 = 0x4750 / 0x10000
CY0 = 0x1e8 / 0x10000
STP = 14.0 / 0x100000 / 4
for y in range(384):
for x in range(512):
sn = 0
for sx in range(4):
cx = CX0 + (x * 4 + sx) * STP
for sy in range(4):
cy = CY0 + (y * 4 + sy) * STP
zx = zy = 0
n = 0
while n < 447:
xx = zx * zx
yy = zy * zy
if xx + yy > 4: break
zy = zx * zy * 2 - cy
zx = xx - yy + cx
n = n + 1
sn += n
n = sn >> 4
h += n
print(h)
print(time.time() - start)
-これを Python 3.7.4 で実行したところ、28654739になりまし...
** (9-6) Ruby版
-私はRuby初心者なので、もっといい書き方があるかもしれませ...
start_time = Time.now
h = 0
CX0 = 0x4750 / 65536.0
CY0 = 0x1e8 / 65536.0
STP = 14.0 / 0x100000 / 4
y = 0
while y < 384 do
x = 0
while x < 512 do
sn = 0
sx = 0
while sx < 4 do
cx = CX0 + (x * 4 + sx) * STP
sy = 0
while sy < 4 do
cy = CY0 + (y * 4 + sy) * STP
zx = zy = 0
n = 0
while n < 447 do
xx = zx * zx
yy = zy * zy
if xx + yy > 4 then
break
end
zy = zx * zy * 2 - cy
zx = xx - yy + cx
n = n + 1
end
sn += n
sy = sy + 1
end
sx = sx + 1
end
n = sn >> 4
h += n
x = x + 1
end
y = y + 1
end
p h
p Time.now - start_time
-これを ruby 2.6.4 で実行したところ、28654739になりました...
** (9-7) ES-BASIC版(32bit向け、レジスタ変数利用)
-ES-BASICはいくつかの変数をレジスタに割り当てることで、大...
1 H=0
2 $EDI = EDI; // EDIレジスタを自由に使いたいときの前処理
3 FOR Y=0,383
4 FOR X=0,511
5 SN=0
6 FOR SX=0,3
7 CX=(X*4+SX)*56+4673536
8 FOR SY=0,3
9 CY=(Y*4+SY)*56+124928
10 ALIAS ZX:ECX, ZY:EBX, XX:ESI, YY:EDI
11 ZX=0
12 ZY=0
13 FOR N=0,446
14 XX=ZX*>>ZX,24
15 YY=ZY*>>ZY,24; // 結果はEAXにも入っている.
16 EAX=EAX+XX
17 IF EAX>0X4000000 GOTO SKIP
18 ZY=ZX*>>ZY,23
19 XX=XX-YY+CX
20 ZX=XX
21 ZY=ZY-CY
22 NEXT
23 LABEL SKIP
24 SN=SN+N
25 NEXT
26 NEXT
27 N=SN>>4; // N=SN/16 (N=0...447)
28 H=H+N; // 表示の代わりに集計
29 NEXT
30 NEXT
31 PRINT H
-これは実行すると 28656617 という結果になります。(9-3)と...
-3行ほど増えていますが、これだけ速くなってくれるのであれ...
** (9-8) ES-BASIC版(64bit向け、レジスタ変数利用)
-ES-BASICの64bit版ができたので試してみました。
1 $DI = RDI; // RDIレジスタを自由に使いたいときの前処理
2 ALIAS ZX:RCX, ZY:RDX, XX:RBX, YY:RSI, N:RDI, CX:R08,...
3 ALIAS SX:R10, SY:R11, SN:R12, H:R13, X:R14, Y:R15
4 H=0
5 FOR Y=0,383
6 FOR X=0,511
7 SN=0
8 FOR SX=0,3
9 CX=(X*4+SX)*56+4673536
10 FOR SY=0,3
11 CY=(Y*4+SY)*56+124928
12 ZX=0
13 ZY=0
14 FOR N=0,446
15 XX=(ZX*ZX)>>24
16 YY=(ZY*ZY)>>24
17 RAX=XX+YY
18 IF RAX>0X4000000 GOTO SKIP
19 ZY=(ZY*ZX)>>23
20 XX=XX-YY
21 ZX=XX+CX
22 ZY=ZY-CY
23 NEXT
24 LABEL SKIP
25 SN=SN+N
26 NEXT
27 NEXT
28 N=SN>>4; // N=SN/16 (N=0...447)
29 H=H+N; // 表示の代わりに集計
30 NEXT
31 NEXT
32 PRINT H
-これは実行すると 28656617 という結果になります。(9-3)と...
-3行ほど増えていますが、これだけ速くなってくれるのであれ...
* こめんと欄
#comment
終了行:
* ES-BASIC #7
-(by [[K]], 2019.09.21)
** (9-1) ベンチマーク#1
-ES-BASICが他の言語と比べてどのくらい速いのか、もしくはど...
-それで世間の人はどんなプログラムで比較しているのかなと思...
--[1]再帰を使いまくってfibo(42)を計算する。
--[2]あえて収束の悪い級数を使って(arctan(1)の級数展開)...
--[3]単純な10億回ループ。
--[4]自然数を与えたときに、その平方根までの奇数で割り算し...
-これらのベンチマークは以下の問題があると思いました。
--[1]フィボナッチ数を計算するのなら、普通は再帰なんか使わ...
--[2]普通、円周率を計算するのには、もっと収束の速い級数を...
--[3]単純10億回ループは、まあ最速なアルゴリズムではあると...
--[4]単に素数探しをしたいだけなら、エラトステネスのふるい...
-ということで、まともなアルゴリズムを使っているのにそれな...
-私の手元でベンチマークしたらこんな感じです:
|言語|処理時間|備考|
|Python 3.7.4|RIGHT:324.276秒|コードは(9-5)|
|Ruby 2.6.4|RIGHT:98.800秒|コードは(9-6)|
|ES-BASIC (32bit)|RIGHT:2.906秒|コードは(9-3)、JITコンパ...
|gcc(C言語)(32bit)|RIGHT:1.954秒|コードは(9-2)、もちろん...
|ES-BASIC (32bit、レジスタ変数利用)|RIGHT:1.820秒|コード...
|gcc(C言語)(64bit)|RIGHT:1.195秒|コードは(9-4)、もちろん...
-ちなみにこのベンチマークプログラムは、以下の画像の各ピク...
--http://k.osask.jp/files/esb20190827b.png
** (9-2) C言語版(32bit向け)
-もちろんC++もこれで行けます。
#include <stdio.h>
#include <time.h>
#define MAX 447
#define STEP (14.0 / 0x100000)
#define DN 4
int main()
{
int x, y, n, sx, sy, sn, h = 0;
double zx, zy, cx, cy, xx, yy;
for (y = 0; y < 384; y++) {
for (x = 0; x < 512; x++) {
sn = 0;
for (sx = 0; sx < DN; sx++) {
cx = (double) 0x4750 / 0x10000 + (x * DN...
for (sy = 0; sy < DN; sy++) {
cy = (double) 0x1e8 / 0x10000 + (y *...
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 >> 4;
h += n; // 表示の代わりに集計
}
}
printf("%d\n", h);
printf("(%.3f[sec])\n", clock() / (double) CLOCKS_PE...
return 0;
}
-うまく実行できると 28654738 が表示されると思いますが、浮...
** (9-3) ES-BASIC版(32bit向け)
-ES-BASICは現状のバージョンでは浮動小数点演算をサポートし...
-ES-BASICでも定数に名前を付ける機能(ALIAS命令)を持って...
1 H=0
2 FOR Y=0,383
3 FOR X=0,511
4 SN=0
5 FOR SX=0,3
6 CX=(X*4+SX)*56+4673536
7 FOR SY=0,3
8 CY=(Y*4+SY)*56+124928
9 ZX=0
10 ZY=0
11 FOR N=0,446
12 XX=ZX*>>ZX,24; // これはZXとZXをIMULで計...
13 YY=ZY*>>ZY,24
14 T=XX+YY
15 IF T>0X4000000 GOTO SKIP
16 ZY=ZY*>>ZX,23
17 ZX=XX-YY+CX
18 ZY=ZY-CY
19 NEXT
20 LABEL SKIP
21 SN=SN+N
22 NEXT
23 NEXT
24 N=SN>>4; // N=SN/16 (N=0...447)
25 H=H+N; // 表示の代わりに集計
26 NEXT
27 NEXT
28 PRINT H
-これは実行すると 28656617 という結果になります。オリジナ...
** (9-4) C言語版(64bit向け)
-もちろんC++もこれで行けます。
-ES-BASICでは「浮動小数点演算が使えないから」という理由で...
#include <stdio.h>
#include <time.h>
#define MAX 447
#define DN 4
int main()
{
long long x, y, sx, sy, zx, zy, cx, cy, xx, yy;
int n, sn, h = 0;
for (y = 0; y < 384; y++) {
for (x = 0; x < 512; x++) {
sn = 0;
for (sx = 0; sx < DN; sx++) {
cx = (x * 4 + sx) * 56 + 4673536;
for (sy = 0; sy < DN; sy++) {
cy = (y * 4 + sy) * 56 + 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 >> 4;
h += n; // 表示の代わりに集計
}
}
printf("%d\n", h);
printf("(%.3f[sec])\n", clock() / (double) CLOCKS_PE...
return 0;
}
-結果としては当然のことながら(9-3)と同じく28656617 が表示...
-32bitのC/C++では、いろいろ工夫してもdoubleを使った場合よ...
** (9-5) Python版
-私はPython初心者なので、もっといい書き方があるかもしれま...
import time
start = time.time()
h = 0
CX0 = 0x4750 / 0x10000
CY0 = 0x1e8 / 0x10000
STP = 14.0 / 0x100000 / 4
for y in range(384):
for x in range(512):
sn = 0
for sx in range(4):
cx = CX0 + (x * 4 + sx) * STP
for sy in range(4):
cy = CY0 + (y * 4 + sy) * STP
zx = zy = 0
n = 0
while n < 447:
xx = zx * zx
yy = zy * zy
if xx + yy > 4: break
zy = zx * zy * 2 - cy
zx = xx - yy + cx
n = n + 1
sn += n
n = sn >> 4
h += n
print(h)
print(time.time() - start)
-これを Python 3.7.4 で実行したところ、28654739になりまし...
** (9-6) Ruby版
-私はRuby初心者なので、もっといい書き方があるかもしれませ...
start_time = Time.now
h = 0
CX0 = 0x4750 / 65536.0
CY0 = 0x1e8 / 65536.0
STP = 14.0 / 0x100000 / 4
y = 0
while y < 384 do
x = 0
while x < 512 do
sn = 0
sx = 0
while sx < 4 do
cx = CX0 + (x * 4 + sx) * STP
sy = 0
while sy < 4 do
cy = CY0 + (y * 4 + sy) * STP
zx = zy = 0
n = 0
while n < 447 do
xx = zx * zx
yy = zy * zy
if xx + yy > 4 then
break
end
zy = zx * zy * 2 - cy
zx = xx - yy + cx
n = n + 1
end
sn += n
sy = sy + 1
end
sx = sx + 1
end
n = sn >> 4
h += n
x = x + 1
end
y = y + 1
end
p h
p Time.now - start_time
-これを ruby 2.6.4 で実行したところ、28654739になりました...
** (9-7) ES-BASIC版(32bit向け、レジスタ変数利用)
-ES-BASICはいくつかの変数をレジスタに割り当てることで、大...
1 H=0
2 $EDI = EDI; // EDIレジスタを自由に使いたいときの前処理
3 FOR Y=0,383
4 FOR X=0,511
5 SN=0
6 FOR SX=0,3
7 CX=(X*4+SX)*56+4673536
8 FOR SY=0,3
9 CY=(Y*4+SY)*56+124928
10 ALIAS ZX:ECX, ZY:EBX, XX:ESI, YY:EDI
11 ZX=0
12 ZY=0
13 FOR N=0,446
14 XX=ZX*>>ZX,24
15 YY=ZY*>>ZY,24; // 結果はEAXにも入っている.
16 EAX=EAX+XX
17 IF EAX>0X4000000 GOTO SKIP
18 ZY=ZX*>>ZY,23
19 XX=XX-YY+CX
20 ZX=XX
21 ZY=ZY-CY
22 NEXT
23 LABEL SKIP
24 SN=SN+N
25 NEXT
26 NEXT
27 N=SN>>4; // N=SN/16 (N=0...447)
28 H=H+N; // 表示の代わりに集計
29 NEXT
30 NEXT
31 PRINT H
-これは実行すると 28656617 という結果になります。(9-3)と...
-3行ほど増えていますが、これだけ速くなってくれるのであれ...
** (9-8) ES-BASIC版(64bit向け、レジスタ変数利用)
-ES-BASICの64bit版ができたので試してみました。
1 $DI = RDI; // RDIレジスタを自由に使いたいときの前処理
2 ALIAS ZX:RCX, ZY:RDX, XX:RBX, YY:RSI, N:RDI, CX:R08,...
3 ALIAS SX:R10, SY:R11, SN:R12, H:R13, X:R14, Y:R15
4 H=0
5 FOR Y=0,383
6 FOR X=0,511
7 SN=0
8 FOR SX=0,3
9 CX=(X*4+SX)*56+4673536
10 FOR SY=0,3
11 CY=(Y*4+SY)*56+124928
12 ZX=0
13 ZY=0
14 FOR N=0,446
15 XX=(ZX*ZX)>>24
16 YY=(ZY*ZY)>>24
17 RAX=XX+YY
18 IF RAX>0X4000000 GOTO SKIP
19 ZY=(ZY*ZX)>>23
20 XX=XX-YY
21 ZX=XX+CX
22 ZY=ZY-CY
23 NEXT
24 LABEL SKIP
25 SN=SN+N
26 NEXT
27 NEXT
28 N=SN>>4; // N=SN/16 (N=0...447)
29 H=H+N; // 表示の代わりに集計
30 NEXT
31 NEXT
32 PRINT H
-これは実行すると 28656617 という結果になります。(9-3)と...
-3行ほど増えていますが、これだけ速くなってくれるのであれ...
* こめんと欄
#comment
ページ名: