- ISA(命令セット・アーキテクチャ)
- プログラマ・ビジブルって?
- ハードウェア設計
- レジスタファイル
- シーケンシャルなプロセッサ(SEQ)
- 処理ステージの説明
- パイプライン処理
- 効率低下の要因
- パイプライン・ハザードとは?
- 例外処理
- 感想
4章について
この章では、基本的な論理回路の仕組みから始まり、x86-64をベースとしたY86-64の実装を通してプロセッサについて書かれていました。
プロセッサを学ぶことで、コンピュータ・システム全体の働きを深く知ることができます。
以下まとめです。
ISA(命令セット・アーキテクチャ)
プロセッサによって、サポートされている命令とそれらのバイト単位でのエンコーディング方法をまとめた総称のこと。
命令は、1バイト、または複数バイトの列としてエンコードされる。
ISAのモデルはシーケンシャル(逐次的)な命令の実行のように見えるが、プロセッサは並列処理をしている。
プログラマ・ビジブルって?
読み書き可能なステートのことをプログラマ・ビジブルなステートとよぶ。
Y86のステートはx86と似ており、15本のプログラム・レジスタを持っており、それぞれ64ビットのワードを格納する。
それぞれ1ビットからなる3つの条件コードを持っている。
条件コード : 算術論理演算の結果に関する情報を保持するために使われる。
プログラマ・カウンタ(PC) : 現在実行している命令の実行をアドレスを保持する。
ハードウェア設計
ハードウェア設計では、ビット演算や、様々な種類のメモリ素子にビット・データを保持するために電子回路が用いられる。
ディジタル・システム構成の主要3要素
組み合わせ回路(ビット演算)
メモリ素子(ビットデータを保持)
クロック信号(メモリ素子の更新)
論理ゲート
ディジタル回路において、計算を行う基本要素のこと。
AND(&&)
, OR(||)
, NOT(!)
それぞれに対応した記号がある。
ちなみに演算量は1ビット(ワード全体を演算しているわけではないため)
組み合わせ回路とHCLによるブール式
組み合わせ回路 : 論理ゲートを組み合わせたもの。
上記の組み合わせ回路をHCLで書くと以下になる。
bool eq = (a && b) || (!a && !b);
HCLはC言語スタイルの文法なので、直感的ですね。
違う点としては、=
は代入ではなく、式に名前をつけているだけであること。
マルチプレクサ(MUX) : 2つ以上の入力を1つの信号として出力する。
ALU(演算装置) : 制御信号の状態に応じて、算術論理演算を行う。
メモリとクロッキング : 組み合わせ回路は情報を保持できないため、シンプルに入力の変化に対して、結果を出力する。
順序回路 : 状態を持ち、その上で計算を行う。
クロック : 記憶回路にいつ新しい値を反映させるかを決める周期的な信号のこと。
レジスタ : ハードウェアと、マシン語レベルのプログラミングでは異なる意味を持つため「ハードウェア・レジスタ」、「プログラム・レジスタ」と区別される。
レジスタファイル
リード・ポートとライトポートを持つ。
リード・ポートが2つあるマルチポート化されたメモリでは、複数の読み書きが同時に行える。
ちなみに同じレジスタに同時に読み書きを行おうとした場合、リード・ポートの出力は、古い値から新しい値に遷移するという。
シーケンシャルなプロセッサ(SEQ)
各クロック・サイクルにおいて、一つの命令を実行するために必要なすべてのステップが完全に処理される。
サイクル・タイムが非常に長くなり、クロック・レートが低くなるといったデメリットがある。
SEQを開発することで、最終的に効率的なパイプライン・プロセッサ実装へつながるという。
処理ステージの説明
命令の振る舞いは種類ごとに異なるが、すべての命令が一つのシーケンスに従うようにする必要がある。
そのため、各ステージにおける処理の詳細は、命令の種類に応じて違っていても良い。
フェッチ : プログラム・カウンタにある値を、メモリ・アドレスとして用い、命令のデータを読み出す。
デコード : 最大二つのオペランドをレジスタ・ファイルから読み出し、valA と valB の片方あるいは双方の値を得る。
実行 : 演算処理、実効アドレスの計算、スタック・ポインタの移動
メモリ : データをメモリに書き込むか、メモリからデータを読み出す。
ライト・バック : 最大二つまでの結果をレジスタ・ファイルに書き込む。
PCアップデート : PCの内容を次の命令のアドレスに更新する。
nop命令 : 何の処理を行うことなくステージ間を流れる(PCは1インクリメントされる)
halt命令 : プロセッサを停止させるためにプロセッサのステータス・コードをHLTにセットする。
SEQの問題点
遅すぎること。
しかし、1サイクル内にすべてのステージに信号を伝搬させるために遅い必要がある。
これだとハードウェア・ユニットを有効に活用できないので、パイプライン化を導入する。
パイプライン処理
丸亀製麺で一列に並ぶイメージ。
うどんだけが食べたくても、すべてのステージを通過する必要がある。
パイプライン化によるメリットは、レイテンシ(個々の客のサービスに要する時間)は増加する可能性はあるが、スループット(単位時間あたりに提供できる客の数)は向上すること。
丸亀製麺は偉大ですね。
パイプライン化されていない場合
回路(300ps)->レジスタ(20ps) 遅延(320ps) スループット(3.12GIPS) 回路->回路->回路
パイプライン化されている場合
回路A,B,Cの3種類(100ps) レジスタ(20ps) A->レジスタ->B->レジスタ->C->レジスタ 遅延(360ps) スループット(8.33GIPS) A->B->C A->B->C A->B->C
遅延は伸びているが、スループットは向上している。
効率低下の要因
非均一な分割
システムのスループットは最も低速なステージの速度によって制限される。
そのため、計算にかかる速度を均一にすることが重要となる。
1つのステージに時間がかかる例
回路A(50ps) 回路B(150ps) 回路C(100ps) レジスタ(20ps) A->レジスタ->B->レジスタ->C->レジスタ A->BBB->CC A ->BBB->CC A ->BBB->CC #Bの処理が終わらないと進めない
深いパイプライン処理
最新のプロセッサはとても深いパイプライン(15やそれ以上)を使用することで、各ステージの遅延を小さくしている。
パイプライン・ハザードとは?
ハザードには、危険、有害といった意味があります。
つまり、パイプライン・ハザードとは、依存関係により正しい処理ができなくなる危険性のことを指します。
データ依存 : 命令によって計算された結果が後続の命令のためのデータとして使われる場合。
制御依存 : ジャンプ、コール、リターンといった命令の実行時に、ある命令が後続の命令のロケーションを決める場合。
データ・ハザード対策
結果を待つために nop命令を挟む。
そうすることでまだ書き込まれていない状態のレジスタを読んでしまうことを防ぐ。
ストール : ハザードの条件が成立しなくなるまで、命令の進行を待たせること。
バブル : nop命令のようなもの。進行を待たせる。
フォワーディング : 結果の値をパイプライン・ステージから、より早いステージへと渡す技術。
Load/Useデータ・ハザード : メモリから読みだした値を後続の命令が使用する場合に発生する。
制御ハザード対策
フェッチ・ステージで次の命令を確実に決められないときに生じる。
条件分岐で予測ミスした場合に、ミスが見つかるまでの間に次の命令がフェッチされてしまう。
そこで、バブルを利用し、その命令をキャンセルさせて、後続の命令をフェッチすることができる。
例外処理
内部的例外 : halt命令や組み合わせが無効な命令、無効なアドレスへのアクセス
外部的例外 :ユーザがマウスのボタンをクリック、インターフェースが新しいパケットを受信
例外が発生した場合、ステータス・コードを適切にセットし、プロセッサを停止させる。
完全な設計の場合は、プロセッサは例外処理モードに例外ハンドラを起動して処理を続ける。
例外発生から停止までの流れ
命令が例外を生成するとき、例外の原因をステータス・フィールドにセットする。
その例外ステータスは、命令の他の情報と一緒にパイプラインを伝わっていき、ライト・バック・ステージに到達する。
この時点で、例外の発生を検出して実行を停止させる。
実行ステージの浮動小数点演算ユニットを拡張したり、メインのパイプラインとは独立に動作する特別なハードウェア機能ユニットを扱うことで処理を高速にする。
感想
Y86-64の実装から各ステージごとの処理の流れについて、体系的に学ぶことができました。
実はこんな仕組みで動いてたんだなと。全然知らなかったので、普段使っているPCを褒めてあげたいですね。
またパイプライン処理の部分は、読み進めていて面白かったです。
この章は全体的に図で説明されているものが多かったので、理解しやすかった気がしました。