OpenMP

OpenMP（オープンエムピー）は、並列計算機環境において共有メモリ・マルチスレッド型の並列アプリケーションソフトウェア開発をサポートするために標準化されたAPIである。「OpenMP」は「open multiprocessing」の略である。
同様に並列コンピューティングに利用されるMPIでは、メッセージの交換をプログラム中に明示的に記述しなければならないが、OpenMPではディレクティブを挿入することによって並列化を行う。OpenMPが使用できない環境では、このディレクティブは無視されるため、並列環境と非並列環境でほぼ同一のソースコードを使用できるという利点がある。また、プラットフォーム固有のスレッドAPIを使わず、コンパイラによって暗黙的に生成されたスレッドプールを利用してタスクを振り分けることになるため、並列プログラムを簡潔に記述できるだけでなく、複数の環境に移植しやすくなる。
MPIとの比較では、OpenMPは異なるスレッドが同一のデータを同じアドレスで参照できるのに対して、MPIでは明示的にメッセージ交換を行わなければならない。そのため、OpenMPは、SMP環境においては大きなデータの移動を行なわずにすむので高い効率が期待できる。ただし並列化の効率はコンパイラに依存するので、チューニングによる性能改善がMPIほど高くならないという問題がある。また、。
OpenMPは、並列プログラミングにおいて最も広く利用されているAPIであるが、共有メモリに対してに近いアクセスができるハードウェアシステムアーキテクチャでは、スケーラビリティに限界がある。そのため、現在のほとんどのスーパーコンピューターでは、OpenMP単独ではなく、分散メモリ環境で高いスケーラビリティを発揮するMPIと組み合わせた、ハイブリッドMPI+OpenMPが利用されている。
現在FORTRANとC/C++について標準化が行われている。
OpenMPを用いたコード例.
以下はC言語における for ループを並列処理させる例である。
int main(int argc, char *argv[])
 int i;
 for (i = 0; i < 10000; ++i)
 /* (並列処理させたいプログラム) */
 return 0;
OpenMPはループの反復処理を自動的に複数のスレッドに分割して並行処理できるようにする。例えば4つのスレッドを用いて処理を分割する場合、上記例ではインデックス[0, 2499], [2500, 4999], [5000, 7499], [7500, 9999]の各範囲をそれぞれのスレッドに分担させる、といった具合である。実際にいくつのスレッドを起動するのか、また各スレッドに対してどのように処理を振り分けるのかはOpenMP処理系およびプログラム実行環境などの条件に依存する。
以下は区分求積法を用いた円周率πの数値計算を、OpenMP並列リダクションによって行なうC++のコード例である。
const double D_PI = 3.1415926535897932384626433832795;
// 区分求積法で π の近似値を求める。
// 1 / (x^2 + 1) を区間 [0, 1] で積分すると π/4 になるという定積分を利用する。
int main()
 const int DivNum = 1000 * 1000 * 1000;
 const double delta = 1.0 / DivNum;
 std::cout « "OpenMP max threads count = " « omp_get_max_threads() « std::endl;
 const auto startTime = std::chrono::system_clock::now();
 double sum = 0;
 for (int i = 0; i < DivNum; ++i)
 const double x = (delta * i);
 const double area = delta * 1.0 / (x * x + 1.0);
 sum += area;
 const double pi = sum * 4.0;
 const auto endTime = std::chrono::system_clock::now();
 std::cout « std::setprecision(15) « "PI ~= " « pi « std::endl;
 std::cout « "Error [%] = " « (100.0 * std::fabs(D_PI - pi) / D_PI) « std::endl;
 std::cout « "Elapsed time [ms] = " « std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() « std::endl;
 return 0;
OpenMPコンパイルオプションの有無を切り替えるか、OpenMPディレクティブをコメントアウト／コメント解除してからコンパイル・実行することで、マルチスレッド版およびシングルスレッド版の速度性能比較を簡単に行なうことができるのがOpenMPプログラムの特徴である。