!DIR$ IVDEP 指令は、ループ内で検出された一部またはすべての配列参照のループがもたらす依存関係を無視し、特にほかの方法では実行できないマイクロベクトル化、配布、ソフトウェアパイプラインなどのさまざまなループの最適化を実行するように、コンパイラに指示します。これは、依存関係が重要ではない、または依存関係が実際に発生しないことをユーザーが把握している状況で使用されます。
次に例を示します。
DO I = 1, N A(V(I)) = A(V(I)) + C(I) END DO |
このループでは、A(V(I)) へのいくつかのループがもたらす依存関係があります。V(I) には、インデックス A への複製値が含まれている可能性があり、ループの順序を変更すると、異なる結果になる可能性があります。ただし、V に固有の値のみ含まれていることがわかっている場合は、ループの順序を安全に変更でき、IVDEP 指令を使用して最適化を実行できます。
-xivdep コンパイラオプション (「3.4.133 –xivdep[= p]」 を参照) を使用して、IVDEP 指令の解釈を無効にするか、指定することができます。
IVDEP 指令の従来の解釈の中には、後方へのループがもたらす依存関係がないことを表明するだけのものがあります。Fortran コンパイラのデフォルトは —xivdep=loop です。これは、IVDEP 指令で推測されるループがもたらす依存関係がないことを表明することを示します。
次に、後方および前方への依存関係の例を示します。
do i = 1, n ! BACKWARD LOOP-CARRIED DEPENDENCE ... = a(i-1) ! S1 a(i) = ... ! S2 end do |
do i = 1, n ! FORWARD LOOP-CARRIED DEPENDENCE a(i) = ... ! S3 ... = a(i-1) ! S4 end do |
最初のループは S2 から S1 への後方へのループがもたらす依存関係で、2 つ目のループには、S3 から S4 への前方へのループがもたらす依存関係があります。2 つ目のループには前方への依存関係しかないため、このループは安全に配布やマイクロベクトル化が行えますが、最初のループは行えません。
次に、デフォルト値 -xivdep=loop を指定した IVDEP の使用例を示します。
integer target a(n) integer, pointer :: p(:), q(:) !DIR$ IVDEP do i = 1, n p(i) = q(i) a(i) = a(i-1) end do |
p(i) と q(i) 間、および p(i) と a(*) 間の推測される依存関係は無視されますが、a(i) と a(i-1) 間の明確な依存関係は無視されません。ループは 2 つのループに分割でき、その結果の p(i) = q(i) ループはマイクロベクトル化できます。
IVDEP 指令は、DO ループの直後に適用されます。この指令とループとの間にほかのコードを使用することはできません。!DIR$ IVDEP は、配列代入、FORALL、または WHERE 構文にも適用できます。特定のループに対して複数の指令が存在する場合 (IVDEP や UNROLL など)、コンパイラは可能な限りそれらすべての指令に従います。