запуск подпрограммы MPI в программе Fortran - PullRequest
0 голосов
/ 27 мая 2018

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

program my_program

implicit none

!Define variables

nprocs =  !formula for calculating number of processes.

call my_subroutine(output,nprocs,other input vars)

end my_program

Я хочу запустить my_subroutine с тем же эффектом, что и этот:

mpirun -n nprocs my_subroutine.o

, где my_subroutine был скомпилирован с 'otherinput vars. '

Возможно ли это?


Вот простой пример.Я пытаюсь скомпилировать следующим образом: $ mpif90 -o my_program WAVE_2D_FP_TUNER_mpi.f90 randgen.f SIMPLE_ROUTINE.f90 Я пытаюсь запустить его так:

Вот подпрограмма, которую я хочу распараллелить с mpi.


SUBROUTINE SIMPLE_ROUTINE(T,PARAM,R,Z,CMAX,EN,INC,NPROCS,U)
! Outputs scalar U = T*Z*CMAX*INC*SUM(PARAM)*SUM(R)*SUM(Y)
USE MPI

IMPLICIT NONE

REAL(KIND=8), INTENT(IN) :: T,PARAM(1:3),R(1:6),Z,CMAX
INTEGER, INTENT(IN) :: EN,INC
INTEGER, INTENT(IN) :: NPROCS
REAL(KIND=8), INTENT(OUT) :: U
REAL(KIND=8) :: H,LOCAL_SUM,SUM_OF_X
REAL(KIND=8), DIMENSION(:), ALLOCATABLE :: X
INTEGER :: PX,PX_MAX,NXL,REMX,IX_OFF,P_LEFT,P_RIGHT
INTEGER :: J
INTEGER :: IERR,MYID

! Broadcast nprocs handle to all processes in MPRI_COMM_WORLD
CALL MPI_BCAST(&NPROCS, NPROCS, MPI_INT, 0, MPI_COMM_WORLD,IERR)
! Create subcommunicator SUBCOMM  (Do not know how to define WORLD_GROUP?)
CALL MPI_COMM_SPLIT(MPI_COMM_WORLD,WORLD_GROUP,SUBCOMM,IERR)
! Assign IDs to processes in SUBCOMM
CALL MPI_COMM_RANK(SUBCOMM,MYID,IERR)
! Give NPROCS - 1 to SUBCOMM
CALL MPI_COMM_SIZE(SUBCOMM,NPROCS-1,IERR)

H = 2.D0/(EN-1)

! LABEL THE PROCESSES FROM 1 TO PX_MAX.
PX = MYID + 1
PX_MAX = NPROCS
! SPLIT UP THE GRID IN THE X-DIRECTION.
NXL = EN/PX_MAX !nxl = 10/3 = 3
REMX = EN-NXL*PX_MAX !remx = 10-3*3 = 1
IF (PX .LE. REMX) THEN !for px = 1,nxl = 3
    NXL = NXL+1 !nxl = 4
    IX_OFF = (PX-1)*NXL !ix_off = 0
ELSE
    IX_OFF = REMX*(NXL+1)+(PX-(REMX+1))*NXL !for px = 2 and px = 3, ix_off = 1*(3+1)+(2-(1+1))*3 = 4, ix_off = 1*(3+1)+(3-(1+1))*3 = 7
END IF

! ALLOCATE MEMORY FOR VARIOUS ARRAYS.
ALLOCATE(X(0:NXL+1))
X(:) = (/(-1.D0+DBLE(J-1+IX_OFF)*H, J=1,EN)/)
LOCAL_SUM = SUM(X(1:NXL))
CALL MPI_REDUCE(LOCAL_SUM,SUM_OF_X,1,&
          MPI_DOUBLE_PRECISION,MPI_SUM,&
          0,MPI_COMM_WORLD,IERR)

U = T*Z*CMAX*INC*SUM(PARAM)*SUM(R)*SUM_OF_X

DEALLOCATE(X)

CALL MPI_COMM_FREE(SUBCOMM,IERR)

CALL MPI_BARRIER(MPI_COMM_WORLD,IERR)

END SUBROUTINE SIMPLE_ROUTINE

В конечном счете, я хочу иметь возможность изменить количество процессоров, используемых в подпрограмме, где я хочу, чтобы nprocsрассчитываться по значению EN.

1 Ответ

0 голосов
/ 27 мая 2018

Простой подход состоит в том, чтобы запустить приложение MPI с максимальным числом процессов.

Затем my_subroutine будет сначала MPI_Bcast(&nprocs, ...) и MPI_COMM_SPLIT(MPI_COMM_WORLD, ..., &subcomm), чтобы создать субкоммуникатор subcomm с nprocs (вы можете использовать MPI_UNDEFINED, поэтому «другим» коммуникатором будет MPI_COMM_NULL.

Тогда вычисления MPI, являющиеся частью subcomm, выполнят вычисления.

Наконец, MPI_Comm_free(&subcomm) и MPI_Barrier(MPI_COMM_WORLD)

С точки зрения производительности создание субкоммуникатора заметок может быть дорогостоящим, но, надеюсь, незначительным по сравнению со временем вычислений. Если нет, то вы бы лучше обновили свой алгоритмтаким образом, он может выполнять задачи nprocs, а другие ожидают выполнения.

Другой подход может состоять в том, чтобы запустить ваше приложение с одной задачей MPI, MPI_Comm_spawn() nprocs-1 задач, объединитькоммуникатор, выполнить вычисление и завершить порожденные задачи. Издержки создания задач гораздо важнее, и это может не полностью поддерживаться вашим менеджером ресурсов, поэтому я бы не советовал эту опцию.

...