2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GMC-4 / ORANGE-4Advent Calendar 2022

Day 2

【GMC-4】命令の実行速度を調べる

Posted at

学研の4ビットマイコンGMC-4の命令の実行速度が気になったので調べてみた。
ついでに互換機やシミュレータについても調べてみた。

測定対象

今回は、以下の5種類について実験を行った。

シミュレータの実行環境は以下である。

Windows 10 Home 21H2 (64ビット)
Intel(R) Core(TM) i7-9750H CPU @2.60GHz 2.59GHz
RAM 16.0GB

測定方法

以下のプログラムにより測定を行った。
なお、このプログラムはMikeAssemblerによるアセンブルが可能である。

target gmc4

	TIA 1
	TIY 3
INIT_ONE_LOOP:
	AM
	AIY -1
	JUMP INIT_ONE_LOOP
INPUT_WAIT:
	KA
	JUMP INPUT_WAIT
	CY
	TIA 0
	JUMP INIT_START
INIT_LOOP:
	AM
INIT_START:
	AIY -1
	JUMP INIT_LOOP

	CAL SHTS
MAIN_LOOP:
	; 実行時間を計る命令を追加する場合、ここに入れる
	; ループのカウントを行う
	TIY 0
	MA
	AIA -1
	AM
	CIA 0
	JUMP MAIN_LOOP
	TIY 1
	MA
	AIA -1
	AM
	CIA 0
	JUMP MAIN_LOOP
	TIY 2
	MA
	AIA -1
	AM
	CIA 0
	JUMP MAIN_LOOP
	TIY 3
	MA
	AIA -1
	AM
	CIA 0
	JUMP MAIN_LOOP

	CAL SHTS
END:
	JUMP END

以下がこのプログラムの機械語表現である。

  | 0 1 2 3  4 5 6 7  8 9 A B  C D E F
--+-----------------------------------
0 | 8 1 A 3  4 B F F  0 4 0 F  0 A 3 8
1 | 0 F 1 5  4 B F F  1 4 E 9  A 0 5 9
2 | F 4 C 0  F 1 C A  1 5 9 F  4 C 0 F
3 | 1 C A 2  5 9 F 4  C 0 F 1  C A 3 5
4 | 9 F 4 C  0 F 1 C  E 9 F 4  A

まず、負荷量の設定を行う。
今回のプログラムでは、最大4重のループを用いる。
ループ回数を決めるカウンタをとりあえず全て1 (1回実行する) に初期化し、
キー入力された個数のカウンタを0 (16回実行する) に書き換える。
入力は0~4が有効である。

キー入力を行うと、ループ処理が実行される。
各ループは以下のブロックで表現され、同じ構造のブロックが4個連なっている。

	TIY (0-3)       ; ループカウンタを選択する
	MA              ; ループカウンタをAレジスタに読み出す
	AIA -1          ; ループカウンタをデクリメントする
	AM              ; ループカウンタを保存する
	CIA 0           ; ループカウンタが0かをチェックする
	JUMP MAIN_LOOP  ; ループカウンタが0でなければ、ループを続行する

今回はこのブロックを何回実行するかを計算し、それに基づいて1秒あたりの命令実行数を計算することにした。
1命令の実行時間は命令の種類や実行結果(ジャンプするかどうかなど)によって変わることが予想されるが、簡単のため今回は無視することにした。

さらに、ループ処理の前後で CAL SHTS 命令により音を鳴らすようにした。
これらの音を録音し、最初の音が鳴り始めてから2番目の音が鳴り始めるまでの時間を調べることにより、命令の実行時間を計測することにした。
この時間には、ループ処理にかかる時間に加え、CAL SHTS 命令1回分の実行時間も含まれる。
そこで、ループの回数を変えて時間を測定し、連立方程式を解くことで、CAL SHTS命令の実行時間とループ処理の実行時間に分けることにした。

  • 1種類目におけるブロックの実行回数を $n_1$
  • 1種類目の実行時間を $t_1$
  • 2種類目におけるブロックの実行回数を $n_2$
  • 2種類目の実行時間を $t_2$
  • CAL SHTS 命令の実行時間を $s$
  • ブロック1回あたりの実行時間を $b$

とおくと $s + n_1 b = t_1, s + n_2 b = t_2$ と表せるので、これを解けば $s, b$ の値が求まる。

ブロックの実行回数

負荷設定0

各ブロックを1回ずつ実行するので、実行回数は4回である。

負荷設定1

  • 最初のブロックを16回実行する
  • 2~4番目のブロックを1回ずつ実行する

よって、実行回数は19回である。

負荷設定2

  • 2番目のブロックのループにより、以下を16回実行する
    • 最初のブロックを16回実行する
    • 2番目のブロックを1回実行する
  • 3番目・4番目のブロックを1回ずつ実行する

よって、実行回数は$(16+1)\times 16 + 1 + 1 = 274$回である。

負荷設定3

  • 3番目のブロックのループにより、以下を16回実行する
    • 2番目のブロックのループにより、以下を16回実行する
      • 最初のブロックを16回実行する
      • 2番目のブロックを1回実行する
    • 3番目のブロックを1回実行する
  • 4番目のブロックを1回実行する

よって、実行回数は$((16+1)\times 16 + 1)\times 16 + 1 = 4369$回である。

負荷設定4

  • 4番目のブロックのループにより、以下を16回実行する
    • 3番目のブロックのループにより、以下を16回実行する
      • 2番目のブロックのループにより、以下を16回実行する
        • 最初のブロックを16回実行する
        • 2番目のブロックを1回実行する
      • 3番目のブロックを1回実行する
    • 4番目のブロックを1回実行する

よって、実行回数は$(((16+1)\times 16 + 1)\times 16 + 1)\times 16 = 69904$回である。

測定結果

実行時間の測定結果は、以下のようになった。
なお、本来は複数回測定して平均を取るべきだろうが、今回は簡単のため1回のみ測定した。

実行環境 負荷設定0 負荷設定1 負荷設定2 負荷設定3 負荷設定4
FX-マイコン - 0.492秒 2.826秒 - -
GMC-4 - - 0.615秒 5.236秒 -
ORANGE-4 - - - 0.514秒 2.970秒
FX-マイコン シミュレータ - 2.315秒 27.822秒 - -
GMC-4 シミュレータ - - - 0.320秒 0.340秒

この測定結果から実行時間を求め、1秒あたりの命令実行数に換算すると、以下のようになった。
1ブロックが6命令からなることを利用している。

実行環境 CAL SHTS命令の実行時間 1ブロックあたりの実行時間 1秒あたりの命令実行数
FX-マイコン 0.318秒 0.00915秒 656命令
GMC-4 0.306秒 0.00113秒 5317命令
ORANGE-4 0.350秒 0.0000375秒 160102命令
FX-マイコン シミュレータ 0.414秒 0.100秒 60命令
GMC-4 シミュレータ 0.319秒 0.000000305秒 19660500命令

すなわち、

  • GMC-4は1秒あたり約5k命令実行できる
  • FX-マイコンはGMC-4の約8分の1の実行速度
  • ORANGE-4はGMC-4の約30倍速い
  • GMC-4 シミュレータはGMC-4の約3700倍速い
  • FX-マイコン シミュレータはGMC-4の約90分の1の実行速度

という結果になった。

7セグメントLEDを点灯させての測定

FX-マイコンは7セグメントLEDを点灯させると実行速度が落ちるようだったので、
先程のプログラムの最初の TIA 1 の次に AO を挿入し、
7セグメントLEDを点灯させるようにしたプログラムで再度測定を行ってみた。
以下がこの変更を行ったプログラムの機械語表現である。

  | 0 1 2 3  4 5 6 7  8 9 A B  C D E F
--+-----------------------------------
0 | 8 1 1 A  3 4 B F  F 0 5 0  F 0 B 3
1 | 8 0 F 1  6 4 B F  F 1 5 E  9 A 0 5
2 | 9 F 4 C  0 F 1 D  A 1 5 9  F 4 C 0
3 | F 1 D A  2 5 9 F  4 C 0 F  1 D A 3
4 | 5 9 F 4  C 0 F 1  D E 9 F  4 B

同様に1回ずつ測定を行った結果、以下の測定結果が得られた。

実行環境 負荷設定0 負荷設定1 負荷設定2 負荷設定3 負荷設定4
FX-マイコン - 0.565秒 3.845秒 - -
GMC-4 - - 0.614秒 5.237秒 -
ORANGE-4 - - - 0.471秒 3.080秒
FX-マイコン シミュレータ - 2.306秒 27.908秒 - -
GMC-4 シミュレータ - - - 0.329秒 0.350秒

この測定結果から実行時間を求め、1秒あたりの命令実行数に換算すると、以下のようになった。
1ブロックが6命令からなることを利用している。

実行環境 CAL SHTS命令の実行時間 1ブロックあたりの実行時間 1秒あたりの命令実行数 実行速度(消灯時比)
FX-マイコン 0.321秒 0.0129秒 466命令 71.2%
GMC-4 0.305秒 0.00113秒 5315命令 100.0%
ORANGE-4 0.297秒 0.0000398秒 150713命令 94.1%
FX-マイコン シミュレータ 0.398秒 0.100秒 60命令 99.6%
GMC-4 シミュレータ 0.328秒 0.000000320秒 18724286命令 95.2%
  • FX-マイコンでは、約30%という顕著な速度の低下がみられた。
  • GMC-4では、速度はほとんど変わらなかった。
  • ORANGE-4では、5%程度の速度の低下がみられた。
  • FX-マイコン シミュレータでは、速度はほとんど変わらなかった。
    • 「動作をできるだけ忠実に再現しました」と主張しているが、ここは再現できなかったようだ。(そもそも遅いし)
  • GMC-4 シミュレータでは、5%程度の速度の低下がみられた。
    • 測定された時間が短いため、実行時の他のタスクの違いなど誤差の可能性も考えられる。

ORANGE-4における7セグメントLEDの点灯による実行速度の低下を確かめるため、
以下のプログラムでPORT1へ0/1の出力を繰り返し、オシロスコープ FNIRSI-1013D で周波数を測定した。

target orange4

	ldyi 1
	ldi 0
	ioctrl
loop:
	ldi 1
	out
	ldi 0
	out
	jmpf loop

以下がこのプログラムの機械語表現である。

  | 0 1 2 3  4 5 6 7  8 9 A B  C D E F
--+-----------------------------------
0 | A 1 8 0  F 7 0 8  1 F 7 1  8 0 F 7
1 | 1 F 0 7

以下が測定結果である。

ORANGE-4 によるポートの上下 (7セグメントLED消灯)

さらに、最初の ldi 0 の次に outn 命令を追加し、
7セグメントLEDを点灯させる以下のプログラム(機械語表現)について、同様に測定した。

  | 0 1 2 3  4 5 6 7  8 9 A B  C D E F
--+-----------------------------------
0 | A 1 8 0  1 F 7 0  8 1 F 7  1 8 0 F
1 | 7 1 F 0  8

以下が測定結果である。

ORANGE-4 によるポートの上下 (7セグメントLED点灯)

7セグメントLED消灯時は28.3kHzであるのに対し、7セグメントLED点灯時は27.1kHzとなっており、95.8%の実行速度となっている。
ORANGE-4では7セグメントLEDを点灯させると約5%速度が低下することを、別の形でも確かめることができた。

GMC-4 シミュレータの追加検証

GMC-4 シミュレータは他と比べて非常に高速で動作し、負荷設定4でも1秒未満で実行できた。
そこで、プログラムの入力部分を削ることで容量を確保し、負荷設定5および負荷設定6相当で検証を行った。

以下が検証用のプログラムである。(GMC-4 シミュレータ上で直接アセンブルできる)

	; 7セグメントLEDを点灯させる際、コメントアウトを解除する
	;AO
	CAL SHTS
MAIN_LOOP:
	; ループのカウントを行う
	TIY 0
	MA
	AIA 0xF
	AM
	CIA 0
	JUMP MAIN_LOOP
	TIY 1
	MA
	AIA 0xF
	AM
	CIA 0
	JUMP MAIN_LOOP
	TIY 2
	MA
	AIA 0xF
	AM
	CIA 0
	JUMP MAIN_LOOP
	TIY 3
	MA
	AIA 0xF
	AM
	CIA 0
	JUMP MAIN_LOOP
	TIY 4
	MA
	AIA 0xF
	AM
	CIA 0
	JUMP MAIN_LOOP
	; 負荷設定6にする際、コメントアウトを解除する
	;TIY 5
	;MA
	;AIA 0xF
	;AM
	;CIA 0
	;JUMP MAIN_LOOP

	CAL SHTS
END:
	JUMP END
	
	ORG 0x50
	DN 0, 0, 0, 0, 0, 0, 0, 0

1回ずつ測定を行った結果、以下の測定結果が得られた。

実行環境 負荷設定5 負荷設定6
GMC-4 シミュレータ (7セグメントLED消灯) 0.680秒 6.180秒
GMC-4 シミュレータ (7セグメントLED点灯) 0.690秒 6.180秒

また、負荷設定5の実行回数は、
「負荷設定4の処理と最後のブロック」を16回実行するので $(69904 + 1) \times 16 = 1118480$ 回
負荷設定6の実行回数は、
「負荷設定5の処理と最後のブロック」を16回実行するので $(1118480 + 1) \times 16 = 17895696$ 回
となる。

この測定結果から実行時間を求め、1秒あたりの命令実行数に換算すると、以下のようになった。
1ブロックが6命令からなることを利用している。

実行環境 CAL SHTS命令の実行時間 1ブロックあたりの実行時間 1秒あたりの命令実行数
GMC-4 シミュレータ
(7セグメントLED消灯)
0.313秒 0.000000328秒 18302417命令
GMC-4 シミュレータ
(7セグメントLED点灯)
0.324秒 0.000000327秒 18335755命令

7セグメントLED点灯時の実行速度は7セグメントLED消灯時の100.2%となり、ほとんど差がないという結果になった。
負荷設定4までの実験と比べてある程度の実行時間を確保できており、より信頼できると考えられる。

結論

今回の実験では、各実行環境の実行速度は以下のようになった。
なお、実行にかかる時間は命令や条件によって変わる可能性がある。

実行環境 実行速度
(7セグメントLED消灯時)
7セグメントLED点灯による
実行速度の低下
FX-マイコン 656命令/s 約30%
GMC-4 5.31k命令/s 見られず
ORANGE-4 160k命令/s 約5%
FX-マイコン シミュレータ 60.0命令/s 見られず
GMC-4 シミュレータ 18.3M命令/s 見られず

参考になれば幸いである。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?