#compilation #fortran #mpi #gnu
#Сборник #fortran #mpi #gnu
Вопрос:
Эта программа Fortran MPI, на мой взгляд, совершенно проста:
program what
use mpi
integer(4), parameter :: ksp = 4
integer(4), parameter :: kdp = 8
integer(ksp) :: nreadslb
integer(ksp), ALLOCATABLE :: all_nreadslb(:)
real(kdp) :: compute_time
real(kdp), ALLOCATABLE :: all_compute_times(:)
integer(ksp) :: myrank
integer :: ierr
call mpi_init(ierr)
allocate(all_nreadslb(10), all_compute_times(10))
CALL MPI_GATHER(compute_time, 1, amp;
MPI_DOUBLE_PRECISION, all_compute_times, 1, amp;
MPI_DOUBLE_PRECISION, 0, MPI_COMM_WORLD, ierr)
CALL MPI_GATHER(nreadslb, 1, MPI_INTEGER4, amp;
all_nreadslb, 1, MPI_INTEGER4, 0, amp;
MPI_COMM_WORLD, ierr)
call mpi_finalize(ierr)
end program
Но не удается скомпилировать на платформе Cray под GNU. Возвращаемая ошибка:
23 | CALL MPI_GATHER(compute_time, 1, amp;
| 2
......
26 | CALL MPI_GATHER(nreadslb, 1, MPI_INTEGER4, amp;
| 1
Error: Type mismatch between actual argument at (1) and actual argument at (2) (INTEGER(4)/REAL(8)).
Реальная проблема заключается в том, что если я закомментирую первый MPI_GATHER, второй компилируется просто отлично, и если я закомментирую второй MPI_GATHER, первый компилируется просто отлично. В наличии их обоих в коде есть что-то, что не нравится компилятору GNU. Просто для усмешки я вставил между ними инструкцию debug; получил ту же ошибку. Код отлично компилируется под Cray или Intel Fortran.
Есть идеи, в чем может быть проблема?
РЕДАКТИРОВАТЬ: я использую среду Cray PrgEnv-gnu / 6.0.9, которая использует gfortran из gcc 10.1.0 и Cray MPICH 7.7.16. Я выполняю компиляцию с помощью команды Cray «ftn», без флагов, просто ftn what.f90
. Также выяснилось, что проблема связана с gcc 10.1.0; код отлично компилируется под 9.3.0. Так что это решает непосредственную проблему. Но если кто-нибудь знает, что делать под 10.1.0 (поскольку 9.3.0 не будет длиться вечно), хотелось бы это услышать! Спасибо.
Комментарии:
1. Какой компилятор вы используете? Как выглядит ваша команда компиляции? Какую версию компилятора и версию библиотеки MPI вы используете? Вы пробовали какую-либо другую версию?
2. Если
mpi_gather
не является универсальным или использует предполагаемый тип / подходящие полиморфные фиктивные аргументы, то да, не разрешается вызывать его дважды с двумя разными типами аргументов. Можете ли вы попробоватьuse mpi_f08
вместо этого получить полный модуль, совместимый с Fortran 2008?3. @francescalus
mpi_gather
может использоваться практически для любого типа данных (в пределах разумного), и я много раз видел, как он работает с несколькими типами данных в одном коде; даже делал это сам. Тем не менее, спасибо.4. Можете ли вы попробовать с
use mpi_f08
вместоuse mpi
и обновить нас? Частью мотивации предоставления этого модуля (интерфейса F2008) являются известные проблемы, из-за которых действительно очень сложно предоставить интерфейс MPI, совместимый с F95 (например, эта ошибка, с которой вы столкнулись).5. Ах, хорошо. Это необязательное дополнение, поэтому может быть недоступно. Если присутствует, это было бы в том же месте (я бы ожидал, но зависит от вашей реализации MPI). Я предполагаю, что вы застряли со старыми флагами компилятора / compiler, увы.
Ответ №1:
Не вдаваясь в подробности о том, следует ли принимать программу-пример или почему, поскольку это зависит от языковой версии Fortran и от деталей используемого модуля MPI, GCC 10 обеспечивает более строгую проверку типов для аргументов процедуры Fortran. Вы должны быть в состоянии преобразовать эти конкретные ошибки в предупреждения, добавив -fallow-argument-mismatch
параметр в командную строку компиляции. Это было эффективно для других проектов, таких как NetCDF.
Комментарии:
1. Спасибо, я подозревал что-то подобное. Это может даже повлиять на мою кодовую базу. Это сложнее проверить, поскольку сначала нужно перекомпилировать библиотеку MPI и многие другие библиотеки с GCC 10, поэтому я чаще всего тестирую только версию, отличную от MPI, с самыми последними компиляторами. Но, возможно, я в порядке, потому что я уже использовал
-Wargument-mismatch
и-Werror
.2. @VladimirF Так что, черт возьми, нам делать? В краткосрочной перспективе я просто вернусь к gcc 9, но это не является хорошим долгосрочным решением. Предложенный Джоном флаг у меня не сработал.
3. @bob.sacamento, добавление этого флага является рекомендуемым подходом GCC для того, чтобы заставить компилятор принять код, который отклонен из-за изменения. Я полагаю, что, поскольку это приводит к преобразованию ошибок в предупреждения, это может оказаться неэффективным, если вы также укажете
-Werror
. Я не думаю, что мы можем сказать больше без деталей, которые запросил Владимир.4. Джон, пробую как ваш флаг, так и Владимира. С и без
-Werror
. Результат в любом случае не изменился. Спасибо.
Ответ №2:
UPD: Похоже, что рецепт при работе в GCC10 в Ubuntu 20.04 вызывает повреждение памяти, по крайней мере, с GNU Fortran (GCC) 8.3.0 20190222 (Cray Inc.) и cray-mpich / 7.7.9. Используйте с особой осторожностью!
Компиляция вашего кода с использованием OpenMPI проходит без проблем. Проблема в привязках MPICH, и до сих пор ведутся споры о том, следует ли исправить gcc или MPICH :).
Мне не нравится идея подавления любых предупреждений, поскольку иногда они могут помочь. Другим способом было бы обернуть C_LOC() вокруг рассматриваемых аргументов (это наилучшее соответствие void * в реальных вызовах C позади). Эта оболочка не должна причинять вреда независимо от библиотеки MPI или версии компилятора.
Вам нужно будет добавить
use, intrinsic :: ISO_C_BINDING, only: c_loc
в преамбуле программы объявите первые аргументы вызовов для MPI_GATHER в качестве ЦЕЛЕВЫХ (также подойдут указатели)
integer(ksp), TARGET :: nreadslb
integer(ksp), ALLOCATABLE, TARGET :: all_nreadslb(:)
real(kdp), TARGET :: compute_time
real(kdp), ALLOCATABLE, TARGET :: all_compute_times(:)
и оберните аргументы с помощью C_LOC
CALL MPI_GATHER(C_LOC(compute_time), 1, amp;
MPI_DOUBLE_PRECISION, C_LOC(all_compute_times), 1, amp;
MPI_DOUBLE_PRECISION, 0, MPI_COMM_WORLD, ierr)
CALL MPI_GATHER(C_LOC(nreadslb), 1, MPI_INTEGER4, amp;
C_LOC(all_nreadslb), 1, MPI_INTEGER4, 0, amp;
MPI_COMM_WORLD, ierr)
Затем компиляция проходит без ошибок.