プリフェッチのサポート

データ・プリフェッチとは、アプリケーションによってデータが必要になる前に、メモリーよりも高速なキャッシュにデータをロードしておくことです。データ・プリフェッチの動作はアーキテクチャーによって異なります。

ほとんどの場合、プリフェッチ命令を発行するとパフォーマンスが向上します。ただし、プリフェッチ命令を発行することでアプリケーションのパフォーマンスが低下する場合もあります。このような場合、プリフェッチを調整します。コンパイラー・オプションでプリフェッチをオンまたはオフにすると、他の最適化はそのままでプリフェッチによるパフォーマンス低下の原因を追求するのに役立ちます。コンパイラー・オプションを使用したデータのプリフェッチに関する詳細は、「オプションを使用したプリフェッチ」を参照してください。

プリフェッチ命令を発行するには 2 つの方法があります。1 つはコンパイラー宣言子、もう 1 つはコンパイラー組み込み関数を使用する方法です。

PREFETCH 宣言子と NOPREFETCH 宣言子

PREFETCH 宣言子および NOPREFETCH 宣言子は、インテル® Itanium® プロセッサーでのみサポートされています。これらの宣言子は、データ・プリフェッチがメモリー参照に生成されるか、されないかを指定します。これは、コンパイラーが使用するヒューリスティックに影響します。

ループの前に PREFETCH A を置いて、ループ内で式 A(j) を使用する場合、コンパイラーはループ内の A(j+d) のプリフェッチを挿入します。d はデータをプリフェッチするための残りの反復回数で、コンパイラーによって決定されます。この宣言子は、最適化レベルが -O1 (Linux) または /O1 (Windows) よりも高い場合にサポートされます。-O2 および /O2 は、デフォルトの最適化レベルである点に注意してください。

!DEC$ NOPREFETCH c

!DEC$ PREFETCH a

  do i = 1, m

    b(i) = a(c(i)) + 1

  enddo

次の例は、IA-64 アーキテクチャーでのみ有効です。

do j=1,lastrow-firstrow+1

i = rowstr(j)

iresidue = mod( rowstr(j+1)-i, 8 )

sum = 0.d0

!DEC$ NOPREFETCH a,p,colidx

do k=i,i+iresidue-1

  sum = sum + a(k)*p(colidx(k))

enddo

!DEC$ NOPREFETCH colidx

!DEC$ PREFETCH a:1:40

!DEC$ PREFETCH p:1:20

do k=i+iresidue, rowstr(j+1)-8, 8

  sum = sum + a(k)*p(colidx(k))

  &      + a(k+1)*p(colidx(k+1)) + a(k+2)*p(colidx(k+2))

  &      + a(k+3)*p(colidx(k+3)) + a(k+4)*p(colidx(k+4))

  &      + a(k+5)*p(colidx(k+5)) + a(k+6)*p(colidx(k+6))

  &      + a(k+7)*p(colidx(k+7))

enddo

q(j) = sum

enddo

組み込み関数

コンパイラー組み込み関数を挿入する前に、サポートされる他のコンパイラー・オプションと宣言子を試してみてください。コンパイラー組み込み関数は、コンパイラー・オプションやコンパイラー宣言子よりも、移植性および柔軟性が低くなります。

宣言子は、コンパイラーの最適化を有効にしますが、組み込み関数は最適化を実行します。宣言子を使用したプログラムは移植性が高いため、コンパイラーは別のプロセッサーに適用することができますが、組み込み関数を使用したプログラムを別のプロセッサーに適用するには、書き換えや移植が必要です。これは、組み込み関数がアセンブリー言語のプログラミングに近いためです。

コンパイラーは、組み込み関数サブルーチンの mm_prefetch をサポートしています。prefetch 宣言子がメモリーからのデータ・プリフェッチを有効にするのに対して、サブルーチン mm_prefetch は、1 つのメモリー・キャッシュ・ライン上の指定のアドレスからデータをプリフェッチします。mm_prefetch サブルーチンについては、「Language Reference」(英語) で説明されています。