2013-09-05 54 views
1

我想通過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的使用也並不容易。

任何人都有經驗或知道的補救措施?

最佳, 傑夫

+0

也可以通過用戶代碼(例如,使用'transfer')來轉換字節序列。 –

回答

4

雖然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位IEEE 754中的0.1428571492433550x3FC24924A0000000。根據英特爾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

相關問題