使用MPI写入文件

时间:2010-12-05 00:27:02

标签: c fortran parallel-processing mpi

我正在写一个文件,如下所示。订单并不一定重要(尽管如果我可以通过K订购它会很好,就像在串行代码中本身一样)

            CALL MPI_BARRIER(MPI_COMM_WORLD, IERR)
            OPEN(EIGENVALUES_UP_IO, FILE=EIGENVALUES_UP_PATH, ACCESS='APPEND')
            WRITE(EIGENVALUES_UP_IO, *) K * 0.0001_DP * PI, (EIGENVALUES(J), J = 1, ATOM_COUNT)
            CLOSE(EIGENVALUES_UP_IO)

我知道这可能是最糟糕的选择。

我已经看过MPI_FILE_WRITE_AT等但是我不确定他们(直接)以我的形式获取数据?

文件格式必须与此格式相同,格式为每K行一行,ATOM_COUNT + 1列。值为REAL(8)

我一遍又一遍地追捕,找不到任何关于实现这一点的简单参考。有帮助吗? :)

C中的类似代码(假设它与FORTRAN基本相同)同样有用

谢谢!

2 个答案:

答案 0 :(得分:2)

因此,确定正确的IO策略取决于很多因素。如果你只是发回一些特征值,并且你写了ASCII,那么最好只将所有数据发送回进程0进行写入。这通常是一个成功的策略,因为它显然不会扩展;但是如果数据量非常小,那么它可能比尝试写出共享文件时所涉及的争用更好(这也是用ASCII更难的)。

如果每个人都拥有相同数量的数据,下面会有一些代码将数据量恢复到proc 0。

另一种方法就是让每个人都写出自己的ks和特征值,然后在程序完成后作为后处理步骤,将它们全部拼凑起来。这避免了MPI步骤,并且(使用正确的文件系统)可以扩展相当多的方式,并且很容易;是否更好是相当容易测试的,并且将取决于数据量,处理器数量和底层文件系统。

   program testio
    use mpi
    implicit none

    integer, parameter :: atom_count = 5
    integer, parameter :: kpertask   = 2
    integer, parameter :: fileunit   = 7
    integer, parameter :: io_master  = 0
    double precision, parameter :: pi = 3.14159

    integer :: totalk
    integer :: ierr
    integer :: rank, nprocs

    integer :: handle
    integer(kind=MPI_OFFSET_KIND) :: offset
    integer :: filetype

    integer :: j,k
    double precision, dimension(atom_count, kpertask) :: eigenvalues
    double precision, dimension(kpertask) :: ks

    double precision, allocatable, dimension(:,:):: alleigenvals
    double precision, allocatable, dimension(:)  :: allks

    call MPI_INIT(ierr)
    call MPI_COMM_SIZE(MPI_COMM_WORLD, nprocs, ierr)
    call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)

    totalk   = nprocs*kpertask

    !! setup test data

    do k=1,kpertask
        ks(k) = (rank*kpertask+k)*1.d-4*PI
        do j=1,atom_count
            eigenvalues(j,k) = rank*100+j
        enddo
    enddo

    !! Everyone sends proc 0 their data

    if (rank == 0) then
        allocate(allks(totalk))
        allocate(alleigenvals(atom_count, totalk))
    endif

    call MPI_GATHER(ks, kpertask, MPI_DOUBLE_PRECISION,    &
                    allks, kpertask, MPI_DOUBLE_PRECISION, &
                    io_master, MPI_COMM_WORLD, ierr)

    call MPI_GATHER(eigenvalues, kpertask*atom_count, MPI_DOUBLE_PRECISION,  &
                    alleigenvals, kpertask*atom_count, MPI_DOUBLE_PRECISION, &
                    io_master, MPI_COMM_WORLD, ierr)

    if (rank == 0) then 
        open(unit=fileunit, file='output.txt')
        do k=1,totalk
            WRITE(fileunit, *) allks(k), (alleigenvals(j,k), j = 1, atom_count)
        enddo
        close(unit=fileunit)

        deallocate(allks)
        deallocate(alleigenvals)
    endif
    call MPI_FINALIZE(ierr)
end program testio

答案 1 :(得分:0)

如果您可以确定每个等级的写入时间,您可以调用MPI_SCAN(size, offset, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD)来计算每个等级应该从哪个开始的偏移,然后他们都可以调用MPI_FILE_WRITE_AT。如果您有大量数据,这可能更合适,并且您确信您的MPI实现有效地进行了写入(不在内部进行序列化等)。