ポインター一義化によりパフォーマンスを向上する

2 つのポインターが同じメモリーの場所を指す場合、両方のエイリアスが作成されます。エイリアスされる可能性のあるポインターを使用してメモリーへ格納すると、一部の最適化を妨げることがあります。例えば、ベクトル化の安全が確保されないループ反復間の依存性が作成される場合があります。エイリアシングだけが潜在的な依存性の原因ではありません。実際、Multiply.c にはほかの依存性が存在します。ただし、この場合、エイリアシングにより生じる依存性を排除することで、ほかのループの依存性を解決できます。

コンパイラーは、ループのベクトル化されたバージョンとベクトル化されていないバージョンの両方を生成し、ランタイム時にテストして最適なコードパスを選択することがあります。ポインターがエイリアスしない場合、それをコンパイラーに知らせると、ランタイム時のチェックは回避され、ベクトル化された単一のコードパスが生成されます。Multiply.c では、コンパイラーは関数 matvec(FTYPE a[][COLWIDTH], FTYPE b[], FTYPE x[]) のポインター ba または x にエイリアスされるかどうかを判断するためにランタイムチェックを生成します。Multiply.c が NOALIAS マクロでコンパイルされると、引数 b の restrict 修飾子は、ポインターがほかのポインターにエイリアスされないこと、特に配列 ba または x とオーバーラップしないことをコンパイラーに知らせます。

restrict 修飾子は、.c または .cpp ファイルでは /Qrestrict コンパイラー・オプション、.c ファイルでは /Qstd=c99 コンパイラー・オプションを使用して指定する必要があります。

NOFUNCCALL プリプロセッサー定義を削除して、matvec() の呼び出しを再度挿入します。NOALIAS プリプロセッサー定義をコンパイラー・オプションに追加します。

プロジェクトをリビルドし、実行ファイルを実行して、出力結果で表示される実行時間を記録してください。Multiply.optrpt に以下のメッセージが出力されます。

ループの開始 Multiply.c(37,5)
Multiply.c(37,5): リマーク #15542: ループはベクトル化されませんでした: 内部ループがすでにベクトル化されています。

ループの開始 Multiply.c(49,9)
ベクトル化のピールループ
ループの終了

ループの開始 Multiply.c(49,9)
Multiply.c(49,9): リマーク #15300: ループがベクトル化されました。
ループの終了

ループの開始 Multiply.c(49,9)
代替アライメントでベクトル化されたループ
ループの終了

ループの開始 Multiply.c(49,9)
ベクトル化の剰余ループ
ループの終了
ループの終了

行番号および列番号は異なる場合があります。

配列がオーバーラップしないことをコンパイラーに知らせたため、コンパイラーは表現認識によりループの依存性を解決し、ループをベクトル化します。

次へ: データのアライメントによりパフォーマンスを向上する