OpenMP

OpenMP（オープンエムピー）は、並列計算機環境において共有メモリ・マルチスレッド型の並列アプリケーションソフトウェア開発をサポートするために標準化されたAPIである。「OpenMP」は「open multiprocessing」の略である。

同様に並列コンピューティングに利用されるMPIでは、メッセージの交換をプログラム中に明示的に記述しなければならないが、OpenMPではディレクティブ（指令）を挿入することによって並列化を行う。OpenMPが使用できない環境では、このディレクティブは無視されるため、並列環境と非並列環境でほぼ同一のソースコードを使用できるという利点がある。また、プラットフォーム固有のスレッドAPIを使わず、コンパイラによって暗黙的に生成されたスレッドを利用してタスクを振り分けることになるため、並列プログラムを簡潔に記述できるだけでなく、複数の環境に移植しやすくなる。

MPIとの比較では、OpenMPは異なるスレッドが同一のデータを同じアドレスで参照できるのに対して、MPIでは明示的にメッセージ交換を行わなければならない。そのため、OpenMPは、SMP環境においては大きなデータの移動を行なわずにすむので高い効率が期待できる。ただし並列化の効率はコンパイラに依存するので、チューニングによる性能改善がMPIほど高くならないという問題がある。また、。

OpenMPは、並列プログラミングにおいて最も広く利用されているAPIであるが、共有メモリに対してに近いアクセスができるハードウェアシステムアーキテクチャでは、スケーラビリティに限界がある。そのため、現在のほとんどのスーパーコンピューターでは、OpenMP単独ではなく、分散メモリ環境で高いスケーラビリティを発揮するMPIと組み合わせた、ハイブリッドMPI+OpenMPが利用されている。

2013年にリリースされたOpenMP 4.0では、多数の先進的な機能が追加された。SIMD命令を使った自動ベクトル化機能（omp simd）や、GPUなどのアクセラレータに並列処理を委譲する分散メモリ型のオフロード機能などがサポートされている。

2023年現在、FORTRANとC/C++について標準化が行われている。

OpenMPを用いたコード例 
以下はC言語における for ループを並列処理させる例である。
int main(int argc, char *argv[])
{
    int i;
#pragma omp parallel for
    for (i = 0; i < 10000; ++i)
    {
        /* (並列処理させたいプログラム) */
    }
    return 0;
}
OpenMPはループの反復処理を自動的に複数のスレッドに分割して並行処理できるようにする。例えば4つのスレッドを用いて処理を分割する場合、上記例ではインデックス[0, 2499], [2500, 4999], [5000, 7499], [7500, 9999]の各範囲をそれぞれのスレッドに分担させる、といった具合である。実際にいくつのスレッドを起動するのか、また各スレッドに対してどのように処理を振り分けるのかはOpenMP処理系（コンパイラ）およびプログラム実行環境などの条件に依存する。

以下は区分求積法を用いた円周率πの数値計算を、OpenMP並列リダクションによって行なうC++のコード例である。一部にC++11の機能が使われているが、OpenMPのディレクティブ自体は言語バージョンとは無関係であり、C++98/C++03でも利用できる。
#include <iostream>
#include <chrono>
#include <cmath>
#include <iomanip>
#include <omp.h>

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;
#pragma omp parallel for reduction(+ : sum)
  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;
}
#pragma omp parallel forは並列ループのディレクティブである。直後に続くreductionはと呼ばれ、並列処理の動作を調整することができる。ここでは総和を格納するスレッド共有変数sumに対する更新操作の演算子（加算）を指定している。異なるスレッドから共有変数にアクセスするときは排他制御やアトミック操作が必要となるが、OpenMPのclauseを使用することでそのような煩雑なコードを記述する必要がなくなり、詳細を処理系に任せて隠蔽することができる。

OpenMPコンパイルオプションの有無を切り替えるか、OpenMPディレクティブをコメントアウト／コメント解除してからコンパイル・実行することで、マルチスレッド版およびシングルスレッド版の速度性能比較を簡単に行なうことができるのがOpenMPプログラムの特徴である。

対応コンパイラ 
 GCC：バージョン4.9でC/C++用のOpenMP 4.0を、バージョン4.9.1でFortran用のOpenMP 4.0をサポートした。GCC 5ではオフロード機能のサポートが追加された。GCC 6以降でC/C++用のOpenMP 4.5を、GCC 7以降でFortran用のOpenMP 4.5をサポートしている。GCC 9以降でOpenMP 5.0の初期サポートが始まっている。
 Clang：バージョン3.7でOpenMP 3.1に対応した。Clang 3.7以前は派生プロジェクトが存在した。Clang 3.9でオフロード以外のOpenMP 4.5機能をすべてサポートした。
 Microsoft Visual C++：Visual C++ 2017時点でOpenMP 2.0をサポートしている。Visual C++ 2019ではSIMDベクトル化機能を実験的にサポートする。
 Intel C++ Compiler：バージョン12.1においてOpenMP 3.1をサポートしている。また、バージョン14.0においてOpenMP 4.0の機能を一部サポートしている。
 : バージョン18.0以降でOpenMP 5.0の機能の大部分をサポートしている。

脚注

注釈

出典

関連項目 
 オープン標準
 OpenCL
 OpenACC
 スレッド (コンピュータ)

より詳しく知るための本など（For further learning） 

 Rohit Chandra, Ramesh Menon, Leo Dagum, David Kohr, Dror Maydan and Jeff McDonald: Parallel Programming in OpenMP, Morgan Kaufmann, ISBN 978-1558606715 (2000年10月).
 Barbara Chapman, Gabriele Jost and Ruud Van der Pas: Using OpenMP: Portable Shared Memory Parallel Programming, MIT Press, ISBN 978-0-262-53302-7 (2007年10月).
 Ruud van der Pas, Eric Stotzer and Christian Terboven: Using OpenMP -- The Next Step: Affinity, Accelerators, Tasking, and SIMD, The MIT Press, ISBN 978-0262344005 (2017年10月27日). ※ OpenMP 4.5 の仕様を記述。
 Timothy G. Mattson, Yun (Helen) He, and Alice Evelyn Konigs: The OpenMP Common Core: Making OpenMP Simple Again, The MIT Press, ISBN 978-0262538862 (2019年11月19日).
 Tom Deakin and Timothy G. Mattson: Programming Your GPU with OpenMP: Performance Portability for GPUs, The MIT Press, ISBN 978-0-262547536 (2023年11月7日).

 牛島 省:「OpenMPによる並列プログラミングと数値計算法」、丸善、ISBN 978-4621077177 (2006年5月).
 黒田久泰：「C言語によるOpenMP入門」、東京大学情報基盤センター スーパーコンピューティングニュース、Vol.9, No. Special Issue 1 (2008), pp.149-168
 佐藤三久：「OpenMP並列プログラミング入門」、筑波大学計算科学センター（2010）
 菅原 清文：「C/C++ プログラマーのための OpenMP 並列プログラミング」、第2版、カットシステム、ISBN 978-4-87783-223-0 (2012年6月).
 片桐孝洋：「並列プログラミング入門:サンプルプログラムで学ぶOpenMPとOpenACC」、東京大学出版会、ISBN 978-4130624565 (2015年5月29日).
 片桐孝洋：「OpenMPの基礎」、名古屋大学情報基盤センター、計算科学技術特論A第3回（2017年度） 
 北山洋幸：「OpenMP基本と実践―メニ―コアCPU時代の並列プログラミング手法」、カットシステム、ISBN 978-4877834494 (2018年10月1日).

外部リンク 

 OpenMP
 Specifications - OpenMP
 Architecture Review Board: OpenMP Application Programming Interface Specification Version 5.0, (2018年11月)
 OpenMP入門 - Fortran利用者向け (NAG社)
 HPCプログラミングセミナーで使用する資料の公開ページです。(HPCI=High Performance Computing Initiative、日本)
 「OpenMPによるマルチコア・メニィコア並列プログラミング入門」(東京大学情報基盤センター講習会資料)
 Victor Eijkhout : Parallel Programming for Science Engineering The Art of HPC, volume 2 (HTML version)

並列コンピューティング
API