我想创建一个并行程序,它大量使用SCALAPACK。SCALAPACK的基础是BLACS,它本身依赖MPI进行进程间通信。
我想用定义的进程数(例如机器上的核数)启动程序,并让算法决定如何使用这些进程进行计算。
作为一个测试案例,我想使用10个进程。这些进程中的9个应该被安排在一个网格(BLACS_GRIDINIT)中,第10个进程应该等到其他进程完成。
不幸的是,OpenMPI崩溃是因为最后一个进程不能从BLACS进入MPI上下文,而其他进程则是这样。
问题:,什么是正确的方法,使用更多的进程超过需要?
我用额外的MPI_INIT和MPI_FINALIZE调用做了一些实验,但我的尝试都没有成功。
我从Intel 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_INIT初始化MPI上下文。这意味着,在这一点上,一切都如预期的那样运作。
最后,对BLACS_EXIT(0)的调用应该将所有资源从BLACS中释放出来,如果参数是0,它也应该调用MPI_FINALIZE。不幸的是,这并不像预期的那样工作,我的最后一个进程也没有调用MPI_FINALIZE。
作为一种解决办法,我们可以询问MPI_FINALIZED并在必要时调用MPI_FINALIZE。
更新2:我以前的尝试是用Intel Studio 2013.0.079和OpenMPI 1.6.2在SUSE Linux Enterprise Server 11上完成的。
在阅读了ctheo的答案之后,我尝试用Ubuntu 12.04 (gfortran 4.6.3, OpenMPI 1.4.3, BLACS 1.1)提供的工具编译这个示例,并取得了成功。
我的结论是,英特尔的实施似乎是错误的。我将在不久的将来用最新的Intel Studio服务版本重试这个示例,但不要期待任何更改。
然而,我会感激任何其他(也许更好)的解决方案。
发布于 2013-08-29 19:21:23
我不知道答案,我敢说,参与这个问题的人和那些知道你问题答案的人都是< 1。不过,我建议你在剪刀上或者通过他们的支持页直接联系田纳西大学的ScaLAPACK团队,运气可能会好一些。祝好运!
发布于 2013-08-30 13:12:29
我不认为您需要在SCALAPACK中使用较少的进程。BLACS_PINFO子例程返回进程总数。如果您想少使用一个,只需执行NPROCS = NPROCS - 1。我使用了您的示例代码(修复了一些格式的排印),添加了减法,并获得了以下输出:
$ 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_GRIDINFO,一个进程获得MYPROW=MYPCOL=-1
另一方面,如果您想要创建多个使用不同进程的网格,那么可能应该使用BLACS_GRIDMAP子程序。下面的示例代码创建了两个相同的网格,每个网格的总进程大小为一半。
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我没有收集零号处理中的数据。因此,如果所有进程都是本地进程,则可以获得此输出。
https://stackoverflow.com/questions/18516915
复制相似问题