11

HLSL には 1 つのピクセル シェーダーがあり、いくつかの場所でわずかに異なるものに使用されます。そのため、いくつかの条件付きブロックがあり、場合によっては複雑な機能が省略されることを意味します。同様に、これは、常に使用されるとは限らないサンプラー パラメーターとしてテクスチャを渡すことを意味します。

これら 2 つのことが追加されてどれだけのパフォーマンスが影響を受けるかはわかりませんが、特に統合グラフィックス チップで SM2.0 をサポートしているため、非効率性が問題になっています。では、テクスチャを渡して使用しないことは、余分なオーバーヘッドを意味するのでしょうか? また、 を使用するifと、いくつかの命令を追加するだけで機能しますか? それとも、CPU の最適化を行うときのように、ストールなどのために劇的に影響を与える可能性がありますか?

4

1 に答える 1

22

GPU でテクスチャを設定するには CPU 時間がかかりますが、実際のバッチコストと比較するとかなり小さいです。さらに重要なことは、シェーダーがそれを参照しない場合、実際のシェーダーの実行にまったく影響を与えないことです。

現在、分岐を処理できる方法は 3 つあります。

まず第一に、分岐条件が常に同じになる場合 (コンパイル時の定数のみに依存する場合)、分岐の片側を完全にインライン化できます。多くの場合、この方法で重要な分岐を排除できる場合は、シェーダーの複数のバージョンをコンパイルすることをお勧めします。

2 番目の手法は、シェーダーが分岐の両側を評価し、条件に基づいて正しい結果を選択できるというものです。実際に分岐する必要はありません (算術的に分岐します)。これは、ブランチ内のコードが小さい場合に最適です。

最後に、実際に分岐命令を使用できます。まず第一に、分岐命令の命令数のコストは控えめです。そして、パイプラインがあります。x86 には長いシリアル パイプラインがあり、簡単にストールする可能性があります。GPU には、まったく異なる並列パイプラインがあります。

GPU はフラグメント (ピクセル) のグループを並行して評価し、一度に複数のフラグメントに対してフラグメント プログラムを 1 回実行します。グループ内のすべてのフラグメントが同じ分岐を取る場合、その分岐の実行コストのみが発生します。それらが 2 つ (またはそれ以上) のブランチを取る場合、すべてのブランチをカバーするために、そのフラグメントのグループに対してシェーダーを複数回実行する必要があります。

フラグメント グループには画面上の局所性があるため、ブランチに同様の画面上の局所性があると役立ちます。次の図を参照してください。


(ソース: nvidia.com )

現在、シェーダー コンパイラは通常、最後の 2 つの方法のどちらを使用するかを非常に適切に選択します (最初の方法では、コンパイラがインライン化しますが、複数のシェーダー バージョンを自分で作成する必要があります)。ただし、パフォーマンスを最適化している場合は、コンパイラの実際の出力を確認すると便利です。このためfxc.exeに、DirectX SDK ユーティリティで/Fc <file>オプションを使用して、コンパイルされたシェーダーの逆アセンブリ ビューを取得します。

(これはパフォーマンスに関するアドバイスです。常にパフォーマンスを測定し、到達している制限を把握し、最適化について心配することを忘れないでください。たとえば、テクスチャ フェッチにバインドされている場合は、シェーダー ブランチを最適化しても意味がありません。)

追加の参照: GPU Gems 2: Chapter 34. GPU Flow-Control Idioms .

于 2011-03-19T12:17:31.777 に答える