我想通過MPI-I/O讀取CFD網格文件。該文件是一種Fortran無格式格式,具有較大的字節順序,它包含整數和實數* 8的混合變量(文件以塊大小整數開頭,後面跟着該塊的x,y,z座標)。我可以設法讀取第一個整數,但真正的實體完全錯誤或不太準確。所以我簡化了代碼以重現相同的錯誤。它寫出一個真正的價值,用Fortran格式化格式的文件,並嘗試從串行與並行讀回(通過MPI-I/O):使用MPI-I/O讀取Fortran未格式化文件中的實體
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
如果用大端選項編譯(我添加「-convert 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)
如果我放棄大端模式(即,更換MPI_FILE_OPEN的數據表示爲「native」+設置disp = 4以跳過Fortran未格式化格式的第一個4字節記錄標記+不需要額外編譯標記),MPI-I/O讀取完全相同的值。但是,由於網格文件已經以big-endian格式給出,所以我必須繼續使用'-convert big_endian'選項。
由於文件格式已被其他預處理和後處理代碼共享,所以HDF-5的使用也並不容易。
任何人都有經驗或知道的補救措施?
最佳, 傑夫
也可以通過用戶代碼(例如,使用'transfer')來轉換字節序列。 –