Fortran MPI代码中的标准输出

5

我有一段并行的Fortran代码,我只希望rank=0的进程可以写入stdout,但我不想在代码中到处添加:

if(rank==0) write(*,*) ...

我在想像以下这样做是否是个好主意,或者是否有更好的方法?

program test

  use mpi

  implicit none

  integer :: ierr
  integer :: nproc
  integer :: rank

  integer :: stdout

  call mpi_init(ierr)
  call mpi_comm_rank(mpi_comm_world, rank, ierr)
  call mpi_comm_size(mpi_comm_world, nproc, ierr)

  select case(rank)
  case(0)
     stdout = 6
  case default
     stdout = 7
     open(unit=stdout, file='/dev/null')
  end select

  write(stdout,*) "Hello from rank=", rank

  call mpi_finalize(ierr)

end program test

这将得到:
$ mpirun -n 10 ./a.out
Hello from rank=           0

感谢任何建议!
3个回答

12
你的解决方案有两个缺点:
  1. 这种“巧妙”的解决方案实际上混淆了代码,因为它说谎了:stdout不再是stdout了。如果有人阅读代码,他/她会认为所有进程都在写入stdout,而实际上并非如此。
  2. 如果你想让所有进程在某个时刻写入stdout,那么你该怎么做呢?再添加更多的技巧吗?

如果你真的想坚持使用这个技巧,请不要将"stdout"作为单元编号的变量名,而应该使用类似于"master"或其他指示你实际上没有写入stdout的名称。此外,您应该意识到数字6并不总是stdout。Fortran 2003允许您检查stdout的单元编号,因此如果可以,建议使用该方法。

我的建议是使用if(rank==0)语句。它们清楚地表明了代码中发生了什么。如果你使用了很多类似的I/O语句,你可以编写子程序仅用于rank 0或所有进程的写入。这些子程序可以有意义的名称,表示预期的用途。


2

mpirun带有选项可以将每个进程的标准输出重定向到单独的文件中。例如,-output-filename out 会生成 out.1.0、out.1.1 等文件,您可以使用任何方式监视这些文件(我使用tail -f)。除了if(rank.eq.0)之外,我认为这是最干净的解决方案。


0

我并不太担心 steabert 提到的两个缺点。我们可以通过引入另一个文件描述符来解决这个问题,该文件描述符清楚地指示它仅在主进程上为 stdout,例如 stdout ->stdout0

但是我的担忧在于:/dev/null 只适用于类 UNIX 的环境。它是否适用于 Windows 环境?那么关于时髦的 BlueGene 系统呢?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接