厳格で厳格なルールはありません。CUDA コンパイラには少なくとも 2 つのアンローラーがあり、それぞれ NVVM または Open64 フロントエンド内に 1 つ、PTXAS バックエンド内に 1 つです。一般に、これらはループを非常に積極的に展開する傾向があるため、#pragma unroll 1
(展開を防ぐために) 他のどの展開属性よりも頻繁に使用しています。ループ展開をオフにする理由は 2 つあります。
(1) ループが完全に展開されると、レジスタ圧力が増加する可能性があります。たとえば、小さなローカル メモリ配列へのインデックスは、コンパイル時の定数になる可能性があり、コンパイラはローカル データをレジスタに配置できます。完全なアンロールは、基本ブロックを長くする傾向があるため、テクスチャとグローバル ロードのより積極的なスケジューリングが可能になり、追加の一時変数とレジスタが必要になる場合があります。レジスタ プレッシャーが増加すると、レジスタ スピルが原因でパフォーマンスが低下する可能性があります。
(2) 部分的に展開されたループは通常、展開係数の正確な倍数ではないループ カウントを処理するために、ある程度の事前計算とクリーンアップコードを必要とします。トリップ カウントが短いループの場合、このオーバーヘッドにより、展開されたループから得られるパフォーマンスの向上が失われ、展開後のパフォーマンスが低下する可能性があります。コンパイラには、これらの制限の下で適切なループを見つけるためのヒューリスティックが含まれていますが、ヒューリスティックが常に最適な決定を提供できるとは限りません。
まれに、コンパイラが自動的に使用するものよりも高い展開係数を手動で指定すると、パフォーマンスにわずかな効果があることがわかりました (通常は 1 桁の割合で向上します)。これらは通常、展開係数が大きいほどグローバルまたはテクスチャの読み込みのより積極的なスケジューリングが可能になる、メモリ集約型のコードのケース、またはループ オーバーヘッドの最小化の恩恵を受ける非常にタイトな計算バインド ループのケースです。
コンパイラのデフォルトは、実際に遭遇するほとんどのケースをカバーするため、アンローリング係数をいじることは、最適化プロセスの後半で行う必要があります。