Skip to content
Go back

Understanding GPU caches

· Updated:

web

要約

  • GPUのキャッシュコヒーレンシーは、回路規模やパフォーマンスの問題があるため、ユーザーがバリアやフェンスを使って明示的に管理する必要がある
  • 命令キャッシュはコアごとにあり、多数のスレッドで共有されるため、キャッシュミスが致命的になる
  • データキャッシュはコアごとにあり、再度の読み出しよりも隣接データがキャッシュにのることの恩恵のほうが大きい
  • キャッシュヒット率を高める目的の、スカラのための特別なデータキャッシュがある
  • コア間で共有されるデバイスレベルのキャッシュがあり、コア単位のキャッシュをスキップしてアトミックに操作できる機能がある
  • キャッシュではないがキャッシュのように近くにあり、ユーザーが自由に使える共有メモリがある

拙訳

キャッシュコヒーレンシー

  • GPUは明示的にフラッシュや無効化を行う必要がある
    • コア数が多すぎてCPUのようなキャッシュ・コヒーレンシー・プロトコルを搭載できない
    • コヒーレントなリソースやメモリバリア命令(シェーダー内)、リソースバリア(コマンド間)、同期プリミティブ(デバイス間)を使う

コア単位の命令キャッシュ

  • GPUはSIMT(Single Instruction Multiple Thread)方式で動作する
    • スレッドのまとまりごとに各スレッドが同じ命令を実行する方式
    • スレッドのまとまりをDXだとwave、AMDだとwavefront、NVIDIAだとwarp、Vulkanだとsubgroupと呼ぶ
    • CPUのSMTのように、複数のwaveでコアを共有して実行する機能もある
  • 命令キャッシュは小さくても問題ない
    • 1回の描画に必要なスレッド数がGPUのコア数に対してかなり多いので、実際にはGPU全体で同じプログラムを実行することが多い
    • そんななので、AMDのGCNアーキテクチャでは4つのCUで命令キャッシュを共有していたりする
    • パフォーマンス的には、命令キャッシュミスによる大量のスレッドのストールを回避するよう、シェーダーをキャッシュに収まるくらいに小さくすることを強く推奨する

コア単位のデータキャッシュ

  • データキャッシュは、一般に、ライトスルー方式で行われる
    • データの変更が即座に次段へ伝播する方式
  • データキャッシュは使える量がすごく少ない
    • コアに付いたキャッシュを実行中のスレッドで分け合うため
    • 同じメモリを何度も読み出すのような従来の使い方は、占有率が高いときには不向き
    • それよか、隣接要素を含めたテクスチャフェッチのような、コア内で同じ場所を読み出すようなアクセスパターンに向く
  • つまり、キャッシュされたデータの再利用は、時間領域(同スレッドによる読み直し)というより、空間領域(同コア内の別スレッドによる同一メモリからの読み出し)でよく発生する
    • 読み直しでのキャッシュヒットが期待できないので、メモリに一時データを置くようなやり方はしない方がいい
    • その分、レジスタ空間が広かったり共有メモリが使えたりするので、そっちでなんとかする
  • コア内のすべてのスレッドが同じメモリを読み出すためのキャッシュが別に用意される
    • スカラキャッシュとか定数キャッシュとか呼ばれたりする
    • 通常の置き換え規則で同じキャッシュを格納した場合に発生するであろう高頻度のデータアクセスによってキャッシュから追い出されないようにするため
    • 命令キャッシュと同様の論理で、コア間で共有する設計になっていることもある

デバイス全体のキャッシュ

  • コア単位のキャッシュの上に、コア間でコヒーレンシーを保つためのデバイス全体のキャッシュがある
    • 通常、アトミック演算はここで処理される
  • GLSLのcoherent修飾子のような、デバイス全体のキャッシュでデータを直接やり取りさせる方法もある
    • コア単位のキャッシュに読み書きしない分、その同期処理でストールしなくてすむ
    • タイルベースのような一般的なスレッド単位のデータアクセスでは、wave全体のリクエストがキャッシュライン全体の大きさのデータトランザクションにまとまるので、オーバーヘッドはないとみて良い
    • この最適化技法は、それぞれコヒーレントな読み書きを介してデータ共有を行う“プロデューサー”および”コンシューマー”ワークロードの間にスケジュールできる非依存な処理が十分な数だけ存在する場合に利益をもたらす
      • コア単位のキャッシュのフラッシュや無効化のようなキャッシュ制御操作を用いずにその2つの間の完了通知のみの依存関係で可能になるため
  • CPUのL3キャッシュと比べるとかなり小さい(数MB程度)
    • AMDのBig Naviとかは、帯域を代替するための巨大な追加キャッシュがある
  • APUにはデバイス全体のキャッシュはないので、CPUのL3キャッシュを使う

共有メモリ

  • Workgroup単位で共有して使用できるスクラッチパッドメモリ
    • キャッシュと異なり、ユーザーが自由に操作できる
  • NVIDIAのVoltaでは、共有メモリとL1キャッシュとテクスチャキャッシュを共通のキャッシュ領域で管理する設計が特徴的
    • 共有メモリを使わないグラフィックス処理ならデータキャッシュとしてまるまる使える
  • AMDでは、コア単位のLDS、デバイス全体のGDS、とに分かれている

その他のキャッシュ

  • 頂点属性のためのキャッシュが昔はあった
  • PC向けGPU(IMR)には、ROPのキャッシュがある
    • レンダーテクスチャやシャドウマップ、Gバッファなどで使うので、コア単位のキャッシュに近い形になっている
  • モバイル向けGPU(TBR)には、ROPのキャッシュはないが、タイルごとにスクラッチパッドメモリがある
  • 最近のGPUは仮想アドレスなので、物理アドレスへ変換するためのTLBがある