首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用MPI-I/O读取Fortran非格式化文件中的实体

用MPI-I/O读取Fortran非格式化文件中的实体
EN

Stack Overflow用户
提问于 2013-09-05 21:10:29
回答 1查看 1.1K关注 0票数 1

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

代码语言:javascript
复制
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选项进行编译(我为英特尔编译器添加了'-convert big_endian‘选项),则英特尔MPI的结果略有不同(似乎是与字节相关的问题):

代码语言:javascript
复制
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的数据表示替换为"native“+设置disp=4跳过Fortran未格式化格式的第一个4字节记录标记+没有额外的编译标志),MPI-I/O读取的值完全相同。但是,由于网格文件是以大端格式给出的,所以我必须继续使用'-convert big_endian‘选项。

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

有没有人有过这样的经验或者知道解决办法?

最好的,杰夫

EN

回答 1

Stack Overflow用户

发布于 2013-09-06 00:10:37

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

至于使用英特尔MPI时浮点数的值稍有错误:64位IEEE754中的0.1428571492433550x3FC24924A0000000。根据英特尔MPI (可以使用MPI_PACK_EXTERNAL验证),此数字的external32表示为:

代码语言:javascript
复制
A0 00 00 00 3F C2 49 24

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

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

代码语言:javascript
复制
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位IEEE754表示中的0.142857074737549

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18637287

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档