Подпрограммы MPI в Fortran

#mpi #fortran90 #subroutine

#mpi #fortran90 #подпрограмма

Вопрос:

Я просмотрел все сообщения по этой теме, которые смог найти, но они, похоже, не решают мою проблему. Я благодарен за любой ввод / помощь / идею. Итак, вот оно:

У меня есть моя основная программа (main.f90):

     program inv_main

    use mod_communication

    implicit none

    include 'mpif.h'   

    ...

    call MPI_INIT(ierr) 

    call MPI_COMM_RANK(MPI_COMM_WORLD,id,ierr)

    call MPI_COMM_SIZE(MPI_COMM_WORLD,nproc,ierr) 

    ...

    call SENDRECEIVE(id, nproc, ierr, VVNP, VVN)

    ...

    call MPI_FINALIZE(ierr) 
    end program inv_main  
  

И вот модуль, который включает в себя подпрограмму (я знаю, что allgather мог бы быть лучшим способом сделать то же самое, но я пока не смог понять это для моего 4D-массива):

     Module mod_communication

    implicit none

    include 'mpif.h'

    integer, dimension(MPI_STATUS_SIZE) :: STATUS ! MPI

    CONTAINS

    Subroutine SENDRECEIVE(id, nproc, ierr, INPUT, OUTPUT )

    integer, intent (in) :: nproc, id, ierr 

    real (dp), intent(in) ::  INPUT(n,m) 

    real (dp), intent(out) :: OUTPUT(n,m,nty,nty)

    integer :: sndr

    IF (id .eq. 0) THEN

    OUTPUT(1:n,1:m,1,1)=INPUT 

    call MPI_RECV(INPUT,n*m,MPI_DOUBLE_PRECISION,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,STATUS,ierr)
    sndr=STATUS(MPI_SOURCE)

    OUTPUT(1:n,1:m,int(sndr/nty) 1,sndr 1-nty*(int(sndr/nty))) = INPUT

    END IF


    IF (id .ne. 0) THEN 

    call MPI_SEND(INPUT,n*m,MPI_DOUBLE_PRECISION,0,id,MPI_COMM_WORLD,ierr)

    ENDIF

    call MPI_BARRIER(MPI_COMM_WORLD,ierr)

    call MPI_BCAST(OUTPUT,n*m*nty*nty,MPI_DOUBLE_PRECISION,0,MPI_COMM_WORLD,ierr)

    end Subroutine 

    end Module mod_communication
  

Это сообщение об ошибке, которое я получил при компиляции:

     use mod_communication
      2
    Error: Symbol 'mpi_displacement_current' at (1) conflicts with symbol from module  'mod_communication', use-associated at (2)
    mpif-mpi-io.h:71.36:
    Included at mpif-config.h:65:
    Included at mpif-common.h:70:
    Included at mpif.h:59:
    Included at main.f90:27:

    integer MPI_MAX_DATAREP_STRING
                                1
    main.f90:21.6:

    use mod_communication
     2
    Error: Symbol 'mpi_max_datarep_string' at (1) conflicts with symbol from module 'mod_communication', use-associated at (2)
    mpif-mpi-io.h:73.32:
    Included at mpif-config.h:65:
    Included at mpif-common.h:70:
    Included at mpif.h:59:
    Included at main.f90:27:

    parameter (MPI_FILE_NULL=0)
  

Это только первые две ошибки, так продолжается и дальше… И я не могу найти свою ошибку. Кроме того, я должен использовать «включить ‘mpif.h'», а не «использовать mpi» из-за машины, на которой я в конечном итоге собираюсь ее запустить. Однако, если я скомпилирую его с использованием mpi на моем собственном компьютере, это выдает другую ошибку, которая заключается в следующем:

     mod_MPI.f90:93.41:

    call MPI_BARRIER(MPI_COMM_WORLD,ierr)
                                     1
    Error: There is no specific subroutine for the generic 'mpi_barrier' at (1)
    mod_MPI.f90:52.41:
  

Комментарии:

1. Если вы собираетесь использовать Fortran MPI, я бы настоятельно рекомендовал вам найти способ использовать «use mpi» на вашем конечном компьютере (просто попросите своего системного администратора создать привязки fortran), потому что, как вы видите здесь, проверка во время компиляции и сообщения об ошибках становятся намного лучше. В частности, здесь вы не можете использовать фиктивную переменную intent (in) для вызова ierr в MPI_Barrier, поскольку MPI_Barrier изменяет ierr, что недопустимо для аргумента intent (in). Я бы также настоятельно рекомендовал вам не использовать пространство имен MPI_ для ваших собственных функций (например, вашего собственного MPI_SENDRECEIVE); стандарт запрещает это, и другие будут напрасно сбиты с толку.

2. Большое спасибо за ваши комментарии! Я избавился от всех своих собственных mpi_namespace. С включением mpif. h Я все еще получаю то же сообщение об ошибке.

3. Ах, теперь я понял, все отлично работает с «use mpi» и устраняет барьеры! Большое спасибо! (Итак, в качестве вывода: в модулях нет барьеров?)

4. Проблема не в барьере как таковом (хотя это правда, что я вижу много ненужных, дорогостоящих барьеров в коде MPI people’s), а в попытке изменить аргумент intent (in) любыми способами, в том числе в вызове подпрограммы.

5. Итак, другой способ исправить это, на случай, если я захочу иметь барьер в своем модуле, было бы сделать его переменной intent (inout)? Только что я поместил барьер в основной код вместо этого. Я подумал, что мне это нужно здесь, потому что я собираю все это с разных процессоров, а затем хочу разослать готовую матрицу всем. То есть мне вообще не понадобился бы барьер? (Извините за все вопросы, я довольно новичок в этом)

Ответ №1:

Ваша основная программа, вероятно, получает (или, скорее, пытается получить) две копии всего содержимого в mpif.h . include Вводя это в модуль, вы эффективно превращаете все его содержимое в модульные объекты (переменные, подпрограммы, параметры, «что нельзя»). Затем, main вы оба use используете модуль и, таким образом, ассоциируете элементы модуля с использованием и пытаетесь include mpif.h повторно объявить все эти элементы снова.

Сделайте также то, что предлагает @Jonathan Dursi.

Комментарии:

1. Большое спасибо! Теперь все работает идеально! Просто нужно попросить моего системного администратора разрешить мне использовать «использовать mpi»… Значит, включение mpif.h никогда не будет работать подобным образом?