#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 никогда не будет работать подобным образом?