スーパースカラ方式

これまでに述べてきたプロセサは、機械語の命令を1サイクルに1つずつ実行するものであり、IPC(Instruction Per Cycle)は1.0を切ることはできない。そこで、さらに性能を向上させるために1サイクルに2つ以上の命令を実行するという方法が考えられた。

話は、少し横道にそれるが、ここまでに説明してきた命令では、

のように、1つの命令は、レジスタに格納された1つのデータを処理するという形式であるが、「CRAY-1」スーパーコンピュータでは、それぞれのレジスタが64個の浮動小数点データを格納し、1つのFADD命令で最大64個のデータを加算するというような命令が作られた。そして、このように複数のデータ列(=ベクトル)を1まとめに処理する命令を「ベクトル命令」と呼び、このような実行方式を「ベクトル実行」と呼ぶ。

なお、当時のテクノロジでは大量のトランジスタを必要とする演算回路は高価であり、64個のデータの加算は、パイプライン構成の1つの演算器で順に処理していた。それでも、1命令ずつ実行するプロセサでは1演算の実行に少なくとも数サイクルを必要とするのに対して、パイプラインによる実行の場合は毎サイクル新しい演算を開始することができるので高性能を実現できるというメリットがあった。

このベクトル実行に対して、各レジスタが1つのデータを格納し、1つの命令で1つのデータを処理する普通の処理方式は「スカラ実行」と呼ばれる。

そして、2つ以上のスカラ命令を並行して実行する方式は、並行して複数の演算が行われるがベクトルデータの処理ではなく、それぞれは異なるスカラデータの演算であるので、「スーパスカラ(Super Scalar)実行」と呼ばれる。

図6.1 スカラとベクトルの概念図

一般に、スカラプロセサは、独立した整数演算器と浮動小数点演算器を持っており、次の例のような命令列の場合には、浮動小数点加算(FADD)と整数加算(ADD)を並列に実行すれば、両方の演算器を遊ばせることなく有効利用ができる。なお、ここでFのついたレジスタは浮動小数点データ用レジスタであり、Rのついたレジスタは整数データ用レジスタである。

また、整数演算器はプロセサチップ全体の面積から見ると数%程度しか占めておらず、面積が小さいので、これを2個搭載して2つの整数加算命令を並行して実行できるような構成としても、コストアップは僅かである。このようなプロセサでは、整数演算命令と浮動小数点演算命令のペアだけでなく2つの整数演算命令のペアもデータ依存性が無ければ同一サイクルに実行を開始することができ、2命令を並列に実行できるケースが大幅に増加し、性能改善効果が大きい。

このようなスーパスカラ実行を行うためには、命令デコーダは複数の命令を並列にデコードし、それぞれの命令についてデータハザードや構造ハザードが無いことを確認するが、2番目やそれ以降の命令では、同一サイクルに実行を開始する先行する命令との間でデータの依存性や使用資源の競合がないことを確認する必要がある。そして、このようなハザードが存在しないことが確認できると、それらの後続の命令をそれぞれの演算器のパイプラインへと送り込むということになる。 しかし、

のように、並列にデコードした命令間にデータの依存性(この場合は、先行するADD命令の結果であるR6を後続のADD命令が使用する)がある場合は、並列には実行できず、最初のADD命令が終了してから、次のADD命令を実行することになり、スーパスカラ実行はできない。

また、データに依存性が無くても、浮動小数点演算器が1個しかないと、次の例のように浮動小数点加算命令が連続している場合は、両方の命令を並行して実行することはできない。

もちろん、浮動小数点演算器を2個にすれば並列実行が可能であるが、浮動小数点演算器は整数演算器よりも必要面積が大きいので、筆者の知る限りでは、2命令並列デコードの汎用プロセサで2個の浮動小数点演算器を持つ例は無い。

一方、4命令並列デコードのプロセサでは、2個の整数演算器と2個の浮動小数点演算器を持つプロセサが一般的である。ただし、まったく同じ演算器を2個持つとは限らず、IntelのXeonプロセサなどでは、一方の浮動小数点演算器は、加減算に加えて割り算や三角関数などの複雑な浮動小数点演算をサポートするが、もう一方の演算器は、ベーシックな加減算だけというような実装が行われている。このように構成の異なる2個の演算器を持つと、デコードや命令構造ハザードの検出という点では複雑になるが、複雑な命令が2つ続くケースは少なく、演算器の必要面積の点で有利である。