マイクロアーキテクチャ

マイクロアーキテクチャ（英: microarchitecture、短縮形で μarch とも）とは、用語の生まれた当初としてはマイクロプログラム方式におけるコンピュータ・アーキテクチャという意味であった。内容は実質的には変わらないが、マイクロプログラム方式をとらないプロセッサも増えた現在では、命令セットアーキテクチャより下位の、実装におけるアーキテクチャ、を指してそう呼んでいる。
具体的にはCPU、DSPなどのハードウェアの動作を完全に記述できるような電子回路の設計や実装を指す。学術的用語には「コンピュータ構成」もあるが、プロセッサ業界ではマイクロアーキテクチャという用語がよく使われる。
マイクロアーキテクチャと命令コードの設計（命令セットアーキテクチャ、ISA）は、共にコンピュータ設計の一部である。なおインテルの場合は、主に命令セットを「アーキテクチャ」、各マイクロプロセッサの設計（実装）を「マイクロアーキテクチャ」と呼ぶ場合が多い（例：IA-32インテル アーキテクチャ、Coreマイクロアーキテクチャ）。

歴史

1950年代から1970年代にかけて作られた多くのコンピューターはコンピューターの命令列をデコードし実行するための制御ロジックをマイクロプログラム方式によって実現していた。マイクロプログラムのワード内のビットは、実際に計算を行うユニットを制御する電気信号であった。この時代、マイクロアーキテクチャという用語はマイクロプログラムのワードによって制御されるユニットについて記述するために用いられた。

命令セットアーキテクチャとの関係

マイクロアーキテクチャとコンピュータの命令セットアーキテクチャははっきり区別される。命令セットアーキテクチャは機械語（アセンブリ言語）プログラマから見たコンピュータシステムの抽象的なイメージであり、命令セット、メモリアドレス指定のモードや、レジスタ、アドレスやデータのフォーマットなどを含むものである。コンピュータ構成とはISAよりももっと低いレベルで具体的にシステムを記述したものである。
コンピュータの構成は、システムを形作る要素と、アーキテクチャの仕様を実現するためにそれらがどのように接続され、相互作用するかを示す。
異なるマシンが同じ命令セットアーキテクチャをもつ場合もあり、すなわち同じプログラムを実行可能であるが、異なるマイクロアーキテクチャを持つ場合がある。こうした異なるマイクロアーキテクチャは（半導体製造技術の進歩とともに）新しい世代のプロセッサが以前の世代に較べ高い性能レベルを発揮するといったことを可能にしている。理論的には、ひとつのマイクロアーキテクチャは（特にそれがマイクロコードを含んでいれば）、異なった2つの制御記憶をプログラムすることで2つの異なる命令セットを実現するために用いることができる。
マシンのマイクロアーキテクチャは通常、マシンのレジスタ、バス、機能ブロックの接続を示すブロック図で表現される。図にはいくつもの実行ユニット実行ユニットの種類（たとえば浮動小数点、整数、分岐予測、単一命令による複数データ演算（SIMDなど）や、パイプラインの構造（たとえば簡単なものでは命令フェッチ、デコード、割り当て、実行などのステージを含むかもしれない）、キャッシュメモリの設計（レベル1、レベル2インターフェイス）、周辺機器のサポートなどが含まれる。
実際の物理的な回路のレイアウトや、ハードウェアの構造、パッケージ、そのほか物理的な詳細はマイクロアーキテクチャの実装と呼ばれる。2つのマシンは同じマイクロアーキテクチャを持つ可能性があり、すなわち同じブロック図で表現されるが、異なったハードウェア実装である可能性がある。

命令セットの選択

どの命令セットアーキテクチャを用いるかという選択は、高性能の装置を実現する上での複雑さに大きく影響する。長い年月をかけて、コンピュータのアーキテクトたちは命令セットを簡潔なものにするよう努力してきた。これによって設計者たちが命令セットの自体の複雑さに注力せず、性能を向上させる機能に労力と時間を費やすことができ、高い性能の実現が可能となった。
命令セットの設計はCISCからRISC、VLIW、EPICへと進歩してきた。またデータ並列性をうまく扱うためのアーキテクチャとしてSIMDとベクトルプロセッサがある。

パイプライン処理（パイプライン化）

パフォーマンスを向上させるための最も重要な、そしてもっとも強力な手法の一つは命令パイプラインを用いることである。初期のプロセッサの設計では、プロセッサは上記のステップのすべてを次の命令に移る前に実行していた。これでは回路の大部分が上記の各ステップで待機状態になってしまう。たとえば実行やそのほかの段階では命令でコードの回路は待機状態になる。
パイプラインは、一定数の命令がプロセッサ内で同時に動作できるようにすることで性能を向上させる。また同じ簡単な例では、プロセッサは最後の命令が結果が出るのを待っている間に新しい命令をデコード開始する（ステップ1）これにより、最大で4つの命令を同時に「動作状態」におくことができ、見かけ上のプロセッサの速度が4倍になる。どの命令も完了するのに同じ時間がかかるのだが依然4段階のステップがある）、CPUは結果として命令を大幅に早く片付けることができ、より高いクロック速度で動作することができる。
RISCでは各ステージをきれいに分割し、同じ長さの時間、すなわち1サイクルかかるようにすることで、パイプラインをより小さく、より簡単に構築できるようにする。プロセッサは結果として製造ラインのように、命令が片方から来て反対側から出て行くように動作する。複雑さを抑えた伝統的なRISCパイプラインにより、パイプライン化されたコアと命令キャッシュを、CISCであればコアのみしか入らないようなダイに両方搭載できるようになった。これがRISCが高速な理由であった。SPARCやMIPSのような初期の設計では、同クロック・同じ値段の インテル や モトローラ のCISCチップに対してしばしば10倍以上高速に動作した。
パイプラインはRISCの設計に限定したものではまったくない。1986までにVAXの最上位機種 (8800) はかなりパイプライン化された設計で、MIPSとSPARCの最初の商業的な設計にわずかに早かった。今日ではほとんどのCPUがいまや（組み込み用の物ですら）パイプライン化されており、パイプライン化されていないマイクロコードのCPUは面積に制約がある組み込み用プロセッサでしか見られない。VAX 8800から現代の Pentium 4 と Athlon にいたる大規模なCISCマシンはマイクロコードとパイプラインの両方を使って実装されている。パイプラインとキャッシュの進歩が、マイクロアーキテクチャの進歩のうちもっとも重要なもので、プロセッサのパフォーマンスを製造技術の進歩とともに、高いペースでの性能向上の割合を保つことを可能にした。

キャッシュ

チップ製造技術の向上によってダイにより多くの回路を詰め込むことができるようになり、設計者がその使い道を探すようになったのはそれほど昔のことではなかった。もっともありふれた方法はダイにキャッシュをどんどん追加していくことだった。キャッシュは単純に高速なメモリであり、メインメモリと通信するのにかかる「長い」サイクルに対して数サイクルでアクセスすることができる。CPUはキャッシュの読み書きを自動化するキャッシュコントローラを搭載し、データがキャッシュ内に存在すればすぐに読み出すことができ、なければキャッシュコントローラが読み込む間プロセッサはストールする。
1980年代の中盤から後半に、RISCの設計でキャッシュを追加していくことが始まった。たいていは全体で4KBのみであった。この数字は時代を経て増え続け、今や典型的なCPUは約512KBのキャッシュを搭載し、よりパワフルなCPUは、1～2MBあるいは4～8MBさえ搭載し、複数のレベルのメモリ階層が構成されている。一般的にいえば、大容量のキャッシュは高速化につながる。
キャッシュとパイプラインはお互いにとって完璧な組み合わせであった。それまでは、チップ外のメモリのレイテンシより高速に動作するパイプラインを作ってもあまり意味はなかった。オンチップのキャッシュメモリを使用することは、パイプラインがキャッシュのレイテンシ、すなわちより短い時間で動作できることを意味した。これによりプロセッサの動作周波数を、チップ外のメモリの速度の向上よりもかなり早いペースで向上させることができた。

分岐予測

命令レベルの並列化により高い性能を実現する上で障壁となるのが、分岐によるパイプラインのストールとフラッシュである。通常、条件分岐が発生するかどうかは、レジスタの演算結果に依存するためパイプラインの後段にならないと分からない。プロセッサの命令デコーダが条件分岐命令に出会った時点から、問題となるレジスタの値が読み出せるようになるまでの時間、パイプラインは数サイクル停止する可能性がある。平均的には、命令の五分の一は分岐であり、つまり高い頻度でストールが発生する。実際に分岐が行われると事態はより深刻で、パイプラインにあった以降すべての命令を廃棄する必要がある。
分岐予測や投機実行などの手法が分岐によるペナルティを軽減させるために用いられる。分岐予測はハードウェアがある特定の分岐が起こるかどうかを推測する。推測により、プリフェッチ命令はレジスタの読み出しを待たなくてもよくなる。投機実行はこれを大きく発展させたもので、予測された経路のコードを、分岐が発生するかどうかがわかる前に実行してしまうものである。

スーパースカラー

これまで述べてきたような方法を実装すると複雑さやゲート数が増大するのだが、半導体製造技術の向上により、すぐに多くのゲートが搭載できるようになってしまう。
上記に述べた方法では、プロセッサは一度に1つの命令の一部を実行する。もし複数の命令が同時に実行できれば、コンピュータのプログラムはより高速に動作するはずである。これがスーパースカラーの実現するもので、そのためにALUなどの機能ユニットを複数個搭載する。機能ユニットを複数搭載することは、シングルイシューのプロセッサのダイサイズが安定して生産できるダイサイズについていかなくなって初めて意味がある。1980年代の後半までには、スーパースケーラの設計が市場に登場し始めた。
現代的な設計では、ロードユニットを二つ、ストアユニットを1つ（多くの命令はストアする結果がないため）、2つ以上の整数演算ユニットと浮動小数点ユニット、何らかのSIMDユニットがよく見られる。命令発行のロジックはメモリから膨大な命令列を読み込み、その時点でアイドルになっている実行ユニットに引き渡すため複雑さが増大する。処理の結果は最後に集められ、並べ替えられる。

アウトオブオーダー

キャッシュの導入により、ストールの頻度やメモリ階層からのフェッチ待ちの時間を減少させることができるが、ストールを完全に排除できる訳ではない。初期の設計では、キャッシュミスがキャッシュコントローラにプロセッサを停止させ待機させるようになっていた。もちろん、その時点でプログラム内にキャッシュのデータが利用可能な別の命令が存在する可能性がある。アウトオブオーダー実行は、実行可能な命令が、以前の命令がキャッシュ待ちになっている間に（先に）処理できるようにし、すべてがプログラムされた順序で発生したかのように結果を並び替えることを可能にする。

投機実行

命令パイプラインの問題点の一つは、実行が継続できる前に進む方向が完全に決まっていなければならないような類の命令である。具体的には、条件分岐は、どちらの分岐に進むべきかを決定する前に、先行する命令の結果を知る必要がある。たとえば、「xが5より大きければこの処理、そうでなければこの処理」といった命令は、後続の命令をフェッチしてよいかを判断する前に、x の結果を待たなければならない。
簡単な4段パイプラインでは、遅延が最大3サイクルで、依然デコードを実行できる。しかし、クロック速度が向上すると、それにともなってパイプラインの段数が増え、現代のプロセッサでは20ステージ以上に達している。この場合、そうした命令が現れるたびにサイクルの大半CPUが停止してしまう。
解決方法、あるいはその一つは、投機実行、別名分岐予測である。分岐のどちらに進むは、実際には片方に偏っており、単純に処理を進めて 「xはおそらく5より小さいので、こちらの処理を開始」のようにして問題ない。予測の結果が正しければ、かなりの時間が節約できる。近代的な設計はさらに複雑な予測機構を持っており、過去の分岐の結果を監視して未来の分岐方向をかなりの精度で予測する。