IVDEP 宣言子は、ベクトル依存性が存在していると推定されてもそれを無視するようコンパイラーに指示します。正しいコードにするため、コンパイラーは、想定される依存性を証明された依存性として扱い、ベクトル化を行わないようにします。この宣言子は、その決定を無視します。推定されたループの依存性が安全で、無視できる場合にのみ IVDEP を使用してください。
例えば、下記のコード・フラグメントで式 j >= 0 が常に true の場合、IVDEP 宣言子はコンパイラーにこの情報を通信することができます。この宣言子は、値 j < 0 の想定されたループ伝播のフロー依存性が安全に無視されることをコンパイラーに知らせます。
例 |
---|
!DEC$ IVDEP do i = 1, 100 a(i) = a(i+j) enddo |
ベクトル化を防ぐ証明された依存性は無視されず、想定された依存性のみが無視されます。
宣言子の使用方法は、ループのフォームにより異なります。次の例を参照してください。
例: ループ 1 |
---|
do i = a(*) + 1 a(*) = enddo |
例: ループ 2 |
---|
do i a(*) = = a(*) + 1 enddo |
フォーム 1 のループの場合、a の古い値を使用しますが、DEF から USE には、ループ伝播のフロー依存性がないと仮定します。
フォーム 2 のループの場合、a の新規の値を使用しますが、USE から DEF には、ループ伝播のアンチ依存性がないと仮定します。
いずれの場合も、ループを分割することが有効で、ループ伝播の出力依存がなくなります。
例 1 |
---|
!DEC$ IVDEP do j=1,n a(j)= a(j+m) + 1 enddo |
例 2 |
---|
!DEC$ IVDEP do j=1,n a(j) = b(j) + 1 b(j) = a(j+m) + 1 enddo |
例 1 では、下位依存の可能性を無視して、ループのソフトウェアのパイプライン化を有効にします。
例 2 は、このループの配列 a と関わる上位依存および下位依存の可能性を示し、依存サイクルを作成しています。IVDEP では、下位依存は無視されます。
IVDEP には、IVDEP:LOOP および IVDEP:BACK の 2 つのオプションがあります。IVDEP:LOOP オプションは、ループ伝播の依存がないことを意味します。IVDEP:BACK オプションは、下位依存がないことを意味します。
IVDEP 宣言子は、IA-64 アーキテクチャー・ベース・アプリケーションでも使用されます。
IVDEP 宣言子のほかにも、ベクトライザーの効率性ヒューリスティックを変更するために使用される VECTOR 宣言子があります。
VECTOR ALWAYS
NOVECTOR
VECTOR ALIGNED
VECTOR UNALIGNED
VECTOR NONTEMPORAL
VECTOR 宣言子は、プログラム中の後に続くループのベクトル化を制御しますが、コンパイラーは入れ子されたループには適用しません。入れ子されたそれぞれのループは、その前に、固有の宣言子が必要です。vector 宣言子は、loop 文の前に配置してください。
VECTOR ALWAYS 宣言子および NOVECTOR 宣言子
VECTOR ALWAYS 宣言子は、ベクトライザーの効率性ヒューリスティックを変更しますが、実際にループのベクトル化が可能な場合にのみこれは動作します。したがって、想定された依存性を無視するには IVDEP を使用します。
VECTOR ALWAYS 宣言子は、次の状況でデフォルトのコンパイラーの動作を変更するのに使用されます。参照が 1 以外のストライドのベクトル化では、通常、速度の向上はみられないので、コンパイラーでは参照が 1 以外のストライドが (1 のストライドの場合より) 多い場合にはベクトル化をデフォルトで行いません。次のループは、ストライド 2 で 2 つの参照があります。
ベクトル化はデフォルトにより無効にされますが、宣言子がこの動作を変更します。
例 |
---|
!DEC$ VECTOR ALWAYS do i = 1, 100, 2 a(i) = b(i) enddo |
一方、ループのベクトル化の回避が望ましい場合 (ベクトル化によりパフォーマンスが向上せずに劣化する場合)、NOVECTOR 宣言子をソーステキストで使用し、ループのベクトル化を無効にします。例えば、コンパイラーは、デフォルトで次のループをベクトル化します。この動作が不適切な場合は、次のように NOVECTOR 宣言子を使用します。
例 |
---|
!DEC$ NOVECTOR do i = 1, 100 a(i) = b(i) + c(i) enddo |
VECTOR ALWAYS と同様に、これらの宣言子も、効率性ヒューリスティックを変更します。異なる点は、UNALIGNED 指示子および ALIGNED 指示子が、すべての配列参照に対して、コンパイラーがそれぞれアライメントの合っていないデータ用の移動命令、およびアライメントされたデータ用の移動命令を使用するように指示することです。これにより、プログラム・コンテキストからアライメント状況を検出したり、参照のアライメントを合わせるダイナミックなループピーリングの使用など、コンパイラーの高度なアライメントの最適化はすべて無効になります。
VECTOR [ALWAYS, UNALIGNED, ALIGNED] 宣言子は、注意して使用してください。コンパイラーの効率性ヒューリスティックの変更は、ベクトル化によりパフォーマンスが向上することが確実である場合にのみ行います。また、アライメントの合ったデータ移動命令ですべての配列参照をコンパイラーに実装すると、アライメントの合っていないアクセスパターンがある場合にランタイム例外が発生します。
VECTOR NONTEMPORAL 宣言子は、IA-32 およびインテル® 64 アーキテクチャー・ベースのシステムでストリーミング・ストアをもたらします。生成されたアセンブリーとのループ (浮動小数点型) の例は、次のとおりです。n が大きくなると、インテル® Pentium® 4 プロセッサー・システムでの非ストリーミング組み込み関数のパフォーマンスが大幅に向上します。
次の例は、コンパイラーに、配列 b ではなく、配列 a のストリーミング・ストアを使用するように指示をする VECTOR NONTEMPORAL 宣言子を示しています。
例 |
---|
subroutine set(a,b,n) integer i,n real a(n), b(n) !DEC$ VECTOR NONTEMPORAL (a) !DEC$ VECTOR ALIGNED do i = 1, n a(i) = 1 b(i) = 1 enddo end program setit parameter(n=1024*1204) real a(n), b(n) integer i do i = 1, n a(i) = 0 enddo call set(a,b,n) do i = 1, n if (a(i)+b(i).ne.2) then print *, 'failed nontemp.f', a(i), i stop endif enddo print *, 'passed nontemp.f' end |