AMD Zen 2は実行パイプライン拡張で浮動小数点性能が2倍に

浮動小数点/SIMDとロード/ストアを拡張

AMDは、Zen 2でZenマイクロアーキテクチャの大幅な手直しを行なった。命令を実行するバックエンド部での重要ポイントは2つ。1つは浮動小数点/SIMD(Single Instruction, Multiple Data)演算パイプを256-bit幅に拡張し、浮動小数点演算のスループットを2倍にしたこと。

もう1つは、メモリアクセスのロード/ストアパイプを従来の2パイプから3パイプに拡張し、ロード/ストアの効率をフルにしたこと。ロード/ストアの拡張は、実質SIMDパイプの拡張のためと言っていいので、バックエンドの拡張は、SIMD演算のスループットを上げるためだと見てよさそうだ。

AMDは、整数コアについては、演算パイプ数は4パイプのまま(それ以上に増やしても意味が薄い)だが、アウトオブオーダの命令ウィンドウは192から224に、物理整数レジスタンスは168本から180本へと拡張した。Zen 2はSMT(Simultaneous Multithreading)なので、1スレッドあたりは命令ウィンドウが112、レジスタが90という計算になる。SIMD系とロード/ストア系の拡張に対して、整数演算のアウトオブオーダ実行のリソースの拡張はひかえ目だ。

ひかえ目というのは、たとえば、Intelはアウトオブオーダウィンドウは10nmプロセスの「Sunny Cove」コアでは352だ。ただし、Intelの拡張が過剰という見方もできるので、単純な比較はできない。

Zen 2は、アウトオブオーダリソースについて言えば、ちょうどIntelのSkylakeクラスにあたる。Skylakeでは、命令ウィンドウは224で、整数レジスタは180本、Zen 2とぴったりマッチする。

AMDは、フロントエンドの拡張で、実行エンジンに対する命令フィードを増やした、つまり、より多くの命令を実行エンジンに送り込めるようにした。現在のバックエンドの構成は、その命令フィードに見合った構成だとAMDは見なしているのかもしれない。いずれにせよ、整数演算リソースの拡張は、Intelと比べると、それほど劇的ではない。

アウトオブオーダウィンドウはSkylake相当に拡張

Zen 2では、アウトオブオーダ部からの「リタイヤキュー(Retire Queue)」は224エントリ。言い換えれば、最大224個の内部命令をアウトオブオーダ実行でインフライトで制御できる。このエントリが大きければ大きいほど、より多くの命令をアウトオブオーダ実行で走らせて、クロック当たりの性能を上げることができる。

初代のZenでは、リタイヤキューは192だったので、17%リソースが増えたことになる。ZenはSMTアーキテクチャなので、2つのスレッドを同時に走らせる場合は、リタイヤキューはそれぞれ96/スレッドとなる。

リタイヤキューの拡張もIPCの向上には寄与するが、AMDの場合はリソースの拡張は抑えており、インパクトはそれほど大きくはない。Intelが世代ごとにアウトオブオーダリソースを大幅に拡張することと比べるとおとなしい。すでに述べたように、Zen 2を迎え撃つIntelのSunny Coveコアでは、リオーダバッファは352エントリとなっている。Zen 2の1.57倍だ。

リタイヤキューの中の内部命令は「リタイヤコントロールユニット(Retire Control Unit:RCU)」によってコミットされアウトオブオーダ部からリタイヤする。ここでややこしいのは、AMDのスライドでは毎サイクルに8個の“Micro-OP”をリタイヤさせることができるとされているのに対して、Zenのソフトウェア最適化ガイドでは8個の“Macro-OP”をリタイヤさせることができるとなっていることだ。ガイドのほうは、Bulldozer世代の名称を一部引きずっているのだが、Macro-OPは複数のMicro-OPを含む複合命令となる。Zen 2のスライドでは、複合型の命令は「Instruction」と表記されている。

そもそも、AMDアーキテクチャの場合、ややこしいのは、ディスパッチャの下にレジスタリネーミングが整数コアと浮動小数点/SIMDコアに分離されて配置され、その下にスケジューリングキューが配置されていることだ。同じx86/x64でもIntel CPUの場合は、デコードされた命令は統合されたスケジューラでMicro-OPに分解され、リネーミングで物理レジスタが割り当てられ、アウトオブオーダのキューにディスパッチされる。

しかし、AMDの場合、デコーダとスケジューラの間にディスパッチャがはさまっている。これは、AMDが伝統的に整数コアとFP/SIMDコアにCPU内部を分割しているためで、スケジューリングも2つのコアそれぞれで分離して行なう。いわゆる、コプロセッサ型のアプローチだ。整数パイプとFPパイプ合わせた全体の整合性は共有されるリタイヤコントロールユニットが制御している。

この構成のため、AMDアーキテクチャでは、ディスパッチの段階でMicro-OPsへの分解が必要になる。たとえば、メモリオペランドを持つFP系の命令の場合、FP演算Micro-OPと、ロードMicro-OPに分解して、それぞれFPコアと整数コアに分離してディスパッチしなければならない。

リタイヤユニットは、インオーダの整合を取る必要があるので、分解されたMicro-OPの実行が完了したら、インオーダ部の複合型の命令としてリタイヤさせる。AMDの場合はどうなっているかというと、ディスパッチの段階でMicro-OPsに分離されるが、同じ複合命令に属するMicro-OPは紐付けられてトラックされるという。このあたりは、まだ不明瞭な部分がある。

基本の構造は変わらない整数コア

内部命令のディスパッチャから整数コアへのMicro-OPsのディスパッチは毎サイクル最大6 Micro-OPs、FPユニットへは毎サイクル最大4 Micro-OPs。ここはZen世代と変わっていない。内部命令のキャッシュであるOPキャッシュ(OP Cache)からの読み出しは毎サイクル最大8 Instructionなので、ディスパッチ帯域が相対的にかなりせまいが、パイプラインの上を広くとり、下をせばめるのは常套的な手段だ。実際にディスパッチへのキューを埋めるには、多くのInstructionを取りこむ必要がある。

レジスタリネーミングユニットは、整数コアとFPユニットそれぞれに分離されている。物理的にレジスタが異なるため、このほうが効率がいいとAMDはみなしている。レジスタリネーミングでは、レジスタの競合を避けるために各Micro-OPsのレジスタをリネームして物理レジスタをマップする。命令間のレジスタの競合には、真に依存性のある競合以外に、同じレジスタを使うだけの偽の競合があり、リネーミングでそれを回避する。

そのための物理レジスタスペースは、Zenの168エントリからZen 2では180エントリへと拡張され、よりアウトオブオーダのスケジューリングに余裕ができた。180物理レジスタはSkylakeと同じだ。

ちなみに、FPユニット側では物理レジスタ数は160エントリでZenから変わらないが、じつはレジスタ量は2倍になっている。後述するが、これによって、レジスタの空間も広がっており、より多くのSIMD命令を走らせることができるようになった。

すでに述べたように、整数コアの実行パイプはロード/ストア系が3本となり、Zenの2本から拡張された。FPユニットの実行パイプは4本のままだが、各ユニットが128-bit SIMDから256-bitへと拡張されている。

命令スケジューラの構成も変更

整数コアをもう少し詳しく見ると、スケジューラのキューの構成が変わった。Zen 2では、整数演算スケジューラは各命令ポートごとに1つのキュー(ALQ:ALU Queue)で、各キューは16エントリ、つまり、4つの整数演算命令ポート毎に16個の命令を待機させることができる。キューで待機する命令は、リソースが有効になるとアウトオブオーダで実行される。

命令ポート毎に個別のキューとなっている整数演算に対して、ロード/ストアは統合されたキュー(AGQ:Address Generator Queue)となっている。28エントリで、AGQから3つのロード/ストア命令ポートに命令が発行される。初代Zenでは、ロード/ストアの2つのポートそれぞれに14エントリのキューだった。ポート当たりのキューは減ったが、ロード/ストア命令の場合、命令を発行してからのキューのほうが重要だ。

Zen 2では、ロード/ストアパイプが増えたことで、スケジューラからの命令発行ポートは合計7つになった。最大7個のMicro-OPsを、実行ユニットにイシュー(発行)することができる。Zenは、ロード/ストアが1つ少ないため6ポートだ。

ちなみに、Bulldozer系アーキテクチャでは整数コアは、演算パイプが2本にロード/ストアパイプが2本の構成だった。物理レジスタは112本で、スケジューラのキューは48エントリ。Bulldozerが、いかに整数演算ピーク性能を抑えた設計だったかがわかる。

もっとも、Zen系はSMTなので、2スレッドを走らせる場合は競合でリソースは減るが、マルチスレッディングは動的な制御であるため、BulldozerよりIPCはずっと高くなる。Zen 2でのリソースの増量は、SMT時の余裕も増やしている。