ぱたへね

はてなダイアリーはrustの色分けができないのでこっちに来た

Instruction Set Styles

a = b +c; を、Accumulator、Memory-memory、Stack、Load-storeの命令セットスタイルでどうなるか考えて考えようという問題。a,b,cはメモリ上の変数です。Load-storeの命令スタイルは、教科書にでてくるMIPSのスタイルです。

Accumulator

Accumulatorの場合は3命令で実行できます。

load AddressB  # bをアキュムレータにロード
add AddressC   # cとアキュムレータに入っているbを足して、結果をアキュムレータに入れる
store AddressA # アキュムレータをaにストア

アキュムレータが1個しか無い場合は、プログラムを実行するのに命令の数が増えてしまいます。

Memory-memory

Memory-memoryの命令セットを使う場合、オペランドにメモリを直接指定できるため、1命令で実行できます。

add AddressA AddressB AddressC

Stack

Stack型のプロセッサというのは、結局スタックのトップをAccumulatorとして使っているので、Accumulatorと似たような命令になります。

push AddressB  # bをスタックにpush
push AddressA  # aをスタックにpush
add            # 加算
pop AddressA   # 加算の結果をpopしてaへ

各スタイルの比較

この条件で比較してみます。

  • オペコードは1バイト
  • メモリアドレスは2バイト
  • データオペランドは4バイト
  • 全ての命令はバイトの長さの整数値
  • 最適化無し
style instructions code bytes data bytes
Accumulator 3 3+3+3 4+4+4
Memory-memory 1 7 12
Stack 4 3+3+1+3 4+4+0+4
Load-Store 4 4+4+3+4 4+4+0+4

命令数に関しては、Memory-memoryが1命令なので一番小さくなります。コードのバイト数に関しても、Memory-memoryが一番小さくなります。a = b + c の場合、データ数はa,b,cの12バイトになるのは全てのスタイルで共通です。

これだけ見るとMemory-memoryが一番良いように思えるのですが、実際にはMemoryへのアクセスは内部レジスタよりも何桁も遅いため、トータルの処理速度は必ずしも速くなりません。a = b + c + d;のような場合、中間の計算結果もメモリに書き戻して、再度読み込むので処理自体は遅くなります。

Load-Storeスタイルに比べて、AccumulatorやStackは若干コードサイズが小さくなります。これは、add $2, $3, $4の命令からオペランドが省略できるというだけの話で、コードサイズの代わりに直交性を失っています。結果的には同じ計算をするにも命令数が増えてしまい、トータルの命令サイズではむしろ大きくなります。言語の組み込みの型で大半の処理が終わる場合は良いのですが、構造体の定義をしようとしただけで少し無理をするコードが必要になります。

AccumulatorやStackのメリットとしては、物理的なレジスタの要求が少ないので、ハードウェアが単純になったり、エミュレーションが楽になったりします。数値計算が多いときや、途中結果をどんどん捨てていっても良い場合は、AccumulatorやStack型でも十分な性能が出せます。PostScriptやHPの電卓でStack型が採用され、今も使われているのはこういった理由が大きいと想像しています。

Accumulatorを使った計算の例(2008/10/24追加)

こちらにAccumulatorを使ったもう少し複雑な例があります。
http://journal.mycom.co.jp/column/architecture/113/index.html

こちらのコラム全体が非常に良くまとまっています。コンピュータアーキテクチャの勉強にお勧めです。
コンピュータアーキテクチャの話