Как сохранить точность для программы Fortran MPI портативным способом?
У меня есть программа на Фортране, где я указываюkind
числовых типов данных в попытке сохранить минимальный уровень точности, независимо от того, какой компилятор используется для сборки программы. Например:
integer, parameter :: rsp = selected_real_kind(4)
...
real(kind=rsp) :: real_var
Проблема в том, что я использовал MPI для распараллеливания кода, и мне нужно убедиться, что связи MPI задают один и тот же тип с одинаковой точностью. Я использовал следующий подход, чтобы оставаться в соответствии с подходом в моей программе:
call MPI_Type_create_f90_real(4,MPI_UNDEFINED,rsp_mpi,mpi_err)
...
call MPI_Send(real_var,1,rsp_mpi,dest,tag,MPI_COMM_WORLD,err)
Однако я обнаружил, что эта подпрограмма MPI не особенно хорошо поддерживается для различных реализаций MPI, поэтому она фактически делает мою программу непереносимой. Если я опущуMPI_Type_create
рутина, то мне осталось положиться на стандартMPI_REAL
а такжеMPI_DOUBLE_PRECISION
типы данных, но что, если этот тип не соответствует тому, чтоselected_real_kind
выбирает как реальный тип, который в конечном итоге будет передан MPI? Я застрял только с использованием стандартаreal
декларация для типа данных, безkind
атрибут и, если я это сделаю, я гарантирую, чтоMPI_REAL
а такжеreal
всегда будет иметь одинаковую точность, независимо от компилятора и машины?
ОБНОВИТЬ:
Я создал простую программу, которая демонстрирует проблему, которую я вижу, когда мои внутренние реалы имеют более высокую точность, чем то, что даетMPI_DOUBLE_PRECISION
тип:
program main
use mpi
implicit none
integer, parameter :: rsp = selected_real_kind(16)
integer :: err
integer :: rank
real(rsp) :: real_var
call MPI_Init(err)
call MPI_Comm_rank(MPI_COMM_WORLD,rank,err)
if (rank.eq.0) then
real_var = 1.123456789012345
call MPI_Send(real_var,1,MPI_DOUBLE_PRECISION,1,5,MPI_COMM_WORLD,err)
else
call MPI_Recv(real_var,1,MPI_DOUBLE_PRECISION,0,5,MPI_COMM_WORLD,&
MPI_STATUS_IGNORE,err)
end if
print *, rank, real_var
call MPI_Finalize(err)
end program main
Если я собираю и запускаю с 2 ядрами, я получаю:
0 1.12345683574676513672
1 4.71241976735884452383E-3998
Теперь измените 16 на 15 вselected_real_kind
и я получаю:
0 1.1234568357467651
1 1.1234568357467651
Всегда ли это будет безопасно использоватьselected_real_kind(15)
с участиемMPI_DOUBLE_PRECISION
независимо от того, какая машина / компилятор используется для сборки?