我正在尝试通过MPI-I / O读取CFD网格文件。该文件是具有big-endianness的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选项进行编译(我为英特尔编译器添加' - 转换big_endian'选项),则英特尔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)
如果我放弃big-endian模式(即,将MPI_FILE_OPEN的数据表示替换为" native" + set disp = 4以跳过Fortran未格式化格式的第一个4字节记录标记+没有额外的编译标志),MPI-I / O读取完全相同的值。但是,由于网格文件是以big-endian格式给出的,我必须继续使用' -convert big_endian'选项。
HDF-5的使用似乎也不容易,因为其他预处理和后处理代码共享了文件格式。
有人有经验或知道补救措施吗?
最佳, 杰夫
答案 0 :(得分:4)
虽然MPI中通信操作的默认错误处理程序是MPI_ERRORS_ARE_FATAL
,因此如果发生任何类型的通信错误,程序将被中止,文件I / O操作的默认错误处理程序为MPI_ERRORS_RETURN
,这意味着程序继续执行并返回错误代码。如果您在调用ierr
后检查MPI_FILE_SET_VIEW
的值,您会注意到使用Open MPI它会返回MPI_ERR_UNSUPPORTED_DATAREP
。原因是Open MPI附带的ROM-IO版本没有实现external32
数据表示。
对于使用英特尔MPI时浮点数的略微错误的值:64位IEEE 754中的0.142857149243355
为0x3FC24924A0000000
。根据英特尔MPI(可以使用external32
进行验证),此数字的MPI_PACK_EXTERNAL
表示形式为:
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
。