【发布时间】:2013-11-12 15:20:04
【问题描述】:
我有一个 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_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
现在将 selected_real_kind 中的 16 更改为 15,我得到:
0 1.1234568357467651
1 1.1234568357467651
无论使用什么机器/编译器进行构建,使用selected_real_kind(15) 和MPI_DOUBLE_PRECISION 总是安全的吗?
【问题讨论】:
-
我使用的代码将其工作精度定义为
wp = selected_real_kind(14,40),然后在MPI 调用中使用MPI_DOUBLE_PRECISION。据我所知,没有问题。 -
我添加了一个简单的例子来说明我需要避免什么问题。所以我想知道,如果我明确定义他们的
kind,我的reals 是否总是与MPI_DOUBLE_PRECISION兼容? -
上次我检查过,使用 16 表示四倍精度(因此是 -3998 范围),这不适用于
MPI_DOUBLE_PRECISION。只要您使用 7 到 15(含)之间,您应该可以使用MPI_DOUBLE_PRECISION。 -
是的,你是对的。但是
MPI_DOUBLE_PRECISION是否总是意味着无论系统/编译器如何,MPI 通信都保持 7 到 15 位精度?换句话说,如果我将我的reals 指定为 14 位精度,然后与MPI_DOUBLE_PRECISION进行 MPI 通信,我是否会担心得到像我发布的那样的结果,其中号码在接收端作为垃圾出现? -
不使用
selected_real_kind,您可以使用use ISO_FORTRAN_ENV并使用类型real32和real64(位数)可移植地指定单精度和双精度实数。