SQUIDで、IntelMPIを使ったノード間並列(分散メモリ並列)処理を行う方法を解説します。MPIを除く、Intelコンパイラでの最適化については、こちらのページをご参照ください。

 

MPIとは

    MPIとは、分散メモリ並列処理におけるメッセージパッシング(複数のプロセス間でデータをやり取りするために用いるメッセージ通信操作)の標準規格のことです。ノード間をまたがる並列化が可能となるため、その分大きなメモリ空間が利用可能になります。ただし、ユーザ自身で処理の分割やノード間の通信を指示する必要があるため、プログラミングの負担がやや大きくなります。
    CとFORTRANで記述方法がやや異なりますが、本稿ではFORTRANを中心に説明します。

 

主な機能

    MPIは以下のような機能を持っています。
    ・プロセスの管理
    プログラムの初期化や終了処理を行います
    ・1対1の通信
    1プロセス対1プロセスの通信操作
    ・集団の通信
    グループ内のプロセス全体が関係する通信操作

 

基本的な利用方法

    MPIプログラミングにかかる負担の多くはプログラムの「設計」に関するものであり、MPIを利用する為に覚えることはそんなに多くありません。本ページに書かれた、基本的な内容を習得するだけでも、十分利用することが可能です。

     

    以下にFortranで書かれたMPIプログラムを載せています。こちらを参考に説明します。

     

    プログラムのハイライト部分(2行目、4行目-6行目、8行目)が、MPIプログラム(MPIサブルーチン及びMPIに関連する処理)になります。5行目-7行目は、MPIの処理をPrint出力するために挿入した処理になりますので、入力しなくても、並列処理としての動きは変わりません。

     

    2行目はMPI用のインクルードファイルの指定です。MPIを利用する場合、必ず指定してください。

     

    プログラム中で「MPI_INIT」がcallされてから、「MPI_FINALIZE」がcallされるまでの区間がMPI並列の対象となり、MPI_INITがcallされた時点から、プロセスが生成されます。4行目と8行目がそれぞれ該当し、5~7行目の処理がマルチプロセスで実行されます。

     

    5行目と6行目の「MPI_COMM_RANK」と「MPI_COMM_SIZE」はMPI処理の情報を得るためのサブルーチンです。「MPI_COMM_SIZE」では、処理を分割している数(並列プロセス数)を取得します。「MPI_COMM_RANK」では、分割された処理(並列プロセス)ごとにつけられた番号(プロセスID)を取得します。

     

    並列プロセス数は、実行コマンド入力時に指定します。

     

    上記のプログラムを、4プロセスで実行した結果は下記のようになります。

    HELLO WORLD myrank= 3 ( 4 processes)
    HELLO WORLD myrank= 1 ( 4 processes)
    HELLO WORLD myrank= 0 ( 4 processes)
    HELLO WORLD myrank= 2 ( 4 processes)

     

基本的なサブルーチンについて

     

    MPI_INIT (ierr)

      MPIを起動するコマンドです。
      必ず他のMPIサブルーチンより前にコールしてください。

      引数
      ierr 正常終了時に0が格納されます。エラー時はそれ以外の値が格納されます。

       

    MPI_FINALIZE (ierr)

      MPIを終了するコマンドです。
      必ず他のMPIサブルーチンより後にコールしてください。

      引数
      ierr 正常終了時に0が格納されます。エラー時はそれ以外の値が格納されます。

       

    MPI_COMM_SIZE(comm, size, ierr)

      引数「comm」で指定されたコミュニケータ(グループ)に含まれるプロセスの数の合計を取得する。
      通常は「comm」に「MPI_COMM_WORLD」というMPI全プロセスを表すコミュニケータを指定し、
      全プロセス数を取得するために使うことが多いのですが、複数のコミュニケータを使うことで、
      複雑な処理を行うことが可能です。

      引数
      comm コミュニケータを指定します。前述の通り、通常はMPI全プロセスをあらわす「MPI_COMM_WORLD」を指定することが多いです。
      size 取得したプロセス数の合計が格納されます。
      ierr 正常終了時に0が格納されます。エラー時はそれ以外の値が格納されます

       

    MPI_COMM_RANK(comm, size, ierr)

      引数「comm」で指定されたコミュニケータ(グループ)内でプロセスごとにつけられた番号を取得する。
      この番号のことを「プロセスID」「rank」と呼びます。
      MPI_COMM_RANKと同じく、通常は「comm」に「MPI_COMM_WORLD」というMPI全プロセスを表すコミュニケータを指定することが多いです。

      引数
      comm コミュニケータを指定します。前述の通り、通常はMPI全プロセスをあらわす「MPI_COMM_WORLD」を指定することが多いです。
      rank commで指定されたグループ内のプロセスID
      ierr 正常終了時に0が格納されます。エラー時はそれ以外の値が格納されます

       

      上記の例では、基本的なサブルーチンのみ用いておりますが、これら以外にも、さまざまなサブルーチンが用意されています。詳細は、下記の[参考資料]をご覧ください

     

コンパイル方法

    プログラミング言語ごとにコマンドが異なりますので、ご注意ください。

    $module load BaseCPU
     
    $ mpiifort [options] source_file (Fortranの場合)
    $ mpiicc [options] source_file (Cの場合)
    $ mpiicpc [options] source_file (C++の場合)

    利用可能なoptionについては、以下のページをご覧ください。

    最適化・ベクトル化利用方法

     

     

実行スクリプト

    MPIを実行する際のコマンドは下記の通りです。

    mpirun ${NQSV_MPIOPTS} -np (総並列数) 実行ファイル名

     

    スクリプト例は下記の通りです。
    4ノード並列実行、1ノードにつき76並列実行(計304並列実行)、経過時間 1時間でMPIのバッチリクエストを実行するスクリプトになります。

     
     

    マルチノード実行時の注意点

      ジョブスクリプトで「setenv (オプション名)」などでオプションや環境変数を指定した場合、マスターノードにのみ設定され、スレーブノードには設定されません。
      全ノードに設定を反映させたい場合は「#PBS -v (オプション名)」と指定してください。
      詳細は下記に記載しております。
      ジョブスクリプトの書き方 環境変数の指定

       

     

参考資料