ユーザー指示または SIMD ベクトル化

ユーザー指示または SIMD ベクトル化は、OpenMP* 並列化が自動並列化を補足するように、自動ベクトル化を補足します。下記の図でこの関係を示します。ユーザー指示によるベクトル化は SIMD (Single-Instruction, Multiple-Data) 機能として実装され、SIMD ベクトル化と呼ばれます。

SIMD ベクトル化機能は、インテル製マイクロプロセッサーおよび互換マイクロプロセッサーの両方で利用可能です。ベクトル化により呼び出されるライブラリー・ルーチンは、互換マイクロプロセッサーよりもインテル製マイクロプロセッサーにおいてより優れたパフォーマンスが得られる可能性があります。

次の図は、ハードウェアのベクトル化機能を活用するベクトル化コードを生成するためのさまざまなアプローチの中で、SIMD ベクトル化がどこに位置付けされているかを示しています。SIMD ベクトル化を用いて記述されたプログラムは、自動ベクトル化ヒントを使用して記述されたものと似ています。SIMD ベクトル化を使用すると、ベクトル化コードの取得に必要なコードの変更を最小限にすることができます。

SIMD ベクトル化は #pragma omp simd プラグマを使用してループをベクトル化します。

関数 add_floats() が不明なポインターを多く使用しているため、コンパイラーの自動ランタイム独立性チェックにより最適化が行われる C++ の例ついて考えてみます。#pragma ivdep の自動ベクトル化ヒントを使ってデータ依存性のアサーションを追加し、自動ベクトル化の最適化をループに適用するかどうかコンパイラーに判断させることができます。または、#pragma omp simd を使用して、このループのベクトル化を実行することができます。

#pragma omp simd と自動ベクトル化ヒントの主な違いは、#pragma omp simd では、コンパイラーはループをベクトル化できない場合に警告を発行します。自動ベクトル化ヒントでは、#pragma vector always ヒントを使用した場合でも、実際のベクトル化はコンパイラーの判断にまかせられます。

#pragma omp simd にはオプション節があり、コンパイラーにベクトル化の方法を指示できます。コンパイラーが正しいベクトル化コードを生成するための十分な情報を得られるように、これらの節を適切に使用してください。節についての詳細は、#pragma omp simd の説明を参照してください。

追加のセマンティクス

omp simd プラグマの使用に関して、次の点に注意してください。

  • 変数は private、linear、reduction のいずれかに属します (またはいずれにも属しません)。

  • ベクトルループ内では、private、linear、reduction の場合、式はベクトル値として評価されます。または、ベクトル値に評価される部分式があります。そうでない場合、スカラー値として評価されます (つまり、同じ値をすべての反復にブロードキャストします)。スカラー値は、よくループ不変として使用されますが、必ずしもループ不変であるわけではありません。

  • ベクトル値はスカラー型の左辺値へ割り当てられません。エラーになります。

  • スカラー型の左辺値はベクトル条件下では割り当てられません。エラーになります。

  • switch 文はサポートされていません。

一部の自動ベクトル化が可能なループでは、SIMD プラグマを使用してベクトル・セマンティクスを表現するのは難しいかもしれません。例えば、C には MIN/MAX 演算子がないため、C で MIN/MAX リダクションを表現するのは困難です。

#pragma omp declare simd 宣言の使用に関する制約

ベクトル化は、ハードウェアとソースコードのスタイルという 2 つの主な要因により制約されます。vector 宣言を使用する場合、使用できない機能は次のとおりです。

  • 、OpenMP* parallel/for/sections/task/target/teams、および明示的なスレッド API 呼び出しによるスレッドの生成と join

  • ロック、バリア、atomic 構文、クリティカル・セクション (#pragma omp ordered simd ブロック内で許可される)

  • インライン・アセンブリー・コード、VM、ベクトル組込み関数 (例: SVML 組込み関数)

  • setjmp、longjmp、SHE、計算型 GOTO の使用

  • EH は許可されず、すべてのベクトル関数は noexcept と見なされる

  • switch 文 (場合によっては、if 文に変換されますが、必ず変換されるとは限りません)

  • exit()/abort() 呼び出し

非ベクトル関数呼び出しは、一般にベクトル関数内で許可されますが、そのような関数への呼び出しはレーン単位でシリアル化されるため、パフォーマンスが低下します。また、SIMD 対応関数では、引数による書き込みを除く副作用があってはなりません。非ベクトル関数は、この規則に反するため、SIMD 対応関数で実行する場合には注意が必要です。

仮引数は次のデータ型でなければなりません。

  • 符号付き (なし) 8、16、32、または 64 ビット整数
  • 32 または 64 ビット浮動小数点
  • 64 または 128 ビット複素数
  • ポインター (C++ 参照はポインター型と見なされる)

関連情報