【问题标题】:Using MPI-I/O to Read the Real Entity in an Fortran Unformatted File使用 MPI-I/O 读取 Fortran 无格式文件中的真实实体
【发布时间】:2013-09-09 08:16:12
【问题描述】:

我正在尝试通过 MPI-I/O 读取 CFD 网格文件。该文件是大端格式的 Fortran 无格式格式,它包含整数和实数 *8 的混合变量(文件以块大小的整数开头,后跟该块的 x、y、z 坐标)。我可以设法读取第一个整数,但真正的实体完全错误或不那么准确。所以我简化了代码以重现相同的错误。它以 Fortran 无格式格式将一个实数值写入文件,并尝试以串行和并行方式(通过 MPI-I/O)将其读回:

program readtest
implicit none
include 'mpif.h'

   integer :: myrank,nproc,ierr,istatus(MPI_STATUS_SIZE)
   integer :: mpifile
   integer :: rdsize
   integer(kind=MPI_OFFSET_KIND) :: disp
   character(len=80) :: mpifiname
   double precision :: in,vals,valp

! Define MPI basics
   call MPI_INIT(ierr)
   call MPI_COMM_RANK(MPI_COMM_WORLD,myrank,ierr)
   call MPI_COMM_SIZE(MPI_COMM_WORLD, nproc,ierr)

! Initialize
   in = 1.0/7.0
   vals = 0.0
   valp = 0.0

! Write a serial files
   open(10,file='Serial.dat',form='unformatted')
   write(10) in
   close(10)

! Serial file read
   open(10,file='Serial.dat',form='unformatted',status='old')
   read(10) vals
   close(10)

! Read by MPI-I/O
   mpifiname = 'Serial.dat'

   disp = 0
   call MPI_FILE_OPEN(MPI_COMM_WORLD, mpifiname, &
                      MPI_MODE_RDONLY, &
                      MPI_INFO_NULL, mpifile, ierr)
   call MPI_FILE_SET_VIEW(mpifile,disp,MPI_BYTE,MPI_BYTE,"external32",&
                          MPI_INFO_NULL,ierr)
   rdsize = 0
   if(myrank == 0) rdsize = 1
   call MPI_FILE_READ_ORDERED(mpifile, valp, rdsize, MPI_DOUBLE_PRECISION, &
                               istatus, ierr)
   call MPI_FILE_CLOSE(mpifile, ierr)

   write(*,*) 'Input: ',in,'Serial:',vals,' Parallel:',valp

   call MPI_FINALIZE(ierr)

stop
end

如果你使用 big-endian 选项编译(我为 Intel 编译器添加了 '-convert big_endian' 选项),Intel MPI 的结果略有不同(这似乎是字节相关的问题):

mpirun -np 1 ./a.out

 Input:   0.142857149243355      Serial:  0.142857149243355       Parallel:
  0.142857074737549 (from Intel MPI)
 Input:   0.142857149243355      Serial:  0.142857149243355       Parallel:
  3.398201204542405E-312 (from OpenMPI)

如果我放弃大端模式(即,将MPI_FILE_OPEN的数据表示替换为“native”+设置disp=4跳过Fortran无格式格式的第一个4字节记录标记+没有额外的编译标志),MPI-I /O 读取完全相同的值。但是,由于网格文件是以大端格式给出的,我必须继续使用“-convert big_endian”选项。

HDF-5 的使用似乎并不容易,因为文件格式已被其他预处理和后处理代码共享。

有没有人有经验或知道补救措施?

最好, 杰夫

【问题讨论】:

  • 也可以通过用户代码转换字节顺序(例如,使用transfer)。

标签: io fortran mpi-io


【解决方案1】:

虽然 MPI 中通信操作的默认错误处理程序是 MPI_ERRORS_ARE_FATAL,因此如果发生任何类型的通信错误,程序会中止,但文件 I/O 操作的默认错误处理程序是 MPI_ERRORS_RETURN,这意味着程序继续执行并返回错误代码。如果您在调用MPI_FILE_SET_VIEW 后检查ierr 的值,您会注意到使用Open MPI 它返回MPI_ERR_UNSUPPORTED_DATAREP。原因是 Open MPI 附带的 ROM-IO 版本没有实现 external32 数据表示。

至于使用 Intel MPI 时浮点数的小错误值:0.142857149243355 in 64-bit IEEE 754 is 0x3FC24924A0000000。根据英特尔 MPI(可以使用 MPI_PACK_EXTERNAL 进行验证),此数字的 external32 表示为:

A0 00 00 00 3F C2 49 24

这根本不是大端存储中的 IEEE 754 编号。相反,它是大端和小端的奇怪混合 - 值被分成两半,每一个都存储在大端中,但下半部分首先出现在小端中。这是英特尔在external32 实现中的一个错误,还是我无法判断的表示的实际怪癖,因为后者在 MPI 标准中几乎没有描述。

在大端机器上编写时,您的未格式化文件可能如下所示:

00 00 00 08 3F C2 49 24 A0 00 00 00 00 00 00 08
----------- ^^^^^^^^^^^^^^^^^^^^^^^ -----------
  reclen         record value          reclen

MPI_FILE_READ_ORDERED 读取的前 8 个字节是00 00 00 08 3F C2 49 24。在英特尔 MPI 将这些字节从 external32 转换回来后,将获得 0x3FC2492400000008,即 64 位 IEEE 754 表示中的 0.142857074737549

【讨论】:

    猜你喜欢
    • 2018-11-29
    • 1970-01-01
    • 2019-12-15
    • 2016-02-29
    • 1970-01-01
    • 1970-01-01
    • 2015-03-13
    • 2018-04-27
    • 2012-04-14
    相关资源
    最近更新 更多