SSブログ
English Version

MSX-DOS上でのGAME言語のベンチマーク [MSX]

 「MSX-DOSに自作スクリーンエディタ移植」の記事内で書いたWebMSX環境を使ったMSX-DOSでGAME言語を動かした際のサンプルプログラムではGAMEコンパイラの効果があまり出ていなかったので実用的なプログラムに近いもので実行速度を評価してみました。

 WebMSXでは「MSX2+ JAPAN(NTSC)」を選択し、QuickOptionsの設定内にある「CPU Turbo」を「8x」に設定しています。

 使用したプログラムはインタプリタでの実行時間が数分かかりそうなものということで縦横合計式のクイズ(私が適当に作ったもの)を全探索で解くプログラムにしました。
 A-Fは1~6の範囲の整数です。

 ベンチマークで使われるASCIIARTの整数版と言ったところです。

ベンチマーク用のクイズ


 参考にtwitterにポストした動画付きコメントを貼っておきます。



 計測結果は次のとおりです。
 尚、後述のようにBASICソースの先頭に「DEFINT A-Z」を追加したので上記のTwitterの値より速くなっています。

LanguageTime[sec]Environment
GAME80 Interpreter54WebMSX
MSX2+ JAPAN, CPU Turbo 8x, MSX-DOS Ver1.03
GAME80 Compiler1WebMSX
MSX2+ JAPAN, CPU Turbo 8x, MSX-DOS Ver1.03
MSX BASIC38WebMSX
MSX2+ JAPAN, CPU Turbo 8x, BASIC Ver3.0
CP/M-80 GAME80 Interpreter52Pic24CPM ボード
Z-80:16MHz
CP/M-80 GAME80 V0.03 Interpreter43Z80GAL ボード
Z-80:20MHz
CP/M-80 GAME80 Compiler1Z80GAL ボード
Z-80:20MHz
CP/M-80 MBASIC65(1m5s)Pic24CPM ボード
Z-80:16MHz, MBASIC Rev. 5.21
CP/M-86 MBASIC191(3m11s)Pic24V20 ボード
V20:8MHz, MBASIC Rev. 5.22
CP/M-86 MBASIC97(1m37s)Pic24V20 ボード
V20:16MHz, MBASIC Rev. 5.22
CP/M-86 BASIC85(1m25s)Pic24V20 ボード
V20:16MHz, Personal Basic Ver 1.1
CP/M-68K CBASIC Compiler319(5m19s)Pic24CPM68K ボード
MC68008:8MHz, CBASIC Ver 1.0
PC-G850V BASIC296(4m56s)PC-G850V(ポケコン)
Built-in BASIC Interpreter
Z-80:8MHz
PC-G850V GAME80 Interpreter553(9m13s)
87(1m27s)
PC-G850V(ポケコン)
Z-80:8MHz
PC-G850V GAME80 Compiler2.5PC-G850V(ポケコン)
Z-80:8MHz
PC-G850V
C Compiler
72(1m12s)PC-G850V(ポケコン)
Built-in C compiler
Z-80:8MHz
PC-6001
GAME80 Interpreter
395(6m35s)PC-6001エミュレータ(PC6001V)
PC-6001's CPU is Z80:3.9936MHz
PC-6001
GAME80 Compiler
11PC-6001エミュレータ(PC6001V)
PC-6001's CPU is Z80:3.9936MHz
ehBASIC V3.52
interpreter for 68000
67(1m7s)Pic24MC68K(CP/M-68K)
MC68HC000-P16:16MHz

★2022/02/21 追記
 自作のMC68Kボード(Pic24MC68K)を追記
 DEFINTには対応していないのでREMでコメントアウトして実行

★2021/10/15 追記
 自作のZ80ボード(Z80GAL)を追記

★2020/09/25 追記
 自作のCP/M-86ボード(Pic24V20)が16MHzで動くようになったので追記

★2020/01/28 追記
 パピコン(PC-6001)にGAMEインタプリタとコンパイラを移植したので追記
 クロックが約4MHzにしては遅い結果でした。VRAMのDMA等が原因?

★2020/01/18 追記
 PC-G850V(ポケコン)での内蔵C言語の測定結果を追記
 BASICの4倍強、GAMEインタプリタより若干速いという結果でした。

★2020/01/16 変更
 PC-G850V(ポケコン)でのGAMEインタプリタをチューニングし高速化

★2020/01/15 追記
 PC-G850V(ポケコン)にGAMEコンパイラを移植したので測定結果を追記
 インタプリタではかなり遅かったが、コンパイルするとクロック相当の速度

★2020/01/14 追記
 PC-G850V(ポケコン)にGAME80を移植したので測定結果を追記
 予想外に遅いですね^^;キーセンスのシステムコールで時間が掛かっている?

★2020/01/09 追記
 PC-G850V(ポケコン)の測定結果を追記。エラー対処のため、下記の変更を実施
  「DEFINT A-Z」 --> comment out
  for段数超過エラーのため、変数Aに関してはIF文でループ

★2020/01/09 追記
 CP/M-80でのGAME80 Interpreterの測定結果を追記

★2020/01/09 追記
 CP/M-68KのCBASIC(Compiler)の測定結果を追記。コンパイルエラー対応のため、下記の変更を実施
  「'」 --> 「REM」
  「DEFINT A-Z」 --> comment out
  「END」 --> 「STOP」
 ※コンパイラなのにメチャ遅いですねぇ^^;;

★2019/12/31 修正
 BASICソースのfor文の初期値を0から1への修正に伴いBASIC系の実行時間を修正(なんとMSX BASICがGAME80より高速になった!)


 CP/M-86のMBASICが異様に遅いのが気になりますが、CPUがV20(i8088互換)なので8bitバスであることが一因かもしれません。

 尚、今回のベンチマークで使用したソースは次のとおりです。

ベンチマークソース(GAME言語)
1' quiz solver
1000 A=1,6
1005  / ?=A
1010  B=1,6
1020   C=1,6
1030    D=1,6
1040     E=1,6
1050      F=1,6
1060       !=2000
1070      @=F+1
1080     @=E+1
1090    @=D+1
1100   @=C+1
1110  @=B+1
1120 @=A+1
1130 /"complete!"
1140 #=-1
2000 ;=B+B+F<>E  ]
2010 ;=A+C+E<>12 ]
2020 ;=B+D+F<>9  ]
2030 ;=B+E+B<>9  ]
2040 ;=A+B+D<>12 ]
2050 ;=C+F+F<>E  ]
2060 /"A B C D E F ="
2070 ?(2)=A ?(2)=B ?(2)=C ?(2)=D ?(2)=E ?(2)=F
2080 ]



ベンチマークソース(BASIC)
1 ' quiz solver
1000 DEFINT A-Z
1010 FOR A=1 TO 6
1015  PRINT A
1020  FOR B=1 TO 6
1030   FOR C=1 TO 6
1040    FOR D=1 TO 6
1050     FOR E=1 TO 6
1060      FOR F=1 TO 6
1070       GOSUB 2000
1080      NEXT
1090     NEXT
1100    NEXT
1110   NEXT
1120  NEXT
1130 NEXT
1140 PRINT "complete!"
1150 END
2000 IF B+B+F<>E  THEN RETURN
2010 IF A+C+E<>12 THEN RETURN
2020 IF B+D+F<>9  THEN RETURN
2030 IF B+E+B<>9  THEN RETURN
2040 IF A+B+D<>12 THEN RETURN
2050 IF C+F+F<>E  THEN RETURN
2060 PRINT "A B C D E F =";
2070 PRINT A;B;C;D;E;F
2080 RETURN

★2019/01/08 変更
 終了時のメッセージからスペースを削除し、GAME言語側と合わせた
★2019/12/31 修正
 for文の初期値を0から1に修正
★2020/01/05 変更
 行番号をGAME言語側ソースに合わせた(実行時間計測値は変化無し)


ベンチマークソース(ポケコン[G850]内蔵C言語)
/* quiz solver */

int a,b,c,d,e,f;

Check() {
    if ((b+b+f)!=e)  return;
    if ((a+c+e)!=12) return;
    if ((b+d+f)!=9)  return;
    if ((b+e+b)!=9)  return;
    if ((a+b+d)!=12) return;
    if ((c+f+f)!=e)  return;
    printf( "\nA B C D E F = %d %d %d %d %d %d",a,b,c,d,e,f );
}

main() {
    for (a=1; a<7; a++ ) {
        printf( "\n%d",a );
        for ( b=1; b<7; b++ ) {
            for ( c=1; c<7; c++ ) {
                for ( d=1; d<7; d++ ) {
                    for ( e=1; e<7; e++ ) {
                        for ( f=1; f<7; f++ ) {
                            Check();
                        }
                    }
                }
            }
        }
    }
    printf( "\ncomplete!" );
}

★2020/01/18 追加


ベンチマークソース(picle)
# quiz solver

var a,b,c,d,e,f;

proc Check() {
    if ((b+b+f)=e) {
        if ((a+c+e)=12) {
            if ((b+d+f)=9) {
                if ((b+e+b)=9) {
                    if ((a+b+d)=12) {
                        if ((c+f+f)=e) {
                            PrnStr_( "\nA B C D E F =" );
                            PrnDecF_( a, 2 );
                            PrnDecF_( b, 2 );
                            PrnDecF_( c, 2 );
                            PrnDecF_( d, 2 );
                            PrnDecF_( e, 2 );
                            PrnDecF_( f, 2 );
                        }
                    }
                }
            }
        }
    }
}

proc main() {
    for (a=1; a<7; a=a+1 ) {
        PrnStr_( "\n" );
        PrnDec_( a );
        for ( b=1; b<7; b=b+1 ) {
            for ( c=1; c<7; c=c+1 ) {
                for ( d=1; d<7; d=d+1 ) {
                    for ( e=1; e<7; e=e+1 ) {
                        for ( f=1; f<7; f=f+1 ) {
                            Check();
                        }
                    }
                }
            }
        }
    }
    PrnStr_( "\ncomplete!" );
}

★2019/12/31 修正
 for文の初期値を0から1に修正

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

レトロマイコン86ボードの構想(その18)asciiartの高速化 [8086]

 V20(8088互換)を使った自作ボードで動作しているCP/M-86上でMBASICを使ってasciiartを動かしてみると3分18秒2分43秒(V20は8MHzで動作)で、Z-80でのASCIIARTの実行速度と比べてそれほど速いという感じはありませんでした(FPUを付ければ速くなるのだろうけど)

★2019/12/21 asciiart実行時間を修正(3分18秒はCP/M-80エミュでの時間でした^^;)

 コンパイルすることである程度は高速化できるでしょうがどれだけ高速になるかはコンパイラに依存する部分が多々あります。
 近年のコンパイラではコンパイル時の最適化として定数畳み込みループ展開等の手法により、例えば最適化の結果、1~10の総和を求めるループ処理自体が単なる定数値になってしまうケースもあります。

 それならば・・・と言うことでハンド最適化してみました(うそ)。
 まず、asciiartの元ソースは下記でマンデルブロ集合での発散までの回数により表示コードを決定しています。

asciiart BASIC ソース
10 FOR Y=-12 TO 12
20 FOR X=-39 TO 39
30 CA=X*.0458
40 CB= Y*.08333
50 A=CA
60 B=CB
70 FOR I=0 TO 15
80 T=A*A-B*B+CA
90 B=2*A*B+CB
100 A=T
110 IF (A*A+B*B)>4 THEN GOTO 200
120 NEXT I
130 PRINT " ";
140 GOTO 210
200 IF I>9 THEN I=I+7
205 PRINT CHR$(48+I);
210 NEXT X
220 PRINT
230 NEXT Y


 定数畳み込みとループ展開を手動で適用した結果、事前に計算できる結果を埋め込むことでV20の8MHz動作でasciiartの実行時間が33秒になりましたww

 Twitterにポストした動画を貼っておきます。



 種明かしは・・・

asciiart ニセ高速化BASIC ソース
10 DIM D$(20)
20 IDX=-1
30  IDX=IDX+1
40  READ D$(IDX)
50  IF D$(IDX)<>"" THEN 30
60 IDX=IDX-1
70 ST=0:EN=IDX:STP=1:GOSUB 500
80 ST=IDX-1:EN=0:STP=-1:GOSUB 500
90 END
500 FOR I=ST TO EN STEP STP
510  DSP$=D$(I):GOSUB 600
520 NEXT I
530 RETURN
600 L=LEN(DSP$)
610 FOR J=1 TO L
620  FOR T=0 TO ((L/2-ABS(J-L/2))/20)^5:NEXT T
630  PRINT MID$(DSP$,J,1);
640 NEXT J
650 PRINT
660 RETURN
1000 DATA "000000011111111111111111122222233347E7AB322222111100000000000000000000000000000"
1010 DATA "000001111111111111111122222222333557BF75433222211111000000000000000000000000000"
1020 DATA "000111111111111111112222222233445C      643332222111110000000000000000000000000"
1030 DATA "011111111111111111222222233444556C      654433332211111100000000000000000000000"
1040 DATA "11111111111111112222233346 D978 BCF    DF9 6556F4221111110000000000000000000000"
1050 DATA "111111111111122223333334469                 D   6322111111000000000000000000000"
1060 DATA "1111111111222333333334457DB                    85332111111100000000000000000000"
1070 DATA "11111122234B744444455556A                      96532211111110000000000000000000"
1080 DATA "122222233347BAA7AB776679                         A32211111110000000000000000000"
1090 DATA "2222233334567        9A                         A532221111111000000000000000000"
1100 DATA "222333346679                                    9432221111111000000000000000000"
1110 DATA "234445568  F                                   B5432221111111000000000000000000"
1120 DATA "                                              864332221111111000000000000000000"
1130 DATA ""



★追記 2023/01/24
 「GAME言語での ASCIIART の高速化」の記事にアセンブラで書いた固定小数点を使い、asciiartを実際に高速化した内容を書きました。


[TOP] [ 前へ ] 連載記事 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

MSX-DOSに自作スクリーンエディタ移植 [MSX]

 MSX-DOSはCP/M-80のDOSコールサービスに対応しているのでCP/M-80用の多くのソフトが動作します。
 試しに「3チップ構成Pic24CPMマイコン(その7)GAMEコンパイラ」の記事で書いたGAME言語で試してみたところ、インタプリタ及びコンパイラが問題なく動作しました。

 実機のMSXマシンが無いので動作環境としてはWebMSXを使わせていただきました。
※WebMSX環境ではALT+V操作でコピペ可能です。



 GAME言語を使ってMSX-DOSのメモリを確認した結果、MSX-DOSではRST28を使っていないようでした。

MSX-DOSのGAME言語によるメモリダンプ


 CP/M-80用ディバッガのZSIDで使っているRST38をRST28に変更することでMSX-DOS上で動作しました。
 ZSIDはダンプ表示1行化のパッチと「3チップ構成Pic24CPMマイコン(その4)ZSIDで小文字のシンボルを使う方法その2」の記事で書いた小文字シンボル対応のパッチを入れ、コマンド名と表示名をZSIDM(MSX用なので'M'を追加)にしました。

MSX-DOS上で動作中のZSID


 また、CP/M-80用のHI-TECH Cを試してみたところ問題なく動作しました。
 注意点として、Bドライブに入れましたがBドライブもbootableにしないと動作後にMSX-DOSのコマンド入力状態に戻れなくなります。

MSX-DOS上で動作中のHI-TECHC


 CP/M-68K用に開発し、CP/M-80にも移植した自作スクリーンエディタ(sked)をMSX-DOSに移植を試みました。
 MSX-DOSのエスケープシーケンスについてはMSX Datapack wiki化計画14章 画面制御コードを参照させていただきました。

 MSX-DOSには反転表示や色付き等に表示文字属性を変更するエスケープシーケンスが無いのでステータス行の区別が付きづらいため、25行目をステータス行に固定し、ファイル内容は24行表示にしてみました。

 また、skedでは改ページ(^L)等の制御コードを色付きで表示していましたが、色付きができないので色なしで表示するようにしています。

 画面モードは80文字x25行を想定していますのでMSX-DOSの「mode 80」のコマンドで画面モードを変更してから起動しています。

MSX-DOS上でのsked


 MSX-DOS用のskedは下記からダウンロードできます。商用利用以外であれば自由に使用可能です。

 また、MSX-DOSでも動作するzsidも置いておきます。


nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー