さらに、ループ内のすべての操作が他の反復から完全に独立していると仮定して、コンパイラーはループを展開する範囲をどのように決定しますか。
2 に答える
MSVCの場合、ベクトルに依存しないヒントのみがあります:http: //msdn.microsoft.com/en-us/library/hh923901.aspx
#pragma loop( ivdep )
Intel / ibmのような他の多くのコンパイラーの場合、ループを最適化するためのいくつかのプラグマのヒントがあります。
#pragma unroll
#pragma loop count N
#pragma ivdep
ヒューリスティックの展開に関するMSVC++の人々とのスレッドがあります:http ://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/d0b225c2-f5b0-4bb9-ac6a-4d4f61f7cb17/
VCは、実行速度とコードサイズのバランスをとろうとします。フラグ/O1または/O2を使用してバランスを変更できますが、速度を最適化する場合でも、VCはコードサイズも節約しようとします。
基本的に、展開するとコードサイズが大きくなるため、OsモードとO1モードでは制限される場合があります(モードテーブル) 。
PS:Pragmaはプリプロセッサディレクティブのように見えますが、そうではありません。これはコンパイラー用のディレクティブであり、プリプロセッサーによって無視(保持)されます。
インテル®コンパイラーの場合:
#pragma loop count Nは、コンパイラがループをベクトル化するために最適な戦略を使用するのに役立ちます。時間を節約できるので、ループの展開を促進するのに役立つと言えます。例:
#pragma loop_count min(n),max(n),avg(n)
#pragma unroll(n)は、-O3フラグとともに使用された場合にのみ機能します。次の戦略を使用して、ターゲットプロセッサに従ってループを展開できます。
ループ展開によって生成されるコードの増加に加えて、コンパイラーはスカラー演算とベクトル演算のループバージョンを生成するため、価値があるかもしれません。
たとえば、展開がパフォーマンスに影響を与えている場合、ベクトルの長さが16で20回の反復を行うループは、一度に16回の操作を実行する1回のループと、4回連続して実行される残りのループになります。コンパイラによって生成される残りのループを回避するために、ループの前に使用できます。
#pragma vector novecremainder //or -mP2OPT_hpo_vec_peel = F to disable peel and remainder loops (compiler internal option)
また
#pragma nounroll //where unrolling is not worth at all
#pragma ivdepを明確にするためだけに:
- これは、依存関係に関するコンパイラのヒューリスティックを変更するための特定のヒントを提供し、想定される依存関係を無視しても安全であることがわかっている場合にのみ使用する必要があります。
- 最も重要なのは、潜在的な依存関係をオーバーライドすることですが、コンパイラーは依存関係分析を実行します。分析に関係なく、#pragmasimdを使用してベクトル化してみてください。
お役に立てれば。