Como faço para manter a precisão de um programa Fortran MPI de maneira portátil?
Eu tenho um programa Fortran onde eu especifico okind
dos tipos de dados numéricos em uma tentativa de manter um nível mínimo de precisão, independentemente de qual compilador é usado para construir o programa. Por exemplo:
integer, parameter :: rsp = selected_real_kind(4)
...
real(kind=rsp) :: real_var
O problema é que usei MPI para paralelizar o código e preciso ter certeza de que as comunicações MPI estão especificando o mesmo tipo com a mesma precisão. Eu estava usando a seguinte abordagem para me manter consistente com a abordagem do meu programa:
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)
No entanto, descobri que esta rotina MPI não é particularmente bem suportada para diferentes implementações de MPI, por isso está realmente tornando meu programa não portátil. Se eu omitir oMPI_Type_create
rotina, então eu sou deixado para confiar no padrãoMPI_REAL
eMPI_DOUBLE_PRECISION
tipos de dados, mas e se esse tipo não for consistente com o queselected_real_kind
escolhe como o tipo real que será repassado pelo MPI? Estou preso apenas usando o padrãoreal
declaração para um tipo de dados, semkind
atributo e, se eu fizer isso, estou garantido queMPI_REAL
ereal
sempre terão a mesma precisão, independentemente do compilador e da máquina?
ATUALIZAR:
Eu criei um programa simples que demonstra o problema que vejo quando meus reais internos têm uma precisão maior do que a oferecida peloMPI_DOUBLE_PRECISION
tipo:
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
Se eu construir e rodar com 2 núcleos, recebo:
0 1.12345683574676513672
1 4.71241976735884452383E-3998
Agora mude o 16 para um 15 emselected_real_kind
e eu recebo:
0 1.1234568357467651
1 1.1234568357467651
Será sempre seguro usarselected_real_kind(15)
comMPI_DOUBLE_PRECISION
não importa qual máquina / compilador é usado para fazer a compilação?