後藤弘茂のWeekly海外ニュース

AMD Kaveriのメモリアーキテクチャと今後のAPU進化

Kaveriの新しいコヒーレントバス「Onion+」

 AMDの新APU「Kaveri(カヴェリ、A10/A8-7xxx)」は、HSA(Heterogeneous System Architecture)のプログラミングモデルを実現することに主眼を置いて設計された。HSAの中でも最重要のフィーチャであるメモリモデル「hUMA(heterogeneous Uniform Memory Access:ヒューマ)」を実現した点は、Kaveriの最大のポイントだ。これによって、CPUコアとGPUコアは、コヒーレンシが保たれた状態で同じメモリ空間を共有できるようになった。プログラマーはポインタを送るだけで、CPUとGPUの間でデータを共有させることができるようになった。GPUのプログラミングを容易にするという、HSAの目的に向けて大きく前進したのがKaveriだ。

hUMAでのデータ共有

 ただし、hUMAを実現する裏側のメカニズムを見ると、まだKaveriのアーキテクチャは究極のAPUに至っていないことがわかる。hUMAを迅速に実現することを主眼として、できる限りアーキテクチャの拡張を避けた。逆を言えば、AMD APUは、さらにアーキテクチャ的に発展の余地がある。CPUとGPUの究極の統合に向けて、AMDはまだ歩み続けている。Kaveriを見ると、今後のAPUがどう進化して行くのかが分かる。

Kaveriのダイレイアウト(PDF版はこちら)

 AMDはAPUの内部バスのアーキテクチャを、段階的に進化させてきた。最初のAPUであるLlano(ラノ)では、CPUコアとGPUコアを物理的に1つのシリコンダイ(半導体本体)に統合した。そして、GPUコアからDRAMコントローラにアクセスするバスを2系統設けた。1つ目のバスは「Radeon Memory Bus (Garlic:ガーリック)」で、これはGPUコアからメモリコントローラへの広帯域の直アクセスを実現する。2つ目のバスは「Fusion Compute Link (Onion:オニオン)」で、ディスクリートGPUがI/Oコントローラ経由でCPUと接続されていたバスをオンダイに実装したようなバスだ。Onionバスは、GPUコアからCPUキャッシュへのスヌープ/プルーブができるI/Oコヒーレンシ型バスになっている。

Llanoでの進化点

 だが、Llanoの段階でも、CPUコアとGPUコアのそれぞれは、分離されたメモリ空間を持ち、その間のアクセスは制限されていた。GPU側からのアクセスはページフォルト(Page Fault)のハンドルができないため、CPUのメモリアドレス空間の中でGPUがアクセスできる領域は、ストレージへとスワップしないように制御しなければならなかった。

Trinity、Richlandでの進化点

 2世代目のAPUのTrinity(トリニティ)では、IOMMU(I/O Memory Management Unit)を拡張したIOMMUv2に切り替えて、ページフォルトのハンドリングをできるようにした。これによってストレージにスワップしているメモリ領域にアクセスした場合も、メモリを呼び戻すことができるようになった。Llanoまでのような、スワップの制御は必要がなくなった。また、Onionは256-bit幅に拡張された(Trinity発表時の資料では128-bitとなっていた)。

 Kaveriではこの構造が大きく変わり、GPUコアとCPUコアの間に新たに「コヒーレントバス(Coherent Bus)」が設けられた。このバスは双方向にメモリコヒーレントが取れたバスとなっている。一方、従来のOnionは、ノンコヒーレントバス(Non-Coherent Bus)と改められた。つまり、GPUからのCPU経由のメモリアクセスは、コヒーレントを取るバスと取らないバスの2系列が併走するようになった。どちらも256-bit幅だ。

Kaveriでの進化点
Kaveriのアーキテクチャ(PDF版はこちら)

 AMDによると、コヒーレントバスのコードネームは「Onion+(オニオンプラス)」だという。これは、PlayStation 4(PS4)のコヒーレントバスと同じコードネームで、技術的な内容も同一だと見られる。ちなみに、AMDにはもう1つ「Chive(チャイブ)」と呼ばれるバス技術がある。Onion+と同様に、GPUコアからCPUとコヒーレンシを取ってメモリアクセスするバスだが技術的に異なるという。「ゲーム機の側の技術については話すことはできないが、ChiveはOnion+とは少し違うバスだ」とAMDのJoe Macri氏(Corporate VP & Product CTO of AMD Global Business Unit)は語る。違いは、おそらくメモリ管理ユニット「MMU(Memory Management Unit)」のアーキテクチャにあると見られる。

Onion+バスを加えるだけでキャッシュフラッシュ問題を解決

 従来のAPUでは、GPUコアはCPUのキャッシュをスヌープできるが、CPUコアはGPUのキャッシュをスヌープできない。GPU→CPUの片方向のキャッシュコヒーレンシしか維持されない「I/Oコヒーレンシ」型のモデルを取っている。GPUはCPUにどのデータがキャッシュされているのかがわかるのに、CPUはGPUにどのデータがキャッシュされているのかが分からない。

 GPUが読み込んだメモリエリアにCPUがアクセスする場合に、そのデータがGPUのキャッシュにあるかどうかはCPUにはわからない。GPUがメモリに書き出さないと、コヒーレンシを取ることができない。そのため、いったんGPUのキャッシュをソフトウェア制御でフラッシュさせて、共有のメインメモリに書き戻させる必要がある。キャッシュフラッシュはコストの高い重い処理となるため、パフォーマンスを削いでしまう。従来のAPUでは、これが大きな問題だった。

Kaveri GPUのメモリ階層(PDF版はこちら)

 Kaveriでは、この問題を非常に簡単な仕掛けで解決している。実際には、Kaveriでも、依然としてCPU側はGPUのキャッシュをスヌープできない。まだ、I/Oコヒーレンシ型のモデルだ。しかし、GPUキャッシュフラッシュの必要をなくした。

 Kaveriでは、GPUがコヒーレントバス(Onion+)でメモリにアクセスする場合は、GPUのL2キャッシュをバイパスしてしまう。GCN(Graphics Core Next)アーキテクチャのGPUコアでは、上の図のようにL1キャッシュはライトスルーなので、ライトバックのL2さえ回避すれば、GPUコアのキャッシュをフラッシュする必要がなくなる。メインメモリはコヒーレンシが保たれているので、Onion+でパフォーマンスロスなく、コヒーレンシアクセスができることになる。AMDがOnion+をコヒーレントバスと呼ぶ理由はここにある。

Kaveriのインターコネクト(PDF版はこちら)

 一方、従来のOnionバスは、GPUのL2キャッシュにキャッシュされる。今回Onionバスではコヒーレンシは保たれない。コヒーレンシを保つ必要があるメモリアクセスは、コヒーレントバス(Onion+)の方を使うためだ。そのため、OnionアクセスでもGPUキャッシュフラッシュの必要がなくなる。

 ちなみに、OnionとOnion+のどちらのバスを使うかは、GPUのロード/ストア命令のタグで判別される。タグは、プログラム上で明示的に付加するのではなく、アクセスするメモリ領域によって自動的に付加されるという。

 ちょっと面白いのは、この場合、Onion経由のキャッシュはバーチャル(仮想)アドレスをベースに行なうと見られることだ。通常、GPUのL2キャッシュはDRAMコントローラの1つと1対1で対応するため、フィジカル(物理)アドレスベースのキャッシングのはずだ。つまり、GPUのMMUはL2よりもGPUコア側にある。しかし、Onionアクセスでは、アドレス変換はGPUコアの外のIOMMUで行なわれるため、L2にキャッシュされる時はバーチャルアドレスベースになるはずだ。APUではGPU L2キャッシュはハイブリッドでアドレススペースを制御していると見られる。

Kaveri GPUの全体図(PDF版はこちら)

キャッシングやMMUアクセスでロスが生じるKaveri

 AMDがKaveriに加えたこのOnion+の改良が素晴らしいのは、プログラム側から見ると、しごく単純にCPUコアとGPUコアの間でメモリコヒーレンシが保たれて見えることだ。メモリ空間のページテーブルが共有されているだけでなく、コヒーレンシも保たれているので、安全にデータの共有ができる。コヒーレンシメカニズムはハードウェアベースであるため、パフォーマンスも高い。

 ちなみに、GPUコア側の3つ目のMMUであるGPU MMUも、ページテーブルは共有する。GPU MMUとCPU側のMMUは、同じページテーブルを同期しており、ここが従来のAPUとKaveriの大きな違いとなっている。その結果、GPUとCPUは同じバーチャルメモリスペースを共有することが可能となり、異なるメモリスペース間でのデータの転送は完全に必要がなくなった。

hUMAとHSAで変化するもの
hUMAの重要な要素

 このように、Kaveriでは、ページテーブルの同期とコヒーレントバス(Onion+)によって、hUMAの使いやすいプログラミングモデルが実現された。

 ただし、現行のアーキテクチャではロスもある。まず、Onion+のコヒーレントアクセスでは、GPU側のL2キャッシュは利用できない。そのため、キャッシングが効くワークロードの場合は、L2キャッシュを使う場合よりパフォーマンスが落ちる。これはワークロードによるが、CPUコア同士のようにキャッシュコヒーレンシが保たれているアーキテクチャとは異なり、パフォーマンスにばらつきが出る可能性がある。

 もう1つは、メモリ管理ユニットを共有する制約だ。Kaveriアーキテクチャでは、コヒーレントバス(Onion+)とノンコヒーレントバス(Onion)はどちらもIOMMUを使う。2つのバスは物理的に独立しており、並列に動作できるが、IOMMUを共有するための制約もある。2つのバスが同時にIOMMUにアクセスはできず、コヒーレントかノンコヒーレントのどちらか一方のバスしかアクセスできない。片方のバスがIOMMUにアクセスしている間は、もう片方のバスはブロックされるとAMDは説明する。

 IOMMUは、バーチャル-フィジカルメモリ間の変換アドレスのキャッシュである「Translation Lookaside Buffer (TLB)」とページテーブルウォーカー(Page Table Walker)からなっている。ページテーブル自身は、すでに説明したようにCPU側のMMUが参照するページテーブルと同期している。コヒーレントバスとノンコヒーレントバスは、それぞれ小容量でアクセスの速いL1 TLBを独立して備えている。各バスがL1 TLBにヒットする場合は競合は発生しない。

 しかし、L1 TLBをミスした場合は、両バスとも、より大きくてレイテンシの長い共有のL2 TLBにアクセスする構造となっている。共有L2と個別のL1という、CPUコアのキャッシュと似たような構造だ。また、L2 TLBもミスした場合は、IOMMUのページテーブルウォーカーによって共有するページテーブルを参照する。

 だが、ページテーブル探査でも該当するページテーブルエントリを見つけられなかった場合は、ページフォルトとなりCPUに制御を投げる。ページフォルトが発生した時IOMMUは、OSが例外処理を行ない該当ページを物理メモリに戻すのを待つ。ページフォルトが解消されるまでの間は、IOMMU自体がスタックするため、コヒーレントとノンコヒーレントの両バスはともにIOMMUにアクセスができないという。

 こうした制約は、IOMMUをコヒーレントバスのメモリアドレス変換に使っているために生じている。AMDはリソースの重複やアーキテクチャの複雑化を避けるために、既存のIOMMUを使う方法を選んだと見られる。ちなみに、MicrosoftのXbox One APUでは、GPUコアとCPUの間のバスはIOMMUを使わずに、別のMMUを新設する方式を取ったと説明している。

将来は双方向のキャッシュコヒーレンシを実現

 GPUを統合する究極の手段は、CPUとGPUの間で、完全な双方向キャッシュコヒーレンシを取れるように設計することだ。CPUコア同士のように、CPUコアとGPUコアの間でも双方向のキャッシュスヌープを実現すれば、GPUコアもキャッシュしながらコヒーレンシを維持できる。せっかくのGPUキャッシュも活かすことができる。また、MMUもIOMMUとは分離して、GPU側にコヒーレントアクセス用のMMUを新設すればMMUの競合も避けられる。

AMDのJoe Macri氏(Corporate VP & Product CTO of AMD Global Business Unit)

 しかし、Kaveriでは、AMDはそうしたアーキテクチャを取らなかった。その理由をAMDのMacri氏は次のように説明する。「APUの内部アーキテクチャ(architecture)が複雑になることを抑え、大文字のAで始まる方のアーキテクチャ、つまりHSA(Heterogeneous System Architecture)を実現することに集中した。HSAの製品を迅速に市場に出すことが重要だった」。HSAのプログラミングモデルを急いで実現するのが優先で、内部バスやMMUのアーキテクチャを複雑にすることを避けたというわけだ。そうして見ると、Kaveriのアーキテクチャ選択は納得が行く。

 「我々は、HSAについては完全でピュアである必要があった。その上で、パフォーマンスと複雑さのバランスを取らなければならなかった。現在のソフトウェアを見てバランスを決めた。優れたプログラマーなら、コヒーレントバスでそれほど大量のアクセスは行なわないだろう。なぜなら、必要なデータの多くはノンコヒーレントで済むからだ。だから、コヒーレントバスのために、いたずらに複雑性を増すことは、今は得策ではないと考えた。

 キャッシュコヒーレンシが技術的に非常に難しいかというと、そうではない。問題は、キャッシュプルーブのメカニズムが、1つ上のレベルの複雑性を加えてしまうことだ。今回は、できるだけ複雑にせずに、エンジニアリングチームへの要求を抑えて、できる限り早く開発することを優先した」(Macri氏)。

 AMDがKaveriでは開発期間が長くなりかねないリスクを避けて、HSAのモデルを最もシンプルに実現できる工夫をしたことがわかる。また、その背景には、GPUコンピュートのワークロードの分析があり、今の段階では複雑性を増やしても、見合わないと判断したこともわかる。キャッシングやMMUアクセスの多重化を行なわなくても、現状のワークロードでは大きな問題ではないとみているようだ。

 とはいえ、AMDはKaveriを完成形と考えているわけではない。HSAのプログラミングモデルに対しては完成の始まりとなるAPUだが、まだまだ改良を加えて行くとAMDのMacri氏は明言する。

 「GPUキャッシュのプルーブは、機が熟せば実装する。Kaveriに続く世代群(generations)で実現されると見るのが自然だろう。それが進化というものだ。キャッシュプルーブはCPUコア同士では実現しているし、(GPUコアのトラフィックが多くても)ブルーブフィルタでアクセスを減らすことができる。Kaveriでは、最初のバージョンなので、複雑性を増すことに、一線を引いただけだ。MMUについても同様だ。将来のバージョンでは解決され、ブロッキングが発生しないようになるだろう」(Macri氏)。

 AMDの今後のAPUには、このほかに、GPUのコンピュートコンテクストスイッチングや、グラフィックス処理のプリエンプティブなタスク切り替えが加わる。GPUコンピュートのコンテクストスイッチングは、GPUのコンテクストのうち、グラフィックスとコンピュートを切り分け、コンピュートコンテクストだけをメモリにストアすることで、迅速なコンテクストスイッチングをカーネルの実行途中でもできるようにする。これも、より細粒度のタスク切り替えを実現するために必須の機能だ。

 さらにその先には、APUの究極の課題であるメモリ帯域の拡張が待っている。AMDはスタックメモリのJEDEC(半導体の標準化団体)規格である「HBM(High Bandwidth Memory)」に熱心に取り組んでいる。Intelが自社開発のeDRAM「Crystalwell」で実現したような超広帯域アクセスを標準メモリで実現する。メモリ帯域の制約が緩むと、AMDはAPUのGPUコアをプロセス微細化とともに強化しやすくなる。

(後藤 弘茂 (Hiroshige Goto)E-mail