ベクトル化の例

このセクションでは、ベクトル・プログラミングの一般的な問題を簡単な例を用いていくつか紹介します。

引数のエイリアシング: ベクトルコピー

この例はベクトルのコピー操作を行うループですが、コンパイラーが DEST(A(I))DEST(B(I)) の相違を証明できないため、ベクトル化は行われません。

例: 相違を証明できないためにベクトル化不可能なコピー

SUBROUTINE VEC_COPY(DEST,A,B,LEN)

DIMENSION DEST(*)

INTEGER A(*), B(*)

INTEGER LEN, I

  DO I=1,LEN

  DEST(A(I)) = DEST(B(I))

END DO

RETURN

END

データのアライメント

16 バイト (Linux* および Mac OS* X) または 64 バイト (Windows*) 以上のデータ構造体または配列は、ベースアドレスが 16 (Linux および Mac OS X) または 32 (Windows) の倍数になるように、各構造体要素または配列要素の先頭をアライメントしなければなりません。

下の図は、間違ってアライメントされたデータが原因でデータ・キャッシュ・ユニット (DCU) が分割した場合の影響を示したものです。アライメントの合っていないデータをロードすると 16 バイト境界にまたがるため、メモリーアクセスが 1 回余分に発生し、その結果、6 ~ 12 サイクルのストールが発生します。データがアライメントされていることがわかっており、このアライメントを使用するよう指定すれば、このストールを回避できます。

16 バイト境界にまたがる間違ってアライメントされたデータ

ベクトル化の実行後、下の図に示すように、ループが実行されます。

ベクトルおよびスカラーのクリーンアップ反復処理

要素 A(1)B(1) が両方とも 16 バイトでアライメントされている場合、ベクトル反復 A(1:4) = B(1:4);A(5:8) = B(5:8); はどちらも、アライメントされた移動によって実現できます。

Caution icon警告

不正なアライメント・オプションでベクトライザーを使用すると、コンパイラーの動作は予測がつかなくなります。特に、アライメントの合っていないデータを、アライメントの合っている移動命令で処理すると、不正命令例外が発生します。

アライメント手法

コンパイラーは、コンパイル時にデータ構造のアライメントが不明な場合に備えて、いくつかのアライメント手法を用意しています。簡単な例を下に示します (これ以外にもいくつかの手法がサポートされています)。次の例のループにおいて、A のアライメントが不明な場合、コンパイラーはプレリュード・ループを生成し、ほとんどの場合に発生する配列参照がアライメントされたアドレスにヒットするまでループを繰り返します。これにより、A のアライメント・プロパティーが判明し、そのプロパティーに応じてベクトルループが最適化されます。この場合、ベクトライザーはインテル® Fortran 特有の機能であるダイナミックなループピーリングを実行します。

データのアライメントの例

例: 元のループ

SUBROUTINE SIMLOOP(A)

REAL A(100)    ! alignment of argument A is unknown

DO I = 1, 100

  A(I) = A(I) + 1.0

ENDDO

END SUBROUTINE

例: データのアライメント

! The vectorizer applies dynamic loop peeling as follows:

SUBROUTINE SIMLOOP(A)

REAL A(100)

! let P be (A%16)where A is address of A(1)

IF (P .NE. 0) THEN

  P = (16 - P)/4   ! determine run-time peeling factor

  DO I = 1, P

    A(I) = A(I) + 1.0

  ENDDO

ENDIF

! Now this loop starts at a 16-byte boundary, and will be

! vectorized accordingly

DO I = P + 1, 100

  A(I) = A(I) + 1.0

ENDDO

END SUBROUTINE