繁体   English   中英

使用MPI-IO编写Fortran格式的文件

Using MPI-IO to write Fortran-formatted files

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我正在尝试使用OVERFLOW-PLOT3D q文件格式(在此定义: http ://overflow.larc.nasa.gov/files/2014/06/Appendix_A.pdf)保存一个解决方案。 对于单个网格,基本上是

READ(1) NGRID
READ(1) JD,KD,LD,NQ,NQC
READ(1) REFMACH,ALPHA,REY,TIME,GAMINF,BETA,TINF, &
        IGAM,HTINF,HT1,HT2,RGAS1,RGAS2, &
        FSMACH,TVREF,DTVREF
READ(1) ((((Q(J,K,L,N),J=1,JD),K=1,KD),L=1,LD),N=1,NQ)    

所有变量都是双精度数字,但NGRID,JD,KD,LD,NQ,NQC和IGAM是整数。 我需要使用MPI-IO导出解决方案。 如果我仅用一个处理器做一个非常简单的示例,以下代码将不起作用,但是我不明白为什么。

call mpi_file_open( mpi_comm_world, fileOut, mpi_mode_wronly + mpi_mode_create, &
                  mpi_info_null, mpi_fh, ierr )
offset = 0
call mpi_file_seek( mpi_fh, offset, mpi_seek_set, ierr )
call mpi_file_write( mpi_fh, (/NGRID,JD,KD,LD,NQ,NQC/), 6, mpi_integer, mstat, ierr )
call mpi_file_write( mpi_fh, (/REFMACH,ALPHA,REY,TIME,GAMINF,BETA,TINF/), 7, mpi_double_precision, mstat, ierr )
call mpi_file_write( mpi_fh, IGAM, 1, mpi_integer, mstat, ierr )
call mpi_file_write( mpi_fh, (/HTINF,HT1,HT2,RGAS1,RGAS2,FSMACH,TVREF,DTVREF/), 8, mpi_double_precision, mstat, ierr )

call mpi_file_write( mpi_fh, Q, NQ*JD*KD*LD, mpi_double_precision, mstat, ierr )

Tecplot无法识别格式。 但是,如果我编写这样的简单非MPI代码:

open(2, file=fileOut, form='unformatted', convert='little_endian')
write(2) NGRID
write(2) JD, KD, LD, NQ, NQC
write(2) REFMACH,ALPHA,REY,TIME,GAMINF,BETA,TINF, &
         IGAM,HTINF,HT1,HT2,RGAS1,RGAS2, &
         FSMACH,TVREF,DTVREF
write(2) ((((Q(J,K,L,N),J=1,JD),K=1,KD),L=1,LD),N=1,NQ)

一切正常。 我的MPI-IO代码有什么问题?? 非常感谢您的帮助!

约阿希姆

注意:我不知道这是否相关,但是如果我在最后的write语句之前添加一个mpi_file_seek(offset),其偏移量为144。 Tecplot同意加载文件(但是数据无法正确读取)。 这很奇怪,因为普通偏移量应该是7个整数+ 15个实数* 8 = 148个字节...

编辑:由于某种原因,您的方法@Jonathan Dursi似乎与Tecplot不兼容。 以下代码有什么问题吗? (简化为单个处理器)

 call MPI_File_write(fileh, [4, ngrid, 4], 3, MPI_INTEGER, MPI_STATUS_IGNORE, ierr)
 call MPI_File_write(fileh, [20, jd, kd, ld, nq, nqc, 20], 7, MPI_INTEGER, MPI_STATUS_IGNORE, ierr)
 call MPI_File_write(fileh, [56], 1, MPI_INTEGER, MPI_STATUS_IGNORE, ierr)
 call MPI_File_write(fileh, [refmach,alpha,rey,time,gaminf,beta,tinf], 7, MPI_double_precision, MPI_STATUS_IGNORE, ierr)
 call MPI_File_write(fileh, [56], 1, MPI_INTEGER, MPI_STATUS_IGNORE, ierr)
 call MPI_File_write(fileh, [4, IGAM, 4], 3, MPI_INTEGER, MPI_STATUS_IGNORE, ierr)
 call MPI_File_write(fileh, [64], 1, MPI_INTEGER, MPI_STATUS_IGNORE, ierr)
 call MPI_File_write(fileh, [HTINF,HT1,HT2,RGAS1,RGAS2,FSMACH,TVREF,DTVREF], 8, MPI_double_precision, MPI_STATUS_IGNORE, ierr)
 call MPI_File_write(fileh, [64], 1, MPI_INTEGER, MPI_STATUS_IGNORE, ierr)
 call MPI_File_write(fileh, [jd*kd*ld*nq*8], 1, MPI_INTEGER, MPI_STATUS_IGNORE, ierr)
 call MPI_File_write(fileh, q, jd*kd*ld*nq, MPI_double_precision, MPI_STATUS_IGNORE, ierr)
 call MPI_File_write(fileh, [jd*kd*ld*nq*8], 1, MPI_INTEGER, MPI_STATUS_IGNORE, ierr)
1 个回复

@francescalus是正确的-Fortran 顺序无格式数据是基于记录的-实际上对很多事情来说确实很不错,但没有其他东西使用它(即使是Fortran中的MPI-IO,也更像C-文件只是一个很大的长未区分的字节流)。

让我们看一下问题中写作程序的简化版本:

program testwrite

integer, parameter:: ngrid=2
integer, parameter:: jd=4, kd=3, ld=2, nq=1, nqc=-1

integer, parameter :: refmach=1, alpha=2, rey=3, time=4, gaminf=5
integer, parameter :: beta=6, tinf=7

integer, dimension(jd,kd,ld,nq) :: q
q = 0

open(2, file='ftest.dat', form='unformatted', convert='little_endian')
write(2) NGRID
write(2) JD, KD, LD, NQ, NQC
write(2) REFMACH,ALPHA,REY,TIME,GAMINF,BETA,TINF
write(2) ((((Q(J,K,L,N),J=1,JD),K=1,KD),L=1,LD),N=1,NQ)
close(2)

end program testwrite

运行此命令,并使用od查看生成的二进制文件(为了清楚起见,我将所有内容都设置为整数):

$ gfortran -o fwrite fwrite.f90 
$ ./fwrite 
$ od --format "d" ftest.dat 
0000000           4           2           4          20
0000020           4           3           2           1
0000040          -1          20          28           1
0000060           2           3           4           5
0000100           6           7          28          96
0000120           0           0           0           0
*
0000260          96
0000264

例如,我们在开始处看到ngrid(2)整数,以4/4预定-记录的大小(以字节为单位)。 然后,以20/20预定,我们看到5个整数(5 * 4字节)4,3,2,1,-1-jd,kd,ld,nq,nqc。 到最后,我们看到一串由零表示的零(96等于4个字节/整数* 4 * 3 * 2 * 1),代表q。 (请注意,没有标准来定义这种行为,但是我不知道任何主要的Fortran编译器都不会这样做;但是,当记录变得比4字节整数所描述的大时,行为就会开始不同。

我们可以使用以下简单程序来测试数据文件:

program testread

implicit none

integer :: ngrid
integer :: jd, kd, ld, nq, nqc

integer :: refmach, alpha, rey, time, gaminf
integer :: beta, tinf

integer :: j, k, l, n

integer, allocatable, dimension(:,:,:,:) :: q
character(len=64) :: filename

if (command_argument_count() < 1) then
    print *,'Usage: read [filename]'
else 
    call get_command_argument(1, filename)
    open(2, file=trim(filename), form='unformatted', convert='little_endian')
    read(2) NGRID
    read(2) JD, KD, LD, NQ, NQC
    read(2) REFMACH,ALPHA,REY,TIME,GAMINF,BETA,TINF

    allocate(q(jd, kd, ld, nq))
    read(2) ((((Q(J,K,L,N),J=1,JD),K=1,KD),L=1,LD),N=1,NQ)
    close(2)

    print *, 'Ngrid = ', ngrid
    print *, 'jd, kd, ld, nq, nqc = ', jd, kd, ld, nq, nqc

    print *, 'q: min/mean/max = ', minval(q), sum(q)/size(q), maxval(q)
    deallocate(q)
endif

end program testread

而跑步给

$ ./fread ftest.dat 
 Ngrid =            2
 jd, kd, ld, nq, nqc =            4           3           2           1          -1
 q: min/mean/max =            0           0           0

很简单。

因此,这种行为在MPI-IO中非常容易模仿。 这里实际上有三部分-标头Q(我认为是分布式的)(例如MPI子数组)和页脚(仅是数组的书挡)。

因此,让我们看一下Fortran中的MPI-IO程序,该程序将执行相同的操作:

program mpiwrite

  use mpi
  implicit none

  integer, parameter:: ngrid=2
  integer, parameter:: jd=3, kd=3, ld=3, nlocq=3, nqc=-1
  integer :: nq

  integer, parameter :: refmach=1, alpha=2, rey=3, time=4, gaminf=5
  integer, parameter :: beta=6, tinf=7

  integer, dimension(jd,kd,ld,nlocq) :: q

  integer :: intsize
  integer :: subarray

  integer :: fileh
  integer(kind=MPI_Offset_kind) :: offset

  integer :: comsize, rank, ierr

  call MPI_Init(ierr)
  call MPI_Comm_size(MPI_COMM_WORLD, comsize, ierr)
  call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)

  nq = nlocq * comsize
  q = rank

  ! create a subarray; each processor gets its own q-slice of the
  ! global array
  call MPI_Type_create_subarray (4, [jd, kd, ld, nq], [jd, kd, ld, nlocq], &
                                    [0, 0, 0, nlocq*rank], &
                                    MPI_ORDER_FORTRAN, MPI_INTEGER, subarray,  ierr)
  call MPI_Type_commit(subarray, ierr)

  call MPI_File_open(MPI_COMM_WORLD, 'mpi.dat',         &
                     MPI_MODE_WRONLY + MPI_MODE_CREATE, &
                     MPI_INFO_NULL, fileh, ierr )

  ! the header size is:
  !  1 field of 1 integer ( = 4*(1 + 1 + 1) = 12 bytes )
  ! +1 field of 5 integers( = 4*(1 + 5 + 1) = 28 bytes )
  ! +1 field of 7 integers( = 4*(1 + 7 + 1) = 36 bytes )
  ! +first bookend of array size = 4 bytes
  offset = 12 + 28 + 36 + 4

  ! rank 1 writes the header and footer
  if (rank == 0) then
      call MPI_File_write(fileh, [4, ngrid, 4], 3, MPI_INTEGER, &
                          MPI_STATUS_IGNORE, ierr)
      call MPI_File_write(fileh, [20, jd, kd, ld, nq, nqc, 20], 7, MPI_INTEGER, &
                          MPI_STATUS_IGNORE, ierr)
      call MPI_File_write(fileh, &
                        [28, refmach, alpha, rey, time, gaminf, beta, tinf, 28],&
                         9, MPI_INTEGER, MPI_STATUS_IGNORE, ierr)

      call MPI_File_write(fileh, [jd*kd*ld*nq*4], 1, MPI_INTEGER,  &
                         MPI_STATUS_IGNORE, ierr)
      call MPI_File_seek(fileh, offset+jd*kd*ld*nq*4, MPI_SEEK_CUR, ierr)
      call MPI_File_write(fileh, [jd*kd*ld*nq*4], 1, MPI_INTEGER,  &
                         MPI_STATUS_IGNORE, ierr)
  endif

  ! now everyone dumps their part of the array
  call MPI_File_set_view(fileh, offset, MPI_INTEGER, subarray,   &
                                'native', MPI_INFO_NULL, ierr)
  call MPI_File_write_all(fileh, q, jd*kd*ld*nlocq, MPI_INTEGER, &
                                MPI_STATUS_IGNORE, ierr)

  call MPI_File_close(fileh, ierr)

  CALL MPI_Finalize(ierr)

end program mpiwrite

在此程序中,进程0负责写入标头和记录字段。 首先写入三个标题记录,每个记录由记录长度(以字节为单位)结尾; 然后为大Q数组编写两个书挡。

然后,每个等级将文件视图设置为首先跳过标题,然后仅描述其在全局数组中的部分(此处仅用其等级号填充),然后写出其本地数据。 这些都是不重叠的数据。

因此,让我们尝试以下几种不同的尺寸:

$ mpif90 -o mpifwrite mpifwrite.f90
$ mpirun -np 1 ./mpifwrite

$ ./fread mpi.dat
 Ngrid =            2
 jd, kd, ld, nq, nqc =            3           3           3           3          -1
 q: min/mean/max =            0           0           0

$ od --format="d" mpi.dat
0000000           4           2           4          20
0000020           3           3           3           3
0000040          -1          20          28           1
0000060           2           3           4           5
0000100           6           7          28         324
0000120           0           0           0           0
*
0000740           0         324
0000750

$ mpirun -np 3 ./mpifwrite
$ ./fread mpi.dat
 Ngrid =            2
 jd, kd, ld, nq, nqc =            3           3           3           9          -1
 q: min/mean/max =            0           1           2

$ od --format="d" mpi.dat
0000000           4           2           4          20
0000020           3           3           3           9
0000040          -1          20          28           1
0000060           2           3           4           5
0000100           6           7          28         972
0000120           0           0           0           0
*
0000620           0           1           1           1
0000640           1           1           1           1
*
0001320           1           1           2           2
0001340           2           2           2           2
*
0002020           2           2           2           0
0002040           0           0           0           0
*
0002140           0           0           0         972
0002160

这是我们期望的输出。 将事物扩展为多种数据类型或多种网格相对简单。

1 如何读取在Fortran中使用MPI-IO编写的二进制数据?

我想从Fortran代码中读取一些输出数据到数据文件中以进行后处理。 给我的代码使用MPI写入那些数据文件。 对于最基本的情况,当处理器数应为1且Nx, Ny, Nz are all set to 1 and l is 3 ,写入数据文件的输出应全部为1。但是,输出写入数据文件的格式是某些不 ...

2 使用MPI-IO读取多个文件

我正在尝试使用C中的MPI-IO读取多个文件。我在跟踪以下示例: http : //users.abo.fi/Mats.Aspnas/PP2010/examples/MPI/readfile1.c 但是我在矩阵中读取而不是一串字符的双打。 这是该实现: 但是,当我在关闭第一个文件 ...

3 如何使用 MPI-IO 在单个格式化(可读)文件中使用 MPI 绘图

我在 fortran-90 框架中使用 MPI。 我想在一个文件中写入从不同处理器计算的所有数据。 我还想以可读格式而不是二进制格式写入数据。 此时,在我的程序中,每个处理器写入一个不同的文件。 因此,我有另一个后处理程序读取文件以创建单个文件。 在这里,具体问题: 1) 是否可以使用 MP ...

4 Fortran 流访问与 MPI-IO 的效率

我有一个并行的代码部分,我在块中写出 n 个大数组(代表一个数字网格),然后在不同大小的块中读取。 为此,我使用了 Stream 访问,因此每个处理器都独立地写入它们的块,但在本节中使用 2 个处理器组进行测试时,我看到了 0.5-4 秒的不一致时间。 我知道你可以用 MPI-IO 做类似的事情, ...

5 使用MPI-IO写入多个共享文件

我正在使用数千个MPI流程进行仿真,并且需要将输出数据写入一小组文件。 例如,即使我可能有10,000个进程,我也只想写出10个文件,每个文件要写1000个文件(以适当的偏移量)。 AFAIK正确的方法是为将要写入相同文件的进程组创建一个新的通信器,使用MPI_File_open()打开该通 ...

6 使用MPI-IO读取文本文件?

我有一个文本文件,其中包含带有矩阵尺寸的标题,然后是矩阵。 这是一个3x3矩阵的示例: 我一直使用MPI-IO获取垃圾值,发现它仅适用于二进制文件,而不适用于文本文件。 我以为我会读一个字符流并将其转换为整数,但是由于矩阵元素的位数是可变的,所以我不确定如何解决此问题。 我真的 ...

9 MPI-IO以非连续模式写入文件

我在编写将以特定模式编写的并行MPI I / O程序时遇到了麻烦。 我能够让进程0写整数0-9,进程1写整数10-19,进程2写整数20-29,依此类推。 这是完成此任务的代码: int main(int argc, char *argv[]) { // MPI_Finali ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM