Я хочу создать параллельную программу, которая интенсивно использует SCALAPACK. Основой SCALAPACK является BLACS, который сам полагается на MPI для межпроцессного взаимодействия.
Я хочу запустить программу с определенным количеством процессов (например, количество ядер на машине) и позволить алгоритму решить, как использовать эти процессы для вычислений.
В качестве теста я хотел использовать 10 процессов. 9 из этих процессов должны выстроиться в сетку (BLACS_GRIDINIT
), а 10-й процесс должен дождаться завершения остальных процессов.
К сожалению, OpenMPI падает из-за того, что последний процесс не попадает в контекст MPI из BLACS, в то время как другие это делают.
Вопрос. Как правильно использовать BLACS с большим количеством процессов, чем необходимо?
Я провел несколько экспериментов с дополнительными вызовами 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 с помощью MPI_INIT
, если этого не произошло раньше. Это означает, что на данный момент все работает так, как ожидалось.
В конце вызов 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 выглядит ошибочной. Я повторю этот пример в ближайшем будущем с новейшим служебным выпуском Intel Studio
, но не ожидайте никаких изменений.
Однако я был бы признателен за любое другое (и, возможно, лучшее) решение.