Skip to content
Go back

Deep Dive: Asynchronous Compute

· Updated:

url

拙訳

両雄集結(Joint Session)

🟥AMD

  • Graphics Core Next (GCN)
  • Compute Unit (CU)
  • Wavefronts

🟩NVIDIA

  • Maxwell、Pascal
  • Streaming Multiprocessor (SM)
  • Warps

用語(Terminology)

非同期Asynchronous: 独立ではなく、非同期ワークはハードウェアを共有する

ワークペアリングWork Pairing: 同時に実行するGPUワークのアイテム

非同期税Async. Tax: 非同期コンピュートに関連するオーバーヘッドコスト

非同期コンピュート→更なるパフォーマンス(Async Compute -> More Performance)

キューの基礎(Queue Fundamentals)

  • 3種のキュー
    • コピー/DMAキュー
    • コンピュートキュー
    • グラフィクスキュー

すべて非同期的に動作する!

一般的なアドバイス(General Advice)

  • 常にプロファイルする!
    • パフォーマンスを作ったり打ち破ったりできる
  • 非同期でないパスを維持する
    • 非同期のオン/オフをプロファイルする
    • いくつかのハードウェアは非同期をサポートしないだろう
  • ハイパースレッディングの仲間?
    • 似たようなルールが適用される
    • 共有ハードウェアリソースの帯域幅調整throttlingを回避する

Regime Pairing

  • 上手なペアリング
    • グラフィクス
      • シャドウレンダリング(ジオメトリ制限)
    • コンピュート
      • ライトカリング(ALUヘビー)
  • 下手なペアリング
    • グラフィクス
      • Gバッファ(帯域幅制限)
    • コンピュート
      • SSAO(帯域幅制限)

(テクニックのペアリングは1対1でなくてもよい)

🚩 --- 赤い旗(🚩 - Read Flags)

問題/解決策の形式

トピックス

  • 🟥リソース競合 --- AMD
  • 🟩デスクリプタヒープ --- NVIDIA
  • 同期モデル
  • “非同期コンピュート税”の回避

🟥ハードウェアの詳細 --- AMD(🟥Hardware Details - AMD)

  • CUあたり4つのSIMD
  • SIMDあたり最大10個のWavefrontがスケジュールされる
    • レイテンシーの隠蔽を達成する
    • グラフィクスとコンピュートが同じCUで同時に実行できる
  • グラフィクスのワークロードは通常ではコンピュートより大きい優先度を持つ

🚩🟥リソース競合 --- AMD(🚩 🟥Resource Contention - AMD)

問題: SIMDごとのリソースはWavefronts間で共有される

SIMDは(異なるシェーダの)Wavefrontsを実行する

  • 占有率は以下によって制限される
    • レジスタ数
    • LDSの量
    • 他の制限が適用されるかも…
  • Wavefrontsはキャッシュを求めて競合する

🚩🟥リソース競合 --- AMD(🚩 🟥Resource Contention - AMD)

  • ベクタレジスタ(VGPR)数に目を配る
GCN VGPR数24以下28323640486484128以下128超
最大SIMDあたりのWave数10987654321
  • キャッシュスラッシングに気を付けて!
    • ダミーLDSを割り当てることで占有率を制限してみる

🟩ハードウェア詳細 --- NVIDIA(🟩Hardware Details - NVIDIA)

  • コンピュートはSM全体に幅優先breadth firstでスケジュールされる
  • コンピュートワークロードはグラフィクス以上の優先度を持つ
    • ドライバはSMの分散をヒューリスティックに制御する

🚩🟩デスクリプタヒープ --- NVIDIA(🚩🟩Descriptor Heap - NVIDIA)

問題: ハードウェアはひとつしか持てない --- アプリケーションはたくさん生成できる

デスクリプタヒープの切り替えは(現在のハードウェアでは)ハザードになり得る

  • GPUはヒープを切り替える前にワークを空にしdrainなければならない
  • CBV/SRV/UAV サンプラヒープに適用する
  • (冗長な変更はフィルタリングされる)
  • D3D: CLごとにSetDescriptorHeapを呼ばなければならない

🚩🟩デスクリプタヒープ --- NVIDIA(🚩🟩Descriptor Heap - NVIDIA)

デスクリプタ(すべてのヒープ)の総数がプールサイズより小さいとハザードを回避する

プールサイズ(🟩Kepler+)

  • CBV/UAV/SRV = 1048576
  • サンプラ = 2048個 + 2032個(静的) + 16個(ドライバ所有)
  • 注意NB [1048575|4095] -> [0xFFFFF|0xFFF] -> (32ビットにパックされる)

🚩同期(🚩 Synchronization)

考慮すべきGPU同期モデル

  • 撃ちっぱなしfire-and-forget
  • ハンドシェイク

CPUもやることがある

  • ExecuteCommandLists(ECLs)はGPUワークをスケジュールする
  • CPUでのECLs間の隙間はGPUに翻訳できる

🚩撃ちっぱなし(同期)(🚩 Fire-and-Forget (Sync.))

  • ワークの開始はフェンスを介して同期される

🚩撃ちっぱなし(同期)(🚩 Fire-and-Forget (Sync.))

  • ワークの開始はフェンスを介して同期される
  • しかし、いくつかのワークロードはフレームごとに変化する
  • この変化が望ましくないワークペアリングを引き起こす
  • 悪いペアリングはパフォーマンスに影響を及ぼすので、全体フレーム時間に影響を及ぼす

🚩CPUレイテンシー(同期)(🚩 CPU Latency (Sync.))

  • 同様のシチュエーション --- ここではCPUが役割を果たす

🚩CPUレイテンシー(同期)(🚩 CPU Latency (Sync.))

  • 同様のシチュエーション --- ここではCPUが役割を果たす
  • ゲームはECLs間のCPUでのレイテンシーを導入する
  • レイテンシーはGPUに翻訳できる
  • 望ましくないワークペアリングなどを引き起こす…

🚩ハンドシェイク(同期)(🚩 Handshake (Sync.))

  • ワークペアリングの開始と終了を同期する
  • ペアリング決定論を保証する
  • いくつかの非同期の機会を捕らえ損なうかも(ハードウェア管理可能)
  • あなたのコードをfuture proofにする!

🚩同期 --- アドバイス(🚩 Synchronization - Advice)

CPUは純真潔白ではない、目を配ろう

2つのGPU同期モデル

  • 撃ちっぱなし :(
    • 反対: 非決定的なregimeペアリング
    • 賛成: 少ない同期 == より即時的なパフォーマンス(ベストケースのシナリオ)
  • ハンドシェイク :)
    • 反対: 追加の同期がパフォーマンスを低下させるかも
    • 賛成: regimeペアリング決定論(いつでも)

決定論(と同様に正確性)のために同期する

🚩非同期税(🚩 Async. Tax)

非同期コンピュートに関するオーバーヘッドコスト

  • 定量化: [AC無効化時(ms)] / [直列化したACの有効化時(ms)] %
    • グラフィクスAPIを介して手動でシリアライズする
  • ACゲインを簡単にノックアウトできる!

🚩非同期税 --- 根本的な原因(🚩 Async. Tax - Root Cause

CPU:

  • 非同期タスクを組織化/スケジュールする追加のCPUワーク
  • 同期/ExecuteCommandListsのオーバーヘッド

GPU:

  • 同期のオーバーヘッド
  • ACのオン/オフの間で使われるシェーダが異なる
  • 追加のバリア(キュー間同期)

🚩非同期税 --- アドバイス(🚩 Async. Tax - Advice

最初に: CPUまたはGPUがボトルネックかどうかを決定する (GPUView)

CPU:

  • フレームあたりのAPI呼び出しを数えて、ACのオン/オフの差を比較する
  • スレッド毎のプロファイリングを通して差異を計測する

GPU:

  • ACのオン/オフのシェーダのGPUコストを比較する
  • Inspect difference contributors

ツール(Tools)

  • APIタイムスタンプ: 非同期コンピュートを有効化/無効化する時間
  • GPUView: (次スライドへ続く)

GPU Viewその1(GPU View #1)

  • 3D、コンピュート、コピーを使用
  • フレーム境界 @ Flipキューパケット
  • フレーム毎のグラフィクスにオーバーラップするコンピュート

GPU Viewその2 --- マーカー(GPU View #2 - Markers)

注意 Ctrl+eで開く

説明

  • Time: GPUの正確な時間
  • DataSize: Dataのバイトサイズ
  • Data: PIXBegin/EndEventでemitされたイベント名
    • バイト配列 -> ASCII/Unicode
    • 手動ステップ :(

GPU Viewその3 --- イベント(GPU View #3 - Events)

CPUタイムライン:

  • ID3D12Fence::Signal
    • DxKrnl --- SignalSynchronizationObjectFromCpu
  • ID3D12Fence::Wait
    • DxKrnl --- WaitSynchronizationObjectFromCpu

GPUタイムライン:

  • ID3D12CommandQueue::Signal
    • DxKrnl --- SignalSynchronizationObjectFromGpu
  • ID3D12CommandQueue::Wait
    • DxKrnl --- WaitSynchronizationObjectFromGpu

ありごとうございました(Thanks \0)

ご質問は?