每个进程写入FORTRAN无格式文件

时间:2015-06-11 20:23:55

标签: fortran mpi binaryfiles

在我的并行程序中,有一个很大的矩阵。每个过程都计算并存储了它的一部分。然后,程序通过让每个进程以正确的顺序编写自己的矩阵部分,将矩阵写入文件。输出文件采用“未格式化”的形式。但是当我尝试用串行代码读取文件时(我分配了大矩阵的正确大小),我得到了一个我不理解的错误。

我的问题是:在MPI程序中,如何将二进制文件作为由不同进程存储的大矩阵的串行版本输出?

这是我的尝试:

    if(ThisProcs == RootProcs) then
        open(unit = file_restart%unit, file = file_restart%file, form = 'unformatted')
        write(file_restart%unit)psi
        close(file_restart%unit)
    endif
#ifdef USEMPI
    call mpi_barrier(mpi_comm_world,MPIerr)
#endif
    do i = 1, NProcs - 1
        if(ThisProcs == i) then
            open(unit = file_restart%unit, file = file_restart%file, form = 'unformatted', status = 'old', position = 'append')
            write(file_restart%unit)psi
            close(file_restart%unit)
        endif
#ifdef USEMPI
        call mpi_barrier(mpi_comm_world,MPIerr)
#endif
    enddo

Psi是大矩阵,它被分配为:

Psi(N_lattice_points, NPsiStart:NPsiEnd)

但是当我尝试用串行代码加载文件时:

open(2,file=File1,form="unformatted")
read(2)psi

forrtl:严重(67):输入声明需要太多数据,单元2(我使用的是MSVS 2012 + intel fortran 2013)

如何修复并行部分以使二进制文件对串行代码可读?当然可以将它们组合成MPI程序中的一个大矩阵,但有更简单的方法吗?

修改1

这两个答案真的很棒。我将使用access =“stream”来解决我的问题。我只是想我可以使用查询来检查文件是“顺序”还是“流”。

3 个答案:

答案 0 :(得分:4)

这不是MPI特有的问题,但也会发生在串行程序中,它采用相同的方法逐个写出块。

忽略每个进程的打开和关闭,并查看整个连接和转移语句。您的连接是使用顺序访问的无格式文件。它没有格式化,因为你明确地要求它,并且顺序因为你没有要求任何其他东西。

顺序文件访问基于记录。每个写入语句都会传出一个由矩阵块组成的记录。相反,您的输入语句会尝试从单个记录中读取。

您的问题是,当您尝试从文件的第一个记录中读取整个矩阵时,该记录不包含整个矩阵。它不包含任何类似正确数据量的内容。最终结果:“输入语句需要太多数据”。

因此,您需要根据相同的记录结构读取数据,或者远离记录文件。

后者很简单,使用流访问

open(unit = file_restart%unit, file = file_restart%file,  &
     form = 'unformatted', access='stream')

或者,使用类似的循环结构读取:

do i=1, NPROCS
  ! read statement with a slice
end do

这当然需要了解正确的切片。

或者,可以考虑使用MPI-IO进行输出,这与使用流输出非常相似。通过流访问重新阅读此内容。你可以在SO的其他地方找到这个概念。

答案 1 :(得分:3)

Fortran未记录的记录文件中的顺序写入并不完全是原始数据。每个写入将以处理器相关的形式在记录之前和之后具有数据。读取的大小不能超过写入的记录大小。这意味着如果psi写入两次写入,则需要在两次读取时将其读回,不能一次读取。

也许最直接的选择是使用stream访问而不是sequential。流文件按字节(通常)索引,不包含记录开始和结束信息。使用此访问方法,您可以拆分写入,但一次读取所有内容。流访问是Fortran 2003的一项功能。

如果你坚持使用顺序访问,你需要知道有多少MPI等级写入文件并循环到正确大小的记录,以便在写入时读取数据。您可以让用户指定排名数或将其存储为文件中的第一个记录,并首先读取该数据以确定如何读取其余数据。

答案 2 :(得分:1)

如果您正在编写MPI,为什么不使用MPI-IO?每个进程都将调用MPI_File_set_view来设置文件的子数组视图,然后每个进程可以使用MPI_FILE_WRITE_ALL共同写入数据。这种方法很可能在大型机器上很好地扩展(尽管你的方法可以达到哦,可能是100个处理器。)