MPI/OpenMP* のハイブリッド・プログラミングを始めよう

同カテゴリーの次の記事

cpuinfo: インテル® MPI ライブラリーのプロセッサー情報ユーティリティー

この記事は、インテル® ソフトウェア・ネットワークに掲載されている「Beginning Hybrid MPI/OpenMP Development」の日本語参考訳です。


はじめに

MPI または OpenMP* のいずれかのプログラミングを始めるだけでも十分な挑戦といえますが、両方を併用する場合はさらに複雑になり、考慮しなければならないことも増えてきます。この記事では、MPIとOpenMP* のハイブリッド・プログラミングを始めるにあたって役立つ情報を紹介します。

必要条件

  • C、C++、FORTRAN77、Fortran90/95 をサポートし、OpenMP* を実装しているコンパイラー
  • ランタイム・ライブラリーと実行ファイルを含む MPI 実装、開発ライブラリー、およびヘッダー

ここでは、上記のすべての要件を満たすインテル® Cluster Studio XE を使用します。ほかのコンパイラーと MPI を使用したコンパイル手順も、テストが完了次第追加する予定です。

基本的な考慮事項

MPI または OpenMP* のいずれかを使用してプログラムを作成する場合、次のような基本的な考慮事項があります。

  • 特定の変数の格納場所は?
  • その変数にアクセス可能なプロセス/スレッドは?
  • その変数を別のプロセス/スレッドに引き渡す方法は?

MPI と OpenMP* を併用する場合、考慮事項はさらに増えます。

  • スレッド化された領域内で MPI_Send を呼び出すとどうなるのか?
  • MPI 呼び出しはマスタースレッドだけが行うべきか?
  • MPI 呼び出し同士は完全に分離すべきか?
  • ルートプロセスのマスタースレッドにすべてを送って出力を制御する場合、ほかのプロセスの各スレッドがルート/マスタースレッドと効率良く通信するにはどうしたら良いか?

これらの課題に実際に取り組むにはどうすべきか? 簡単な答えはありません。あるプログラムでは優れたパフォーマンスを発揮する方法であっても、別のプログラムではパフォーマンスを大幅に低下させることがあります。ここで使用する Hello World サンプルプログラムでは、 ルートの各スレッドが OpenMP* のクリティカル・セクションの出力を処理します。クリティカル・セクションが完了すると、マスターは他のすべてのプロセスの各スレッドから情報を (MPI を介して) 受け取ります。この時点では、ルート/マスターがすべての出力を処理します。

コード

この記事で使用するすべてのサンプルコードは、記事の最後にあるリンクからダウンロードできます。ここでは、重要なコード行についてのみ説明します。

   int required=MPI_THREAD_SERIALIZED; // 必要な MPI スレッド化のサポートレベル
   // 各スレッドが MPI ルーチンを呼び出しますが、これらの呼び出しは、
   // 1 つのプロセスで一度に 1 つのみ行われるように調整されます。  

   int provided;                       // 提供される MPI スレッド化のサポートレベル
...
   MPI_Init_thread(&argc, &argv, required, &provided);

MPI プログラムの初期化に利用される MPI_Init の代わりに、ハイブリッド・プログラムでは MPI_Init_thread を使用して初期化します。これには、2 つの引数 requiredprovided が追加で必要です。1 つ目の required には必要なスレッド化のサポートレベルを指定します。実際に実装されるスレッド化のサポートレベルは provided に返ります。これらの引数を使用することで、要求するスレッド化が実際に実装できるかどうかを確認できます。十分なサポートレベルが得られない場合の動作は、開発者が決定します。サポートレベルの値は、(MPI 2.2 標準規格の) 次のいずれかの値になります。

  • MPI_THREAD_SINGLE 1 つのスレッドだけが実行します。
  • MPI_THREAD_FUNNELED プロセスはマルチスレッド対応かもしれませんが、メインスレッドだけが MPI 呼び出しを行うようにアプリケーションで確認する必要があります。
  • MPI_THREAD_SERIALIZED プロセスはマルチスレッド対応で、複数のスレッドが MPI 呼び出しを行うかもしれませんが、一度に 1 つのスレッドのみ MPI 呼び出しを行うことができます。
  • MPI_THREAD_MULTIPLE 複数のスレッドが MPI 呼び出しを行うことができ、制限はありません。
   // スレッド化のサポートレベルの確認

   if (provided < required) {

      // 要求するサポートレベルが満たされていません。スレッドを 1 つにし、警告を発行します。

      if (rank == 0) {
         cout << "Warning:  This MPI implementation provides insufficient"
            << " threading support." << endl;
      }
      omp_set_num_threads(1);
   }

ここでは、要求するサポートレベルと提供されるサポートレベルを比較し、要求するサポートレベルが実装されない場合、プログラムは 1 つのスレッドだけを使用するようにシリアル動作を強制します。

コンパイル

コンパイル時に、MPI ライブラリーがリンクされ、OpenMP* 宣言子/プラグマが解釈されるようにします。ほとんどの MPI 実装には、適切なコンパイラー・オプションを自動で含めるラッパーがあります。PATHLD_LIBRARY_PATH 環境変数が正しく設定されていることを確認してください。可能な場合は、マルチスレッド MPI ライブラリーを使用します。インテル® MPI ライブラリーでは、-mt_mpi コマンドライン・オプションを追加するだけです。以下に、インテル® Cluster Studio を使用する場合の C++ のコンパイル行を示します。

mpiicpc -mt_mpi -openmp hybrid_hello.cpp -o hybrid_hello

C++ 以外の言語の場合は、ソースファイルを変更し、適切な MPI コンパイルスクリプトに変更するだけです。すべて期待どおりに動作すれば、問題なくコンパイルおよびリンクされます。

実行

これで、通常の MPI プログラムと同じようにプログラムを実行できます。OpenMP* 環境変数を設定する場合は、( -genv を使用して) コマンドラインで行うか、または実行前に行います。ここでは、すべてデフォルトの設定を使用し、MPI や OpenMP* の動作を制御する環境変数は設定していません。

mpirun -n 4 ./hybrid_hello

出力結果は次のようになります。

Hello from thread 0 of 6 in rank 0 of 4 on localhost
Hello from thread 1 of 6 in rank 0 of 4 on localhost
Hello from thread 2 of 6 in rank 0 of 4 on localhost
Hello from thread 3 of 6 in rank 0 of 4 on localhost
Hello from thread 4 of 6 in rank 0 of 4 on localhost
Hello from thread 5 of 6 in rank 0 of 4 on localhost
Hello from thread 0 of 6 in rank 1 of 4 on localhost
Hello from thread 1 of 6 in rank 1 of 4 on localhost
Hello from thread 4 of 6 in rank 1 of 4 on localhost
Hello from thread 5 of 6 in rank 1 of 4 on localhost
Hello from thread 2 of 6 in rank 1 of 4 on localhost
Hello from thread 3 of 6 in rank 1 of 4 on localhost
Hello from thread 0 of 6 in rank 2 of 4 on localhost
Hello from thread 1 of 6 in rank 2 of 4 on localhost
Hello from thread 2 of 6 in rank 2 of 4 on localhost
Hello from thread 3 of 6 in rank 2 of 4 on localhost
Hello from thread 4 of 6 in rank 2 of 4 on localhost
Hello from thread 5 of 6 in rank 2 of 4 on localhost
Hello from thread 0 of 6 in rank 3 of 4 on localhost
Hello from thread 1 of 6 in rank 3 of 4 on localhost
Hello from thread 2 of 6 in rank 3 of 4 on localhost
Hello from thread 3 of 6 in rank 3 of 4 on localhost
Hello from thread 4 of 6 in rank 3 of 4 on localhost
Hello from thread 5 of 6 in rank 3 of 4 on localhost

ホスト名は使用しているシステムの名前になり、スレッド番号はシステムで利用可能なコア数および指定したプロセス数に依存します。

まとめ

この記事が、MPI/OpenMP* のハイブリッド・プログラミングに取り掛かろうとしている皆さんに役立つことを願っています。MPI/OpenMP* のハイブリッド・プログラミングには多くの可能性がありますが、同時に多くの落とし穴もあります。詳細は、以下の記事を参照してください。

ハイブリッド・アプリケーション: インテル® MPI ライブラリーと OpenMP* (英語: 今後翻訳予定)

MPI と OpenMP* の併用によりハードウェアを活用する (英語: 今後翻訳予定)

コンパイラーの最適化に関する詳細は、 最適化に関する注意事項を参照してください。

本記事で使用したサンプルコード

hybrid_hello.c

hybrid_hello.cpp

hybrid_hello.f

hybrid_hello.f90

関連記事