0

SCALAPACK を多用する並列プログラムを作成したいと考えています。SCALAPACK の基礎は BLACS であり、BLACS 自体はプロセス間通信を MPI に依存しています。

定義された数のプロセス (マシン上のコアの数など) でプログラムを開始し、これらのプロセスを計算に使用する方法をアルゴリズムに決定させたいと考えています。

テストケースとして、10 個のプロセスを使用したいと考えました。これらのプロセスのうち 9 つをグリッド ( BLACS_GRIDINIT) に配置し、10 番目のプロセスは他のプロセスが終了するまで待機する必要があります。

残念ながら、最後のプロセスが BLACS から MPI コンテキストに入らないため、OpenMPI はクラッシュします。

質問:必要以上のプロセスで BLACS を使用する正しい方法は何ですか?

MPI_INITadditionalとMPI_FINALIZE呼び出しを使っていくつかの実験を行いましたが、どれも成功しませんでした。


インテル® MKL のサンプル・コード (少し短縮) から始めました。

      PROGRAM HELLO 
*     -- BLACS example code --
*     Written by Clint Whaley 7/26/94 
*     Performs a simple check-in type hello world 
*     .. 
*     .. External Functions ..
      INTEGER BLACS_PNUM
      EXTERNAL BLACS_PNUM 
*     .. 
*     .. Variable Declaration ..
      INTEGER CONTXT, IAM, NPROCS, NPROW, NPCOL, MYPROW, MYPCOL
      INTEGER ICALLER, I, J, HISROW, HISCOL 

*     Determine my process number and the number of processes in 
*     machine 
      CALL BLACS_PINFO(IAM, NPROCS) 

*     Set up process grid that is as close to square as possible 
      NPROW = INT( SQRT( REAL(NPROCS) ) )
      NPCOL = NPROCS / NPROW 

*     Get default system context, and define grid
      CALL BLACS_GET(0, 0, CONTXT)
      CALL BLACS_GRIDINIT(CONTXT, 'Row', NPROW, NPCOL)
      CALL BLACS_GRIDINFO(CONTXT, NPROW, NPCOL, MYPROW, MYPCOL) 

*     If I'm not in grid, go to end of program 
      IF ( (MYPROW.GE.NPROW) .OR. (MYPCOL.GE.NPCOL) ) GOTO 30

*     Get my process ID from my grid coordinates 
      ICALLER = BLACS_PNUM(CONTXT, MYPROW, MYPCOL) 

*     If I am process {0,0}, receive check-in messages from 
*     all nodes 
      IF ( (MYPROW.EQ.0) .AND. (MYPCOL.EQ.0) ) THEN

         WRITE(*,*) ' '

         DO 20 I = 0, NPROW-1
            DO 10 J = 0, NPCOL-1

               IF ( (I.NE.0) .OR. (J.NE.0) ) THEN
                  CALL IGERV2D(CONTXT, 1, 1, ICALLER, 1, I, J)
               END IF 
*              Make sure ICALLER is where we think in process grid
              CALL BLACS_PCOORD(CONTXT, ICALLER, HISROW, HISCOL)
              IF ( (HISROW.NE.I) .OR. (HISCOL.NE.J) ) THEN
                 WRITE(*,*) 'Grid error!  Halting . . .'
                 STOP
              END IF
              WRITE(*, 3000) I, J, ICALLER
10         CONTINUE 
20      CONTINUE
        WRITE(*,*) ' '
        WRITE(*,*) 'All processes checked in.  Run finished.' 

*     All processes but {0,0} send process ID as a check-in
      ELSE
         CALL IGESD2D(CONTXT, 1, 1, ICALLER, 1, 0, 0)
      END IF

30    CONTINUE

      CALL BLACS_EXIT(0)

1000  FORMAT('How many processes in machine?') 
2000  FORMAT(I) 
3000  FORMAT('Process {',i2,',',i2,'} (node number =',I,
     $       ') has checked in.')

      STOP
      END

更新:のソース コードを調べて、BLACSそこで何が起こっているのかを確認しました。

これが以前に発生しなかった場合、呼び出しBLACS_PINFOは MPI コンテキストを で初期化します。MPI_INITこれは、この時点ですべてが期待どおりに機能することを意味します。

最後に、 への呼び出しはBLACS_EXIT(0)からすべてのリソースを解放する必要がBLACSあり、引数が0の場合は も呼び出す必要がありますMPI_FINALIZE。残念ながら、これは期待どおりに機能せず、最後のプロセスは を呼び出しませんMPI_FINALIZE

回避策として、必要に応じて質問MPI_FINALIZEDして電話することができますMPI_FINALIZE

更新 2:以前の試みは と で行われIntel Studio 2013.0.079ましOpenMPI 1.6.2SUSE Linux Enterprise Server 11

ctheo の回答を読んだ後、Ubuntu 12.04( gfortran 4.6.3, OpenMPI 1.4.3, BLACS 1.1) で指定されたツールを使用してこの例をコンパイルしようとしましたが、成功しました。

私の結論は、Intel の実装にはバグがあるように見えるということです。の最新のサービス リリースで、そう遠くない将来にこの例を再試行しますがIntel Studio、変更は期待できません。

ただし、他の(そしておそらくより良い)ソリューションをいただければ幸いです。

4

2 に答える 2

0

SCALAPACK で使用するプロセスを減らすために多くのことを行う必要はないと思います。サブルーチンは、プロセスのBLACS_PINFO総数を返します。1 つ減らしたい場合は、 を実行してくださいNPROCS = NPROCS - 1。私はあなたのサンプルコードを使用し(FORMATのいくつかのタイプミスを修正しました)、減算を追加し、次の出力を得ました:

$ mpirun -n 4 ./a.out 

Process { 0, 0} (node number = 0) has checked in.
Process { 0, 1} (node number = 1) has checked in.
Process { 0, 2} (node number = 2) has checked in.

 All processes checked in.  Run finished.

BLACS_GRIDINIT、縮小された でグリッドを作成しNPROCSます。BLACS_GRIDINFO1 つのプロセスを呼び出すと、MYPROW=MYPCOL=-1

一方、異なるプロセスを使用する複数のグリッドを作成する場合は、おそらくBLACS_GRIDMAPサブルーチンを使用する必要があります。以下のサンプル コードは、合計プロセスの半分のサイズで 2 つの等しいグリッドを作成します。

      PROGRAM HELLO 
*     .. 
      INTEGER CONTXT(2), IAM, NPROCS, NPROW, NPCOL, MYPROW, MYPCOL
      INTEGER ICALLER, I, J, HISROW, HISCOL
      integer UMAP(2,10,10)
*     
      CALL BLACS_PINFO(IAM, NPROCS) 
      NPROCS = NPROCS/2
*     
      NPROW = INT( SQRT( REAL(NPROCS) ) )
      NPCOL = NPROCS / NPROW 
*     
      DO IP = 1, 2
        DO I = 1, NPROW
          DO J = 1, NPCOL
            UMAP(IP,I,J) = (IP-1)*NPROCS+(I-1)*NPCOL+(J-1)
          ENDDO
        ENDDO
        CALL BLACS_GET(0, 0, CONTXT(IP))
        CALL BLACS_GRIDMAP(CONTXT(IP), UMAP(IP,:,:), 10, NPROW, NPCOL )
      ENDDO
*
      DO IP = 1, 2
        CALL BLACS_GRIDINFO(CONTXT(IP), NPROW, NPCOL, MYPROW, MYPCOL) 
        IF(MYPROW.GE.0 .AND. MYPCOL.GE.0 ) THEN
          WRITE(*,1000) IAM, MYPROW, MYPCOL, IP
        END IF
      ENDDO

      CALL BLACS_EXIT(0)
 1000 FORMAT('Process ',i2,' is (',i2,','i2 ') of grid ',i2)
*
      STOP
      END

次の出力が得られました。

$ mpirun -n 8 ./a.out 
Process  0 is ( 0, 0) of grid  1
Process  1 is ( 0, 1) of grid  1
Process  2 is ( 1, 0) of grid  1
Process  3 is ( 1, 1) of grid  1
Process  4 is ( 0, 0) of grid  2
Process  5 is ( 0, 1) of grid  2
Process  6 is ( 1, 0) of grid  2
Process  7 is ( 1, 1) of grid  2

プロセスゼロでデータを収集しませんでした。したがって、すべてのプロセスがローカルである場合、この出力を取得できます。

于 2013-08-30T13:12:29.950 に答える