Вызов BLACS с большим количеством процессов, чем используется

Я хочу создать параллельную программу, которая интенсивно использует 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, но не ожидайте никаких изменений.

Однако я был бы признателен за любое другое (и, возможно, лучшее) решение.


person Stefan    schedule 29.08.2013    source источник
comment
Вы используете ScaLAPACK из MKL или другую самокомпилируемую реализацию? Было бы странно, если бы вы были первым, кому нужно создать сетки с меньшим количеством процессов, чем общий размер задания MPI.   -  person Hristo Iliev    schedule 02.09.2013
comment
@HristoIliev Проблемы возникают при использовании ScaLAPACK от MKL. И я думаю, вы неправильно поняли: я хотел использовать меньше процессов в сетке, чем количество доступных процессов MPI, потому что я хотел использовать квадратную сетку, но запустить 10 процессов MPI. Использование 9 процессов MPI не вызывает проблем. В моем втором обновлении вы можете видеть, что у меня нет проблем, когда я использую предварительно скомпилированную версию из Ubuntu.   -  person Stefan    schedule 02.09.2013
comment
Я думаю, вы неправильно поняли мой комментарий. В любом случае, это, вероятно, ошибка в MKL, появившаяся в компиляторах 12.x, поскольку она правильно работает с MKL из 11.1. Ошибка все еще присутствует в последней и лучшей бета-компиляторе.   -  person Hristo Iliev    schedule 02.09.2013


Ответы (2)


Я не знаю ответа, и рискну предположить, что набор людей, которые участвуют в SO, и тех, кто знает ответ на ваш вопрос, равен ‹ 1. Однако я бы предположил, что вам может немного повезти, если вы спросите на scicomp или связавшись с командой ScaLAPACK в Университете Теннесси напрямую через их страница поддержки. Удачи!

person Wesley Bland    schedule 29.08.2013
comment
О, я думаю, что количество постоянных участников поблизости, которые могут ответить на этот вопрос, составляет примерно 2 (Джонатан Дурси и Христо Илиев). Давайте подождем и посмотрим. - person High Performance Mark; 30.08.2013
comment
Как вы можете видеть в моем редактировании, я нашел простое решение. Я попытаюсь переделать этот пример с GCC и BLACS из netlib, чтобы увидеть, проблема ли это в самом BLACS или в реализации Intel. - person Stefan; 30.08.2013

Я не думаю, что вам нужно много делать, чтобы использовать меньше процессов в SCALAPACK. Подпрограмма BLACS_PINFO возвращает общее количество процессов. Если вы хотите использовать на один меньше, просто выполните 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_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

Я не собирал данные в нулевом процессе. Таким образом, вы можете получить этот вывод, если все процессы являются локальными.

person ztik    schedule 30.08.2013
comment
Сокращение NPROCS неявно осуществляется за счет использования NPROW раз NPCOL процессов при настройке сетки. Я уже заметил, что последний процесс получает свои копии (N|MY)PROW и (N|MY)PCOL, установленные в -1, что не ясно из этого исходного кода. Основная проблема заключается просто в том, что процесс, которого нет в сетке, не вызывает MPI_FINALIZE, хотя это надо делать в BLACS_EXIT. В результате OpenMPI жалуется на аварийное завершение, потому что процесс вызвал MPI_INIT без вызова MPI_FINALIZE. - person Stefan; 30.08.2013
comment
Какой компилятор/ОС/BLACS вы использовали? - person Stefan; 30.08.2013
comment
Я использую gcc 4.7.3 в Linux (ubuntu 13.04). Вероятно, поведение зависит от ОС. Для компиляции я использовал: mpif90 blacs.f -lscalapack-openmpi -lblacs-openmpi -lblacsF77init-openmpi. Кроме того, я думаю, что libblacsF77init позаботится о MPI_INIT и MPI_FINALIZE в фортране. - person ztik; 30.08.2013