要約
- 基本はCSで何でもやる
- image barrierのかわりにcoherentを使ってL2キャッシュミスを減らすとともに、vkEventでディスパッチを分割することで、fillとdrainをパイプライン化させる
拙訳
GCN REVIEW
- SIMD (VALU = Vector ALU):16幅のVALUが4クロックで64幅のwaveを実行する
- occupancy最大で、SIMDあたり10 waves
- CU:1つあたりSIMDが4つ
- 最大時、クロックあたり1 waveのスループット
- SALU = Scalar ALU
- LDS = Local Data Store
- V$ = Vector L1キャッシュ (VMEM)
- I$ = 命令L1キャッシュ
- K$ = Scalar L1キャッシュ (SMEM)
AMDAHL’S LAW
- 並列能力にスケールするマシンで可能なパフォーマンス改善は並列処理の量に比例する
- 例えば、GHz付近では、処理の75%だけを並列に実行した場合、最良の実行効率は非並列マシンの25%に低下するだろう
- なので、パイプライン化された並列処理でGPUを埋め尽くそう!
UNDERSTANDING GCN VECTOR MEMORY ACCESS
- 平均レイテンシはGPUやワークロードなどで変化し得る
- それ用に作ったシェーダのレイテンシーテストの結果からパフォーマンスの崖を推定できる
- L1ヒットで約114クロック(イメージ命令ごとのreturn rateがピークでVMEMあたり16クロック)
- L2ヒットで約190クロック(L1ヒットと比べて追加で76クロックくらい余計にかかる ⇒ L1ヒットの4.75倍)
- L2ミスで約350クロック(L1ヒットと比べて追加で236クロックくらい余計にかかる ⇒ L1ヒットの14.75倍)
- メモリのスループットを減らすものとは
- request queueがdrainingしないくらい十分な速度でVMEM命令を維持できていない
- memory requestsの規則的な流れを維持してみる(wave occupancyのいびつさを調査する、など)
- L1キャッシュミスやL2キャッシュミスに起因するメモリバブル
- 空間・時間的にデータの局所性を改善してL1ヒット率をあげてみる
- request queueがdrainingしないくらい十分な速度でVMEM命令を維持できていない
IDLE BOUND
- アイドル状態がパフォーマンスを制限する例:
- アイドルを含むバリア
- 直列な依存関係+やることが少ない
- GPUを飽和しない単純なジオメトリ
- SIMULTANEOUS_USE_BITはコマンドバッファの並列性を妨げる
- 1/4解像度パスのdrainとfillに関する数値:
- あるポストパスでは、VALUのアイドルが少なくとも14%ある
- ポストパス+クリアでは、VALUのアイドルが少なくとも26%ある
- “First-Fill Waves” = コールドキャッシュ状態で開始するwave
- 1440pのフルスクリーンパスだと最大で4.4%がfirst-fill waveになる
- 面積1/4のパスだと最大で17%(DOFとかMBでよくある)
- 面積1/16のパスだと最大で71%(リダクションでよくある)
- コールドキャッシュで消費されるGPU時間が結構多い可能性がある
- waveの起動率、命令キャッシュミス、スカラキャッシュミス、依存関係にあるフェッチ、などがレイテンシーとして現れる
AVOID SLOW CLEARS
- CSでイメージをクリアするのは避ける
- フルスクリーンのトライアングルでイメージをクリアするのは避ける
- 圧縮されるサーフェスでは、0.0か1.0ですべてをクリアすると美味しい
PS AND CS ON GCN
- PS - 次のV$に移る前にV$あたり1から4の間のwavesを起動する - 順序あり出力
- DCCやZ圧縮された出力をサポートする(圧縮がロードのレイテンシーを増加させ得ることに注意)
- 前段のパスで書き出されたレンダーターゲットを読み出すためにキャッシュのフラッシュを行う
- VSの開幕のレイテンシーが大きいとVSとPSの間の遅延がそれなりに大きくなり得る
- CS - 次のV$に移るまえにV$あたりworkgroupを起動する - 出力なし(順序なし)
- 圧縮イメージの読み出しは可能だが、DCCやZ圧縮されたイメージへの書き出しは出来ない
- リードからライトへ遷移するさいキャッシュをフラッシュしなくて良い
- グラフィックスキューでパイプライン化したり、CSキューで非同期に実行するのがカンタン
DELTA COLOR COMPRESSION (DCC) ON/OFF
- PCのGPUでのDCCは功罪両面ある
- (メタデータをフェッチする必要があるので)レイテンシーが増加するが、帯域幅が節約できる可能性がある
- プロファイルして、DCCを使うときと使わないときとを選択するのが一番良い
- STORAGEやUAVフラグを使うとレンダーターゲットでDCCを無効化できる
- 一括ON/OFFするよりも個々のレンダーターゲットで試してみる方が良い
- パフォーマンス差の例(Vega):
- deferred shadingで-5.0%
- SSRで-3.1%
- SSAOで+1.8%
- コンポジションで+2.2%
- ポストプロセスで+3.8%
AUTHOR’S OPINION OF IDEAL TRIANGLE-BASED ENGINE
- VS+PSはジオメトリのレンダリングにだけ使い、CSはそれ以外のすべてで使う
- CSは容易にパイプライン化するための能力を最大化する
PIPELINING
- 前段の処理のdrainに、fill中のコールドキャッシュのレイテンシーを隠蔽する
SIMPLE DATA RACE TESTER
- 32ビットのイメージを黑から白に書き換え、それをバリアなしでコピーしたとき黑が残っているかを見る
- RX580でテストすると、128x128以下だとデータレースが発生したが、256x256では起こらなかった
- インコヒーレント(GLC=0)なストアでもコヒーレントなL2$へのライトスルーになっている
- 書き換え処理のwaveがコピー処理のwaveより先に起動される
- GPUに大まかなworkgroupの起動順序がある
LEVERAGING COHERENT MEMORY QUALIFIER IN GLSL
- coherentを使うと、L1$をバイパスしてコヒーレントなL2$に格納されるGLC=1ストアにGCNでは解釈される
- ロードはcoherent修飾子を使う必要がないので、以下のusageモデルに従ってキャッシュされる
- フレームの開始・終了にキャッシュをフラッシュして、freshなキャッシュを保証する
- いずれかのリードの前にコヒーレントなストアで一度だけキャッシュラインを書き込む(実行依存性、すなわち、vkEventが必要なだけ)
- すきなだけ非コヒーレントなキャッシュ(すなわち、最高のパフォーマンス)でキャッシュラインを読み込む
MECHANICS OF PIPELINING WITH EVENTS
- ディスパッチを分割する
- 分け方はカーネルウィンドウの最大サイズなどで変える必要があるだろう