私のマシンには2つのキューファミリがあります。1つはすべてをサポートし、もう1つは転送のみをサポートします。
すべてをサポートするキューファミリのqueueCountは16
。
今スペックは述べています
異なるキューに送信されたコマンドバッファは、並行して実行される場合と、相互に順序が狂う場合があります。
それは、最大のパフォーマンスを得るために、利用可能なすべてのキューを使用する必要があることを意味しますか?
はい。独立性の高いワークロードがある場合は、個別のキューを使用してください。
キュー間で多くの同期が必要な場合、それはあなたが得るかもしれない潜在的な利益を殺すかもしれません。
基本的に、同じキューファミリの場合、GPUに実行可能な代替作業を提供します(そして、ストール、バブル、アイドルを埋め、GPUに選択肢を与えます)。また、CPUをより適切に使用できる可能性があります(たとえば、シングルスレッドとスレッドごとに1つのキュー)。
個別の転送キュー(または他の特殊なファミリ)を使用することも、推奨されるアプローチのようです。
それは一般的に言っています。より現実的、経験的、懐疑的、そして実用的な見方がSWによってすでに提示されており、NBの回答です。実際には、これらのキューは同じリソースを対象とし、同じ制限があり、他の一般的な制限、これから得られる潜在的な利点を制限します。特に、ドライバーが複数のキューで間違ったことをした場合、キャッシュに非常に悪い可能性があります。
このAMDの 同時実行のための非同期キューの活用 (2016)では、HW\driverにどのようにマッピングするかについて少し説明しています。個別のキューファミリを使用することの潜在的な利点を示しています。コンピューティングファミリーの2つのキューを提供していますが、当時はアプリのメリットは見られなかったとのことです。彼らは、グラフィックキューが1つしかないことと、その理由を説明しています。
NVIDIAは「非同期コンピューティング」について同様の考えを持っているようです。 Vulkanへの移行:非同期計算 に示されています。
安全のために、現在のハードウェアでは、グラフィックスを1つだけ、非同期計算キューを1つだけ使用する必要があるようです。 16のキューは罠のようであり、自分を傷つける方法のようです。
転送キューを使用すると、見た目ほど単純ではありません。ホスト->デバイス転送には専用のものを使用する必要があります。また、非専用は、デバイス->デバイス転送操作に使用する必要があります。
何のために?
遅延レンダラーの典型的な構造を考えてみましょう。 gバッファを作成し、ライティングパスを実行し、後処理とトーンマッピングを実行し、透明なものを投入して、最終的な画像を表示します。各プロセスは、開始する前に完了した前のプロセスに依存します。 g-bufferが終了するまで、ライティングパスを実行することはできません。などなど。
複数の実行キュー間でそれをどのように並列化できますか?これらのコマンドはすべて同じ添付画像に書き込んでいるため、g-bufferの構築またはライティングパスを並列化することはできません(複数のキューから並列化することはできません)。また、同じ画像に書き込んでいない場合は、結果の画像を組み合わせて最終的な画像にするキューを選択する必要があります。また、同じ深度バッファを使用しないと、深度バッファリングがどのように機能するかわかりません。
そして、その組み合わせステップには同期が必要です。
現在、並列化できるタスクがたくさんあります。錐台カリングを行う。パーティクルシステムの更新。メモリ転送。そういうもの; nextフレームを対象としたデータ。しかし、現実的に一度にいくつのキューをビジー状態に保つことができますか? 3?多分4?
言うまでもなく、スケーリング可能なレンダリングシステムを構築する必要があります。 Vulkanでは、実装が複数のキューを提供する必要はありません。したがって、コードは、1つのキューのみを提供するシステムと16を提供するシステムで適切に実行できる必要があります。また、16キューのシステムを利用するには、レンダリングを大きく変える必要があります。
ああ、そしてあなたがたくさんのキューを要求したが、それらを使用しない場合、パフォーマンスに影響を与える可能性があることに注意してください。 8つのキューを要求する場合、実装では、8つのコマンドセットを同時に発行できると想定するしかありません。つまり、ハードウェアはすべてのリソースを単一のキュー専用にすることはできません。したがって、そのうちの3つしか使用しない場合は、実装が使用を待機しているリソースに対して、潜在的なパフォーマンスの50%以上が失われる可能性があります。
確かに、実装はそのようなものを動的にスケーリングできます。しかし、この特定のケースをプロファイリングしない限り、あなたは決してわかりません。ああ、それが動的にスケーリングする場合...このように複数のキューを使用しても多くのことを得ることができません。
最後に、 いくつかのプラットフォームで、複数のキューの送信がGPUの供給を維持するのにどれほど効果的であるかについて、いくつかの調査がありました(すべての部分を読んでください) 。それの一般的な長短は次のように思われます:
それは実際のシナリオと設定に強く依存します。詳細がないとわかりにくいです。
コマンドバッファを複数のキューに送信する場合は、適切な同期も行う必要があります。これが正しく行われないと、1つのキューを使用するよりも実際にパフォーマンスが低下する可能性があります。
1つのキューにのみ送信する場合でも、実装はコマンドバッファを並列に実行し、順序が狂って(別名「実行中」)実行する可能性があることに注意してください。詳細については、章 を参照してください。仕様の2.2 または このAMDプレゼンテーション 。
コンピューティングとグラフィックスを行う場合、同時送信(および同期)で別々のキューを使用すると、非同期コンピューティングをサポートするハードウェアのパフォーマンスが向上します。
したがって、実際のユースケースを知らなければ、これについて明確な「はい」または「いいえ」はありません。
同じキューで複数の独立したワークロードを送信でき、それらの間に暗黙の順序保証がないように見えるため、キューファミリを飽和させるために実際には複数のキューは必要ありません。したがって、複数のキューの唯一の目的は、デバイスの作成時に指定されたように、キュー間で異なる優先順位を許可することだと思います。
この回答が受け入れられた回答と直接矛盾していることは知っていますが、その回答では、より多くの並列作業をデバイスに送信するためにさらにキューを必要としないという問題に対処できません。