MPI_FILE_WRITE_ORDERED覆盖先前写入的数据

时间:2019-08-07 10:36:23

标签: fortran mpi intel-fortran mpi-io

我有以下代码

program mpi_io

use mpi

implicit none

integer :: mpierr, whoami, nproc, iout, STATUS(MPI_STATUS_SIZE),charsize
integer(kind=mpi_offset_kind):: OFFSET, fs
character(len=60) :: dd,de
character:: newline = NEW_LINE('FORTRAN')


call MPI_INIT        ( mpierr )
call MPI_COMM_RANK   ( MPI_COMM_WORLD, whoami, mpierr )
call MPI_COMM_SIZE   ( MPI_COMM_WORLD, nproc, mpierr )


dd ='=========================' //  INT2STR(whoami)//newline
de = 'special'//  INT2STR(whoami)//newline
call MPI_FILE_OPEN(  MPI_COMM_WORLD, 'test.dat',  MPI_MODE_CREATE + MPI_MODE_WRONLY, MPI_INFO_NULL, IOUT, mpierr)
call mpi_type_size(mpi_byte, charsize , mpierr)


offset = charsize*len(TRIM(de))
if(whoami == 0)call MPI_FILE_WRITE_AT( iout,offset, TRIM(de), len(TRIM(de)), MPI_BYTE, status, mpierr)

call MPI_File_get_size(iout, fs, mpierr)
offset = fs
call MPI_FILE_SEEK(iout, fs, MPI_SEEK_SET, mpierr)
call MPI_FILE_WRITE_ordered( iout,  TRIM(dd), len(TRIM(dd)), MPI_BYTE, status, mpierr)

!call MPI_FILE_WRITE_ordered( iout,  dd, len(dd), MPI_CHARACTER, status, mpierr)

call mpi_file_close(iout,mpierr)

call mpi_finalize(mpierr)

contains

   function INT2STR( i ) result( str )

   integer, intent(in)       :: i
   character(:), allocatable :: str
   character(RANGE(i)+2)     :: tmp

   write(tmp, '(I0)') i
   str = TRIM(tmp)

   end function
end program

我要寻找的是仅由一个处理器(有时由所有处理器)写入文件的组合。如您在本示例中看到的那样,我首先只想按根排名写de,然后就按所有处理器写dd

现在写,我的de似乎已被覆盖

如您所见,我试图通过查询文件的大小并执行MPI_FILE_SEEK来抵消它,但这似乎无济于事 有人有想法吗?

我正在使用IFORT v19

1 个答案:

答案 0 :(得分:1)

要引用MPI 3.1标准的13.4.1节中的定位子节:“ MPI为数据访问例程提供三种定位类型:显式偏移量,单个文件指针和共享文件指针。不同的定位方法可能是混在同一个程序中,互不影响。”

您的问题是您正在混合使用所有三种不同的定位方法。 MPI_FILE_WRITE_AT使用显式偏移。同样,MPI_FILE_SEEK更改单个文件指针。 MPI_FILE_WRITE_ordered写入共享文件指针给定的当前位置。因此,由于“不同的定位方法可能混在同一个程序中并且互不影响”,因此MPI_FILE_WRITE_AT和MPI_FILE_SEEK所提供的任何内容都不会影响MPI_FILE_WRITE_ordered将数据放入文件中的任何方式。因此,在程序中对MPI_FILE_WRITE_ordered的首次调用将覆盖MPI_FILE_WRITE_AT写入的数据。

您想要的是在编写de时更新共享文件指针。此外,由于仅通过一个过程即可完成操作,因此您不需要集体例程。实现此目的的正确例程是MPI_FILE_WRITE_SHARED。这是我认为可以满足您需求的程序版本:

ijb@ianbushdesktop ~/work/stack $ cat mpiio.f90
program test_mpi_io

  use mpi

  implicit none

  integer :: mpierr, whoami, nproc, iout, STATUS(MPI_STATUS_SIZE),charsize
  character(len=60) :: dd,de
  character:: newline = NEW_LINE('FORTRAN')


  call MPI_INIT        ( mpierr )
  call MPI_COMM_RANK   ( MPI_COMM_WORLD, whoami, mpierr )
  call MPI_COMM_SIZE   ( MPI_COMM_WORLD, nproc, mpierr )


  dd ='=========================' //  INT2STR(whoami)//newline
  de = 'special'//  INT2STR(whoami)//newline
  call MPI_FILE_OPEN(  MPI_COMM_WORLD, 'test.dat',  MPI_MODE_CREATE + MPI_MODE_WRONLY, MPI_INFO_NULL, IOUT, mpierr)
  call mpi_type_size(mpi_byte, charsize , mpierr)


  if(whoami == 0)call MPI_FILE_WRITE_SHARED( iout,TRIM(de), len(TRIM(de)), MPI_BYTE, status, mpierr)

  call MPI_FILE_WRITE_ordered( iout,  TRIM(dd), len(TRIM(dd)), MPI_BYTE, status, mpierr)

  call mpi_file_close(iout,mpierr)

  call mpi_finalize(mpierr)

contains

  function INT2STR( i ) result( str )

    integer, intent(in)       :: i
    character(:), allocatable :: str
    character(RANGE(i)+2)     :: tmp

    write(tmp, '(I0)') i
    str = TRIM(tmp)

  end function INT2STR
end program test_mpi_io

ijb@ianbushdesktop ~/work/stack $ mpif90 -Wall -Wextra -std=f2003 -O mpiio.f90  -o test_mpi_io
ijb@ianbushdesktop ~/work/stack $ rm test.dat 
ijb@ianbushdesktop ~/work/stack $ mpirun -np 4 ./test_mpi_io 
ijb@ianbushdesktop ~/work/stack $ cat test.dat 
special0
=========================0
=========================1
=========================2
=========================3
ijb@ianbushdesktop ~/work/stack $ rm test.dat 
ijb@ianbushdesktop ~/work/stack $ mpirun -np 8 ./test_mpi_io 
ijb@ianbushdesktop ~/work/stack $ cat test.dat 
special0
=========================0
=========================1
=========================2
=========================3
=========================4
=========================5
=========================6
=========================7
ijb@ianbushdesktop ~/work/stack $ 

此外,当我在这里时,您应该避免在mpi程序中调用以mpi_开头的名称。这是因为该组合是mpi保留的,使用它可能会引起名称冲突。因此,我重命名了您的程序单元