OpenMP は最初の仕様書 1.0 が公開された後、2.0、2.5、3.0 とバージョンアップを重ね、現在は 2011年 7月に公開された 3.1 仕様が最新となっています。
仕様ごとに機能強化が行われているため、皆さんが利用するコンパイラーが OpenMP のどの仕様をサポートしているか知っておく必要があります。C/C++ および Fortran とも _OPENMP マクロを利用することで OpenMP 仕様のバージョンを知ることができ、このマクロは、プリプロセッサーとコンパイラー両方で条件付きコンパイルに利用できます。
_OPENMP マクロは、OpenMP 仕様がリリースされた年月を YYYYMM 形式の数値で返します。各 OpenMP 仕様が返す値は次のようになります。バージョン 2.5 以前は C/C++ と FORTRAN でマクロが返す値は異なりますが、2.5 からは統一されています。
仕様 | 言語 | 値 | インテル® コンパイラーのバージョン |
1.0 | FORTRAN | 199710 | 5.x |
1.1 | FORTRAN | 199911 | 6.x |
1.0 | C/C++ | 199811 | 6.x |
2.0 | FORTRAN | 200011 | 7.x, 8.x |
2.0 | C/C++ | 200203 | 7.x, 8.x |
2.5 | C/C++、FORTRAN | 200505 | 9.x, 10.x |
3.0 | C/C++、FORTRAN | 200805 | 11.x, 12.0 |
3.1 | C/C++、FORTRAN | 201107 | 12.1 |
例えば C 言語の場合、printf(“OpenMP version %d\n”, _OPENMP) でコンパイラーがサポートする仕様がリリースされた年月を表示できます。
OpenMP は幾つかの API をサポートしていますが、#pragma omp parallel や c$OMP PARALLEL 指示句は、コンパイラーに OpenMP 指示句の解釈を指示するオプション(-openmp)を指定しなければ無視されますが、API はリンク時にエラーとなります。
_OPENMP マクロを利用することで、次のような条件付きコンパイルが可能です。
#ifdef _OPENMP int thread_num = omp_get_thread_num(); #endifまた、仕様が異なる指示句の切り分けにも利用できます。例えば、C/C++ の OpenMP 2.0 では for 指示句を利用する for ループのループインデックスは、符号付き整数でなければいけませんが、3.0 ではそれ以外(符号なし整数やポインターなど)の幾つかのパターンが許されます。
#if (_OPENMP >= 200805) #pragma omp parallel for for( int *i = ptr; i < (i + MAX); i++) *i = 0; #else if (_OPENMP < 200805) #pragma omp parallel for for( int i = 0; i < MAX; i++) a[i] = 0; #endifVisual C++ 2005 以降 2010 までは、OpenMP 2.0 の使用をサポートしていますので、Visual C++ を利用する場合 OpenMP 2.0 の仕様の範囲で並列構文を記述しなければいけません。GCC の場合は、4.2 以降 OpenMP を正式サポートしていますので、利用する GCC のバージョンでどの OpenMP 仕様が利用できるか、_OPENMP マクロで値を取得して確かめてください。
では、OpenMP 特集を活用ください。
OpenMP 特集記事- OpenMP* 入門
- インテル® C++/Fortran コンパイラーによる OpenMP* 3.1 仕様のサポート
- C++ 開発者が陥りやすい OpenMP* の 32 の罠
- インテル® パフォーマンス・ライブラリー(IPP)における OpenMP* サポートの変更 (近日公開予定)
- OpenMP* を使用して既存のシリアルコードで並列処理の可能性を見つけよう (近日公開予定)