gpt4 book ai didi

fortran - 如何以可移植的方式保持 Fortran MPI 程序的精度?

转载 作者:行者123 更新时间:2023-12-03 22:39:30 25 4
gpt4 key购买 nike

我有一个 Fortran 程序,我在其中指定数字数据类型的 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_REALMPI_DOUBLE_PRECISION 数据类型,但是如果该类型与 selected_real_kind 选择的最终由 MPI 传递的真实类型不一致怎么办?我是否只对数据类型使用标准 real 声明,而没有 kind 属性,如果我这样做,我是否可以保证 MPI_REALreal 始终具有相同的精度,而不管编译器和机器如何?

更新:

我创建了一个简单的程序来演示当我的内部实数比 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

现在将 selected_real_kind 中的 16 更改为 15,我得到:
       0   1.1234568357467651     
1 1.1234568357467651

无论使用什么机器/编译器进行构建,使用 selected_real_kind(15)MPI_DOUBLE_PRECISION 总是安全的吗?

最佳答案

使用 Fortran 2008 内在 STORAGE_SIZE 来确定每个数字需要的字节数并将其作为字节发送。请注意,STORAGE_SIZE 以位为单位返回大小,因此您需要除以 8 才能获得以字节为单位的大小。

此解决方案适用于移动数据,但不能帮助您使用缩减。为此,您必须实现用户定义的归约操作。如果这对您很重要,我会用详细信息更新我的答案。

例如:

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,storage_size(real_var)/8,MPI_BYTE,1,5,MPI_COMM_WORLD,err)
else
call MPI_Recv(real_var,storage_size(real_var)/8,MPI_BYTE,0,5,MPI_COMM_WORLD,&
MPI_STATUS_IGNORE,err)
end if

print *, rank, real_var

call MPI_Finalize(err)

end program main

我确认此更改纠正了问题,我看到的输出是:
   0   1.12345683574676513672      
1 1.12345683574676513672

关于fortran - 如何以可移植的方式保持 Fortran MPI 程序的精度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19726509/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com