Youtube登録者5000人突破!!

【IT】OpenMPによる並列計算プログラミング入門【C/C++】

OpnMP(Openm Multi-Processing)は、1つのマシン内で並列計算を行うためのAPIです。

FORTRANとC(C++)で利用ができます。今回は、C++を例に用いて説明します。

並列計算

並列計算は、計算対象を複数のタスクに分けることで、各コアで並行して処理できるようにします。

小分けにしたタスクはスレッドと呼ばれ、スレッドをコアに割り振ります。

プログラム全てを並列化できることはほとんどありません。基本的にはプログラムの一部だけ並列処理を行うのが一般的です。

並列計算

最も並列化に適した部分を並列化してあげる必要があるので、並列化する上でプログラムの知識は欠かせません。

OpenMPの書き方

ここからは実際にOpenMPを利用していきましょう。すでに環境がある前提で説明を行うので、環境構築に関しては他のサイトを参考にしてください。

まず、OpneMPのライブラリをインクルードする必要があります。インクルードには、プログラムの冒頭に#include <omp.h> と記述してください。

処理の複数実行

次に、既存のプログラムの並列化を行います。並列化には2通りの代表的な方法があります。

一つは対象の処理をスレッド数分行うというものです。下記のように #pragma omp parallel とブラケットで対象の処理を囲います。

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

int main(){
  #pragma omp parallel{
    printf("Hello \n");
  }
}

上記のプログラムでは、printfの部分がOpneMPの対象として囲まれているので、スレッドの数だけ画面に「Hello」が表示されることになります。

for分の展開

2つ目の方法はfor文の展開です。既存のプログラムの高速化として使いやすいので、こちらのほうがよく利用されます。

こちらは、すでにあるfor文を並列により高速化するという方法です。

先程の記述に加えて、for文の前に #pragma omp for を書くだけでfor文を展開して並列化してくれます。

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

int main(){
  int x[100],y[100],z[100];
  #pragma omp parallel{
    #pragma omp for
    for(int i=0; i<100; i++){
      x[i] = 1;
      y[i] = 2;
    }
    #pragma omp for
    for(int i=0; i<100; i++){
      z[i] = x[i] + y[i];
    }
  }
}

上記だと、for文は全てスレッドで並列化されることになります。

下記のように #pragma omp parallel for を使うことで簡略化して書くことができます。

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

int main(){
  int x[100],y[100],z[100];
    #pragma omp parallel for
    for(int i=0; i<100; i++){
      x[i] = 1;
      y[i] = 2;
    }
    #pragma omp parallel for
    for(int i=0; i<100; i++){
      z[i] = x[i] + y[i];
    }
  }
}

簡略化によりブラケットを省略することができるので、コードが非常に見やすくなります。こちらの書き方が一般的です。

例えば、100回ループで4スレッドなら、各スレッドで25回分のループが実行されます。

ここで注意ですが、forループを並列化する場合は、各ループで相互参照がないことを事前に確認しておきましょう。

数値解析では、陽的な処理であれば基本的に並列化が可能です。

実行

一般的なコンパイラであれば、OpenMPに対応しています。そのため、上記のプログラムを与えてやれば、コンパイル時に並列化用の実行ファイルを作成してくれます。

ここではgccコンパイラを例に説明します。

OpenMPを使うときは、コンパイラオプションに「-fopenmp」を加えます。

また、環境変数に「OMP_NUM_THREADS」を追加して、スレッド数を与えます。例えば、redhatもしくはcentos系Linuxだと「export OMP_NUM_THREADS=4」をコマンドラインで実行してやれば良いです。

以上を行うことで、OpenMPによる並列化が行えます。

おわりに

今回はOpenMPを使用したノード内並列化について説明しました。

重要なポイントは下記の通りです。

  • 並列計算では、プログラムの一部が並列化される
  • OpenMPは並列計算の規格であり、プログラムの修正により並列計算できるようになる
  • OpenMPは一つのマシン(ノード)内で並列計算ができる
  • OpenMPを使うには、ライブラリをインクルードする
  • OpenMPでは、#pragma omp parallel とブラケットで並列部分の指定を行う
  • #pragma omp for によりfor文を並列処理できる
  • 実行時は、 -fopenmp のオプションを加えてコンパイルする
  • 並列数は環境変数にて事前に指定する

特に、for文の展開による並列化は簡単にプログラムを高速化できるため、非常に有用です。

並列計算は今回紹介したOpneMPとマシン(ノード)間を並列化させるMPIがあります。

OpenMPのほうが簡単なので、手軽に並列計算をしたい場合はOpenMPからまずは行いましょう。

youtubeもやってます

Linuxに関する解説を動画で行っています。基本的な内容に不安のある方はこちらもどうぞ。