我正在写一个文件,如下所示。订单并不一定重要(尽管如果我可以通过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基本相同)同样有用
谢谢!
答案 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实现有效地进行了写入(不在内部进行序列化等)。