openmpopenmpを使い始める


備考

OpenMP(Open MultiProcessing)は、コンパイラ指令に基づいた並列プログラミングモデルであり、アプリケーション開発者がアプリケーションコードに並列性を段階的に追加することを可能にします。

並列プログラミング用のOpenMP API仕様では、ほとんどのプラットフォームで、C、C ++、Fortranでのマルチプラットフォーム共有メモリマルチプロセッシングプログラミングをサポートするアプリケーションプログラミングインタフェース(API)を提供しています。これは、実行時動作に影響を与える一連のコンパイラ・ディレクティブ、ライブラリ・ルーチン、環境変数で構成されています。

OpenMPはノード内の並列処理(共有メモリマルチプロセッシング)に重点を置いているため、MPIなどのメッセージパッシングプログラミングモデルと組み合わせて複数のノードで実行することができます。

バージョン

バージョン言語発売日
4.5 C / C ++ / Fortran 2015-11-01
4.0 C / C ++ / Fortran 2013-07-01
3.1 C / C ++ / Fortran 2011-07-01
3.0 C / C ++ / Fortran 2008-05-01
2.5 C / C ++ / Fortran 2005-05-01
2.0c C / C ++ 2002-03-01
2.0f Fortran 2000-11-01
1.0c C / C ++ 1998-10-01
1.0f Fortran 1997-10-01

編集

異なるバージョンのOpenMP仕様をサポートする多くのコンパイラがあります。 OpenMPのリストを保持し、ここでそれをサポートするコンパイラとサポートされているバージョンで。一般に、OpenMPサポートでアプリケーションをコンパイル(およびリンク)するには、コンパイルフラグを追加するだけで済みます.OpenMP APIを使用する場合は、OpenMPヘッダー(omp.h)をインクルードする必要があります。ヘッダーファイルの名前は固定されていますが、コンパイルフラグはコンパイラによって異なります。以下は、OpenMPを有効にするコンパイラーとフラグの非包括的なリストです。

  • GCC(gcc、g ++、gfortranを含む):- -fopenmp
  • LLVM:-fopenmp
  • Intelコンパイラスイート(icc、icpc、ifortを含む):- -qopenmp (およびGCC / LLVMとの互換性のための-fopenmp
  • IBM XLコンパイラー・スイート(xlc、xlC、xlfを含む):- -xlsmp=omp
  • PGIコンパイラスイート(pgcc pgc ++ pgfortranを含む): '-mp'

OpenMPを使用した並列hello world

#include <omp.h>
#include <stdio.h>

int main (int argc, char *argv[])
{
   #pragma omp parallel
   {
     printf ("Hello world! I'm thread %d out of %d threads.\n",
             omp_get_thread_num(), omp_get_num_threads());
   }
   return 0;
}
 

このコードは、単にスレッドのチームを作成します(環境変数OMP_NUM_THREADS 定義されていない場合は、システム上の論理コアごとに1つずつ作成されます)。そして、各スレッドは、典型的なHelloワールドメッセージを出力するだけでなく、

削減の例

#include <omp.h>
void main ()
{     
    int i;       
    double ZZ, func(), res=0.0;

    #pragma omp parallel for reduction(+:res) private(ZZ) 
    for (i=0; i< 1000; i++){
        ZZ = func(I);
        res = res + ZZ; 
    }
}
 

最後の行:実際にはプライベートコピーに追加され、ループの後に結合されます。コンパイラは詳細を処理します。

Work Sharing構文 - Forループの例

double  res[MAX];  int i;
#pragma omp parallel 
{    
    #pragma omp for
    for (i=0;i< MAX; i++) {
        res[i] = huge();
    } 
}    
 

forループは並列に実行されます。 huge()は実行に時間がかかりすぎることがあります。 OpenMPは上記のコードを書くためのショートカットをサポートしています:

double  res[MAX];  int i;
#pragma omp parallel for
for (i=0;i< MAX; i++) {
    res[i] = huge();
} 
 

ループの反復がどのようにスレッドにマッピングされるかに影響を与えるschedule句を持つこともできます。例えば:

#pragma omp parallel
#pragma omp for schedule(static)
for(i=0;I<N;i++) {
    a[i] = a[i] + b[i];
}
 

スケジューリングのスタイルは次のとおりです。

スケジュール(静的[、チャンク])
サイズの反復のブロックを各スレッドに「チャンク」します。
指定されていない場合は、使用可能なスレッドにできるだけ均等に割り当てる

スケジュール(動的[、チャンク])
各スレッドは、すべての反復が処理されるまで、キューから「チャンク」反復を取得します。

スケジュール(ガイド[、チャンク])
スレッドは反復ブロックを動的に取得します。ブロックのサイズは大きくなり、計算が進むにつれてサイズが "チャンク"に縮小されます。

スケジュール(実行時)
OMP_SCHEDULE環境変数から取得したスケジュールとチャンクサイズ。