我正在尝试通过 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 的使用似乎也并不容易,因为文件格式已被其他预处理和后处理代码共享。
有没有人有经验或者知道治疗方法?
最好的,杰夫