マイクロアーキテクチャ
マイクロアーキテクチャ(microarchitecture、短縮形で μarch とも)とは、用語の生まれた当初としてはマイクロプログラム方式におけるコンピュータ・アーキテクチャという意味であった。内容は実質的には変わらないが、マイクロプログラム方式をとらないプロセッサも増えた現在では、命令セットアーキテクチャより下位の、実装におけるアーキテクチャ、を指してそう呼んでいる。
具体的にはCPU、DSPなどのハードウェアの動作を完全に記述できるような電子回路の設計や実装を指す。学術的用語には「コンピュータ構成」もあるが、プロセッサ業界ではマイクロアーキテクチャという用語がよく使われる。
マイクロアーキテクチャと命令セットアーキテクチャは共にコンピュータ設計の一部である。インテルは命令セットを「アーキテクチャ」、各マイクロプロセッサの設計を「マイクロアーキテクチャ」と呼ぶ場合が多い(例:Intel 64 アーキテクチャ、Skylakeマイクロアーキテクチャ)。
1950年代から1970年代にかけて作られた多くのコンピューターはコンピューターの命令列をデコードし実行するための制御ロジックをマイクロプログラム方式によって実現していた。マイクロプログラムのワード内のビットは、実際に計算を行うユニットを制御する電気信号であった。この時代、マイクロアーキテクチャという用語はマイクロプログラムのワードによって制御されるユニットについて記述するために用いられた。
マイクロアーキテクチャとコンピュータの命令セットアーキテクチャははっきり区別される。命令セットアーキテクチャは機械語(アセンブリ言語)プログラマから見たコンピュータシステムの抽象的なイメージであり、命令セット、メモリアドレス指定のモードや、レジスタ、アドレスやデータのフォーマットなどを含むものである。コンピュータ構成とはISAよりももっと低いレベルで具体的にシステムを記述したものである。
コンピュータの構成は、システムを形作る要素と、アーキテクチャの仕様を実現するためにそれらがどのように接続され、相互作用するかを示す
。
異なるマシンが同じ命令セットアーキテクチャをもつ場合もあり、すなわち同じプログラムを実行可能であるが、異なるマイクロアーキテクチャを持つ場合がある。こうした異なるマイクロアーキテクチャは(半導体製造技術の進歩とともに)新しい世代のプロセッサが以前の世代に較べ高い性能レベルを発揮するといったことを可能にしている。理論的には、ひとつのマイクロアーキテクチャは(特にそれがマイクロコードを含んでいれば)、異なった2つの制御記憶をプログラムすることで2つの異なる命令セットを実現するために用いることができる。
マシンのマイクロアーキテクチャは通常、マシンのレジスタ、バス、機能ブロックの接続を示すブロック図で表現される。図にはいくつもの実行ユニット(たとえば浮動小数点、整数、分岐予測、単一命令による複数データ演算(SIMDなど)や、パイプラインの構造(たとえば簡単なものでは命令フェッチ、デコード、割り当て、実行などのステージを含むかもしれない)、キャッシュメモリの設計(レベル1、レベル2インターフェイス)、周辺機器のサポートなどが含まれる。
実際の物理的な回路のレイアウトや、ハードウェアの構造、パッケージ、そのほか物理的な詳細はマイクロアーキテクチャの実装と呼ばれる。2つのマシンは同じマイクロアーキテクチャを持つ可能性があり、すなわち同じブロック図で表現されるが、異なったハードウェア実装である可能性がある。
パイプライン処理は、現代的なマイクロアーキテクチャで最も使われているデータ処理方法である。この手法はほとんどの近代的なマイクロプロセッサ、マイクロコントローラ、DSPに用いられている。パイプライン設計は複数の重複した実行処理ができ、あたかも工場の組み立てラインのようにふるまう。マイクロアーキテクチャ設計におけるパイプライン処理にはいくつかの基本的なステージがある。ステージにはフェッチ、デコード、実行、そして書き出しなどがあり、それ以外の、たとえばメモリアクセスなどのステージを含むアーキテクチャもある。パイプラインの設計は、マイクロアークテクチャ設計で行う中心的な仕事の一つである。
実行ユニットもマイクロアークテクチャには欠かせないものである。実行処理ユニットには演算論理装置 (ALU)、浮動小数点ユニット (FPU)、ロード/ストアユニット、分岐予想ユニット、複数命令を処理するSIMDからなる。これらのユニットがプロセッサの制御や演算を行う。実行ユニット数の選択、それらの処理時間(レイテンシ)と処理能力(スループット)は、マイクロアーキテクチャ設計の作業のうちで中心的なものである。サイズ、レイテンシとスループットとシステムのメモリへの接続も、マイクロアーキテクチャ的な設計上の決定事項である。
システムレベルの設計事項のうち、たとえばメモリコントローラなどの周辺回路を含むかどうか、といったこともマイクロアーキテクチャ設計プロセスの一部と考えられている。これにはパフォーマンスや接続方法についての選択も含まれる。
アーキテクチャ設計とは異なり、特定のパフォーマンスレベルを目指す際、マイクロアーキテクチャ設計では、制約条件により綿密に注意が払われる。マイクロアークテクチャの設計上の決定事項は直結的にシステムに影響するため、以下のような問題に注意を払わなければならない。
試験をする方法、能力
一般的に全てのCPUは、シングルチップでもマルチチップのマイクロプロセッサでも、プログラムを走らせるとき次のような段階的な演算をする。
一見簡単に見える一つながり処理の連続を複雑なものにしているのは、メインメモリとハードディスクなど不揮発性記憶装置(プログラムの命令とデータが保存される)などで形成される階層的な記憶装置が、常にプロセッサ本体より低速であるという事実である。ステップ2はしばしばコンピュータのバスからデータが到着する際に(CPUの世界では)長大な遅延を発生させる。こうした遅延を可能な限り回避できるような設計のために、膨大な量の研究結果が費やされている。長い間、一つの中心的な目標は、複数の命令を並列に実行させ、実効的なプログラムの実行速度を向上させることであった。こうした努力により複雑な論理回路や回路構造が導入された。当初はそのような手法は、必要な回路の規模から高価なメインフレームやスーパーコンピュータにのみ適用可能であった。半導体生産技術が進歩するにつれ、こうした手法が1つの半導体のチップにより多く搭載できるようになった。
CPUの記事に、CPUの処理の基本についてより詳細な議論がある。
History of general purpose CPUs の記事に、CPU発展の歴史についてより詳細な議論がある。
以下は、現代的なCPUに一般的なマイクロアーキテクチャ技術についての調査である。
どの命令セットアーキテクチャを用いるかという選択は、高性能の装置を実現する上での複雑さに大きく影響する。長い年月をかけて、コンピュータのアーキテクトたちは命令セットを簡潔なものにするよう努力してきた。これによって設計者たちが命令セットの自体の複雑さに注力せず、性能を向上させる機能に労力と時間を費やすことができ、高い性能の実現が可能となった。一方で、1970年代の8086に始まるx86の命令セットが、32ビット(IA-32)、64ビット(x64)と拡張を重ねつつ2020年代にも有力な命令セットとして存続しているように、過去との互換性を重視する例も存在する。
命令セットの設計は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より小さいので、こちらの処理を開始」のようにして問題ない。予測の結果が正しければ、かなりの時間が節約できる。近代的な設計はさらに複雑な予測機構を持っており、過去の分岐の結果を監視して未来の分岐方向をかなりの精度で予測する。
コンピュータのアーキテクトたちは、CPUの動作周波数とDRAMのアクセス時間との乖離に悩まされてきた。1つのプログラム内の命令レベルの並列化を利用した手法はいずれも、メインメモリからデータをフェッチする場合には長いストールを発生させる可能性がある。さらに、高度な命令レベル並列化のための膨大な数のトランジスタと高い動作周波数により発生する熱は、もはや安価に冷却できるレベルではなくなった。こうした理由により、新しい世代のコンピュータは、1つのプログラムやスレッドの範囲を超えたより高い次元の並列化手法を用い始めた。
このトレンドは「スループットコンピューティング」としても知られる。この考え方は、もともとはメインフレームの市場でオンライントランザクション処理が1トランザクションの速度ではなく、膨大な数のトランザクションを処理できる能力を強調したことに由来する。ネットワークのルーティングやWebサーバなどのこの10年で急速に増加したトランザクション的なアプリケーションに対して、コンピュータ業界は再び容量とスループットの問題を強調してきている。
並列性を実現する方法の一つはマルチプロセッシング、つまり複数のCPUを搭載したシステムを用いることである。かつてはハイエンドのメインフレームやスーパーコンピュータのためのものであったが、小規模の2-8個のマイクロプロセッサを搭載したサーバはスモールビジネスの市場で一般的になっていた。大企業では、大規模(16-256個)のものが一般的である。さらに複数のCPUを搭載したパーソナルコンピュータが1990年代に登場した。
半導体技術の進歩によってもたらされる、さらなるトランジスタサイズの減少はさらに進み、複数のCPUが同じシリコンチップ上に実装されたマルチコアCPUが登場している。はじめは組み込み市場をターゲットとし、シンプルで小さなCPUのみ1つのシリコン上に実装可能であった。2005年までに、半導体技術の進歩によりハイエンドのデスクトップCPUを二つ搭載した CMPチップを大量生産することが可能となった。サンマイクロシステムズの UltraSPARC T1 のように、単純な(スカラー、インオーダーの)設計を踏襲し、1つのシリコンにより多くのプロセッサを詰め込む事を選択したものもある。
また、最近よく用いられるようになった技術としてマルチスレッディングがある。マルチスレッディングでは、プロセッサが低速なシステムのメモリからデータをフェッチする際、データの到着のためにストールする代わりに、プロセッサは実行可能な別のプログラムあるいはスレッドに切り替えを行う。これは特定のプログラムやスレッドの動作を高速化するものではないが、CPUのアイドル時間を減少させることで全体的なシステムのスループットを向上させる。
概念的には、マルチスレッディングはオペレーティングシステムレベルのコンテキストスイッチと等価である。違いは、マルチスレッド化されたCPUが通常のコンテキストスイッチが必要とする数百から数千のCPUサイクルを1サイクルで行ってしまうという点である。これはCPUの状態ハードウェア(レジスタファイルやプログラムカウンタなど)をアクティブなスレッドごとに持つことにより実現される。
さらなる改善方法として、同時マルチスレッディングがある。この技術は、スーパースケーラCPUに異なるプログラム(スレッド)の命令を同じCPUサイクルで複数実行させるものである。
History of general purpose CPUsの記事に、CPUの設計に影響を与えている研究分野のトピックが述べられている。