ここで説明するディレクティブはベクトル化をサポートします。
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
CDEC$ IVDEP
do j=1,n
a(j) = a(j+m) + 1
enddo
例 2
CDEC$ 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 ディレクティブは、Itanium® ベース・アプリケーションに対しても -ivdep_parallel オプションとともに使用されます。
ディレクティブの詳細は、『Intel® Fortran Language Reference』(英語) の「General Directives」セクションにある「Directive Enhanced Compilation」を参照してください。
IVDEP ディレクティブのほかにも、ベクトライザの効率性ヒューリスティックを変更するのに使用されるディレクティブがあります。
VECTOR ALWAYS
NOVECTOR
VECTOR ALIGNED
VECTOR UNALIGNED
VECTOR NONTEMPORAL
VECTOR ディレクティブは、 プログラム中の後に続くループのベクトル化を制御しますが、コンパイラはネストされたループには適用しません。ネストされたそれぞれのループは、その前に、固有のディレクティブが必要です。VECTOR ディレクティブは、ループ制御文の前に配置してください。
ディレクティブの詳細は、『Intel® Fortran Language Reference』(英語) の「General Directives」にある「Directive Enhanced Compilation」を参照してください。
VECTOR ALWAYS ディレクティブは、ベクトライザの効率性ヒューリスティックを変更しますが、実際にループのベクトル化が可能な場合にのみこれは動作します。従って、想定された依存性を無視するには IVDEP を使用します。
VECTOR ALWAYS ディレクティブは、次の状況でデフォルトのコンパイラの動作を変更するのに使用されます。参照が 1 以外のストライドのベクトル化では、通常、速度の向上はみられないので、コンパイラでは参照が 1 以外のストライドが (1 のストライドの場合より) 多い場合にはベクトル化をデフォルトで行いません。次のループは、stride 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
ディレクティブの詳細は、『Intel® Fortran Language Reference』(英語) の「General Directives」にある「Directive Enhanced Compilation」を参照してください。
VECTOR ALWAYS と同様に、これらのディレクティブも、効率性ヒューリスティックを変更します。異なる点は、UNALIGNED 指示子および ALIGNED 指示子が、すべての配列参照に対して、コンパイラがそれぞれアライメントの合っていないデータ用の移動命令、およびアライメントされたデータ用の移動命令を使用するように指示することです。これにより、プログラム・コンテキストからアライメント状況を検出したり、参照のアライメントを合わせるダイナミックなループ・ピーリングの使用など、コンパイラの高度なアライメントの最適化はすべて無効になります。
注
ディレクティブ VECTOR [ALWAYS, UNALIGNED, ALIGNED] は、注意して使用してください。コンパイラの効率性ヒューリスティックの変更は、ベクトル化によりパフォーマンスが向上することが確実である場合にのみ行います。また、アライメントの合ったデータ移動命令ですべての配列参照をコンパイラに実装すると、アライメントの合っていないアクセスパターンがある場合にランタイム例外が発生します。
ディレクティブの詳細は、『Intel® Fortran Language Reference』(英語) の「General Directives」にある「Directive Enhanced Compilation」を参照してください。
VECTOR NONTEMPORAL ディレクティブは、Pentium® 4 プロセッサ・ベース・システムのストリーミング・ストアをもたらします。生成されたアセンブリとのループ (浮動小数点型) の例は、次のとおりです。n が大きくなると、Pentium 4 プロセッサ・システムでの非ストリーミング組込み関数のパフォーマンスが大幅に向上します。
次に、VECTOR NONTEMPORAL ディレクティブの使用例を示します:
subroutine
set(a,n)
integer
i,n
real a(n)
!DEC$ VECTOR NONTEMPORAL
!DEC$ VECTOR ALIGNED
do i =
1, n
a(i)
= 1
enddo
end
program
setit
parameter(n=1024*1204)
real a(n)
integer
i
do i =
1, n
a(i)
= 0
enddo
call set(a,n)
do i =
1, n
if
(a(i).ne.1) then
print
*, 'failed nontemp.f', a(i), i
stop
endif
enddo
print *,
'passed nontemp.f'
end
ディレクティブの詳細は、『Intel® Fortran Language Reference』(英語) の「General Directives」にある「Directive Enhanced Compilation」を参照してください。