ゲーム機技術総合

興味を持ったことを書いていきます。

PS4のコヒーレントバス

すでにPS5への世代交代がなされた現在ですが、今更ながらPS4について取り上げたいと思います。

なぜ今更、PS4についてなのかというと、とあるリーク記事を見つけたからです。

vgleaks.com

これはPS4が発売される前、PS4 SDKからリークされた情報が載っており、主に取り上げられてる内容としてはPS4においてのコヒーレントアクセスについてです。

PS4のコヒーレントアクセス周りについては、日本だとPC Watchの後藤氏による記事で詳細に取り上げられてますが、このリーク記事はそれらを深掘りしたものとなっております。

主な要点としてはPS4で採用されたKaveriアーキテクチャにおいてのコヒーレントバスの扱いと、それに採用された二つのコヒーレントバス、OnionとOnion+についての内容となっております。

今回はそれらについて取り上げていきます。

 

コヒーレントバス

まずコヒーレントバスというのはCPU - GPU間でのキャッシュコヒーレンシを保つための専用バスです。

この世代のAMDはCPUとGPUが同じダイに実装されたAPUという製品を開発しており、

CPU-GPUが同じリソースを滞りなく共有して処理できるモデルを開発しました。

そこで大量のデータを処理するGPUのために専用バスGarlicと、CPU-GPU間でのリソース共有ができるコヒーレントバスOnionを設計しました。(いずれもネギ属のコードネームが付けられています。)

そもそもキャッシュコヒーレンシ(一貫性)とはそれぞれのプロセッサ間で一貫したデータモデルを持つことです。

たとえば一般的なマルチコアCPUにおいてもこのコヒーレンシ問題が付き纏います。

それぞれのコアが好き勝手にデータを処理するのは、各コア間で共有されてるデータの一貫性が悪化する原因になります。そのため処理されたデータが更新されたものであるというフラグを立てる、もしくはメモリに書き出してすべてのプロセッサに更新されたデータであることを明示する必要があります。

この動作はマルチコアCPUだけにとどまらず、リソースを共有するGPUなどのプロセッサにおいて問題となります。

とくにAPUではCPUとGPUが同じリソースを共有する場面もあり、コヒーレンシの維持には手間がかかるため、専用のコヒーレントバスであるOnionを実装したと思われます。

GPUがCPUと共有リソースを持つ場面といえば、GPGPUなどGPUの演算性能を生かした汎用演算だと思われます。

ちなみにこの世代のAPUがなぜここまでコヒーレントバスに注力したアーキテクチャになっていたのかというと、HSA(Heterogeneous System Architecture)を念頭に設計されてたからと言えます。

このHSAというのはCPUとGPUを同じプログラミングモデルで扱うことにより、利便性とパフォーマンスを大きく追求しようぜという試みで、AMDは専用のHSAランタイムなどの開発に注力していました。

そのためAMDは、最初のAPUアーキテクチャだったLlanoから次のTrinity、そしてKaveriとCarrizoまでこのコヒーレントバスを改良していくことになります。

PS4もちょうど第三世代のKaveriアーキテクチャのモデルを採用しています。

 

PS4のコヒーレントシステム

PS4のSoCブロック図

このブロック図ではPS4で用いられたバスシステムが読み取れます。

PS4では、コヒーレントバスとしてのOnionGPU専用バスのGarlic、それに加えてもう一つのコヒーレントバスであるOnion+が実装されています。

ちなみにGarlicは非コヒーレントバスとなっており、CPUとのキャッシュコヒーレンシを取らない仕様になっているのでここでは取り上げません。

まずOnionについてですが、これはGPU-IOコントローラ-UNB(Unified North Brigde)間をつなぐ構図になっています。UNBは実質的にCPU側のメモリコントローラとして機能してると考えていいです。

Onionを使ったコヒーレントアクセスは以下の流れ。

  1. GPUGPU内部のメモリコントローラからIO hubを経由して、IOコントローラに接続。
  2. IOコントローラ内部のIO MMUがアドレス変換を行いCPU側のアドレス領域にアクセスできるように処理。
  3. CPU側のメモリ領域、CPU内部のキャッシュにアクセスしてデータにアクセス後、データを処理する。
  4. CPUとのコヒーレンシを保つためにGPUはすべてのL2キャッシュラインに対してキャッシュフラッシュを行う。

 

キャッシュフラッシュとはキャッシュラインのデータを一度、メモリに書き出す動作のことをいい、これによりCPUが変更を加えられたデータを認知することができます。

これらの手順によりGPUは、CPUとのコヒーレンシを保ったまま、CPUとの共有リソースを処理できます。

しかし、ここで注目すべき点は、4番目のキャッシュフラッシュです。

GPUが行うキャッシュフラッシュは、キャッシュ内部にある他のGPU専用リソースの解放を意味しており、そうすると他のタスクへの影響が避けられません。

この時代のGPUとなると、非同期コンピューティングのようにグラフィックス処理とコンピュート処理、それぞれ性質が異なる処理を同時に動かすことができるようになったのでとくに問題視されました。

 

「それでは問題となるキャッシュフラッシュの問題を取り除けばいいのではないか?」

ここでOnion+というもう一つのコヒーレントバスが登場します。

Onion+の動作構図としてはOnionと同じく、GPU-IOコントローラ-UNBを経由しますがやや違いがあります。

  1. GPU内部のCUがキャッシュ、GPUメモリコントローラ、IO hubをバイパスし、IOコントローラに直接、アクセスする。
  2. IOコントローラ内部のIO MMUがアドレス変換を行いCPU側のアドレス領域にアクセスできるように処理。
  3. CPU側のメモリ領域、CPU内部のキャッシュにアクセスしてデータにアクセス後、データを処理する。

注目する点として1番目のいくつかのハードウェアブロックをバイパスする点です。

完結に言って仕舞えばOnionで問題となっていたGPUキャッシュブロックを意図的にバイパスすることにより、問題となっていたGPUのキャッシュフラッシュを避けることが可能になりました。

つまりOnion+はGPUのキャッシシステムを使わないため、処理されたデータは直接メモリに書き出されることになり、キャッシュフラッシュをしなくてもCPUがGPUによって処理されたデータを認知できるようになりました。

これによりGPUのキャッシュラインを全てフラッシュせず、CPUとのコヒーレンシを保てることになりました。

 

 

こうしてOnion+はAMDのHSAの注目機能としてKaveriアーキテクチャにて採用され、PS4でも非同期コンピュート性能の目玉機能としてプッシュされました。

AMDは、Onion+の登場でOnionを非コヒーレントバスとして使ってるとも発言しており、実質的にOnionの後継としての位置付けを行なっています。

PS4においては、これらの機能がPS3で使われたCellコンピューティング思想とマッチングしたということで旧来のファンからはとくに注目された技術です。

HSA自体がCellっぽさあったというのも大きいとは思いますが、まあ厳密にはちょっと違うと思いますけどね。

 

とりあえず、これでPS4のコヒーレントバスについて事前知識は終わりとなります。

ここまでの感じだとOnion+はOnionの改良版と言った形だと受け止められるかと思いますが、実際はそうではありません。

ここからはリーク資料で明らかになった内容について取り上げます。

 

リーク資料の詳細

それではここで冒頭で取り上げたリーク資料を交えて解説します。

vgleaks.com

vgleaks.com

内容が結構あるため重要な箇所についてまとめたものが以下となります。

  • PS4ではOnionとOnion+は、それぞれシステムコヒーレントバッファ(SC)とアンキャッシュドバッファ(UC)にアクセスするために使われる。
  • SCのためにL1、L2キャッシュに新しいタイプのinvaildateビットを付与できる。
  • SCのためにL2キャッシュは新しいタイプのライトバック機能が付与された。
  • UCのためにL1、L2キャッシュにバイパスビットが付与された。

 

システムコヒーレントバッファ(SC)とアンキャッシュドバッファ(UC)は、CPUとGPUの両方からアクセス可能と書いてあり、またUCに関してはOnion+でアクセスするとの記述がありました。名前の通りデータがキャッシングされないということでOnion+仕様が前提のバッファです。

Onionに関しては明確な記述が少ないですが、SCについての機種で最大のコヒーレンシ問題性についての記述があり、おそらくSCバッファはOnionでアクセスするためのバッファであると考えていいと思います。

とりあえずここではSC=Onion、UC=Onion+を使ってるとの前提で話を進めます。

 

個人的に今回のリーク資料での一番の注目ポイントとしては、SCのためにL1、L2に新しいビット(invaildateビット)、L2に新しいタイプのライトバック機能が加えられてる点でしょう。

前者に関しては直訳すれば無効化ビットになりますが、これだけでは説明が不十分ですね。

というわけでSCバッファを使った一例について詳しい詳細がありましたのでそのまま載せます。

Simple Example:

–   Let’s take the case where most of the GPU is being used for graphics (vertex shaders, pixel shaders and so on)

–   Additionally, let’s say that we have an asynchronous compute dispatch that uses a buffer SC memory for:

  • Dispatch inputs, with are created by the CPU and read by the GPU
  • Dispatch outputs, which are created by the GPU and read by the CPU

 

–   The GPU can:

1)      Acquire the SC buffer by performing an L1 invalidate (GC and SC) and an L2 invalidate (SC lines only). This eliminates the possibility of stale data in the caches. Any SC address encountered will properly go offchip (to either system memory or CPU caches) to fetch the data.

2)      Run the compute shader

3)      Release the SC buffer by performing an L2 writeback (SC lines only). This writes all dirty bytes back to system memory where the CPU can see them

–   The graphics processing is much less impacted by this strategy

  • On the R10xx, the complete L2 was flushed, so any data in use by the graphics shaders (e.g. the current textures) would need to be reloaded
  • On Liverpool, that RO data stays in place – as does PV and GC data 

これは通常のグラフィックスパイプラインとSCを扱う非同期コンピュートを処理する際の例です。

注目する点としては1番のキャッシュ無効化、3番目のL2ライトバックのところでしょう。

1番目のキャッシュ無効化は、L1、L2キャッシュ内のSCラインに対してinvaildateビットを付与する形、つまりこのSCラインとはコヒーレンシに影響を与えるデータが格納されれ、そのキャッシュラインに対して無効化を付与するということだと思われます。

その後、Onion経由でSCバッファにアクセスし、それを用いてGPUがコンピュートシェーダを処理する形になり、最終的にはL2キャッシュがSCラインのみに対してライトバックを行う。(キャッシュデータをとあるタイミングでメモリに書き出す)

このライトバックによりメモリに書き出されるのは、コヒーレンシに影響を与えるSCラインのみであるため、キャッシュフラッシュされるのはこのSCラインということになります。

つまりPS4のOnionアクセスでは、今までのようにGPUキャッシュのオールフラッシュが強制されることはないということです。

PS4のOnionではキャッシュ無効化ビットや専用のライトバック命令が追加されたことにより、従来のOnionが抱えていた問題を緩和したことを意味します。

ちなみに資料内ではレイキャスト処理、水面処理などのグラフィックス処理において、SCバッファを使った例が取り上げられているため、必ずしもOnion+が常の最適解というわけではないと断言できます。。

それほど改良されたOnionは効果的に動いてると見ていいでしょう。

 

とはいえ、複数のコンピュートシェーダが動いてる際はUCバッファを使うほうがいいかもとの記述もあります。

これはSCバッファ、つまりOnionで使われる一連のキャッシュ操作が、複数のコンピュートシェーダが動いてる場合においては煩雑な手続きになるとのことで、キャッシュバイパスのアプローチを採るOnion+を使ったほうがいいケースもあるとのことです。

PS4GPUには粒度の低いコンピュートタスク専用スケジューラとしてACEが8基搭載されてるため、このような一例が紹介されてるのかもしれません。(ちなみにACE1基で8つのコンピュートタスクを発行できるとのことで合計64個のコンピュートタスクを発行できるという計算です。)

 

まとめると、PS4GPUが実行するタスクにおいてOnionとOnion+の両方でどちらが効果的かを開発者が判断して実装できる環境になってるといえます。

 

まとめ

ネックな要素ばかりがメディアで取り上げられてた印象が強かったOnionですが、リーク資料を見るとかなり効果的な進化を遂げていたのではないかと思いましたね。

当時は改良版のOnion+ばかりスポットが当てられていたのでずっと気になっていた話題でもあります。

とはいえ、このOnion+も次の世代のCarrizoでは廃止され、その次のZen APUでは新しいバスシステムであるInfinity Fabricに置き換わりました。

ちなみにCarrizoではOnionがアドレス変換専用バスに変わり、コヒーレンシ前提でのデータアクセスも従来のGarlic経由から行えるようになったことでGPUの最大帯域を活用できるようになったとのことです。

Onion系バスをデータアクセスで使うには全体的に帯域幅が狭く(20GB/s程度)、GPUが扱うには心許なかったため、これは大きな改善だと思われます。

それに加え改良版のOnionで、ある程度のキャッシュフラッシュ問題を緩和したこともあり、Carrizo以降はキャッシュ制御によるコヒーレンシ確保が難なく可能になったとも推測できます。

そのためキャッシュバイパスの構造はもはや必要なくなったと推測されます。

当時としては先進的だったOnion+ですが、今見れば過渡期の代物だったかのようにも思えます。