【问题标题】:Writing to files with MPI使用 MPI 写入文件
【发布时间】:2011-05-20 09:22:23
【问题描述】:

我正在按如下方式写入文件。顺序不一定重要(尽管如果我能按 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 基本相同)同样有用

谢谢!

【问题讨论】:

  • k 这里是每个任务都有一个(或一些)的东西?每个人的 ATOM_COUNT 都一样吗?
  • 哦,等等——我没有注意到未格式化的写入。你是用 ASCII 做的吗?如果是,那么(a)你真的不应该(它很慢,会产生大文件,除非你真的把它打印出来并通过肉眼进行分析,为什么还要麻烦?),并且(b)你很可能任何类型的并行 IO 方法都不走运。有了你正在做的事情,由于输出数据很小,你最好将所有数据排列为 0 MPI_GATHER() 并将其写出来,而不是遍历障碍。
  • 它进入 gnuplot,所以必须像这样格式化(AFAIK)

标签: c fortran parallel-processing mpi


【解决方案1】:

所以确定正确的 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

【讨论】:

  • 感谢您的示例。我想我没有提到,这是在 K(0 到 1000)的循环中,并且 EIGENVALUES 可以有很多元素(500 是正常的),所以循环 EIGENVALUES 的每次迭代都会丢失 - 所以将它们发送回来是'可行。但是,在不同的处理器上保存到不同的文件是可能的,并且作为一个简单的解决方案现在可能会有所帮助:)
  • 我为每个进程创建了一个单独的文件,并将它们拼接在一起。我必须保留 gnuplot 的格式,所以使用 MPI 直接编写似乎很痛苦。这个现在很好用,谢谢
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多