Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran MPI-IO:写入子阵列_Fortran_Mpi_Mpi Io - Fatal编程技术网

Fortran MPI-IO:写入子阵列

Fortran MPI-IO:写入子阵列,fortran,mpi,mpi-io,Fortran,Mpi,Mpi Io,我开始使用MPI-IO,并尝试编写一个非常简单的示例,说明我想用它做的事情;然而,尽管这是一个简单的代码,并且我从这里和那里阅读的示例中获得了一些灵感,但我还是发现了一个我不理解的分段错误 这段代码的逻辑非常简单:每个线程将处理一个本地数组,它是我要编写的globlal数组的一部分。我使用MPI\u type\u create\u subarray来创建子数组类型。然后我打开文件,设置一个视图并尝试写入数据。我在MPI\u文件\u Write\u All期间遇到分段错误 代码如下: progra

我开始使用MPI-IO,并尝试编写一个非常简单的示例,说明我想用它做的事情;然而,尽管这是一个简单的代码,并且我从这里和那里阅读的示例中获得了一些灵感,但我还是发现了一个我不理解的分段错误

这段代码的逻辑非常简单:每个线程将处理一个本地数组,它是我要编写的globlal数组的一部分。我使用
MPI\u type\u create\u subarray
来创建子数组类型。然后我打开文件,设置一个视图并尝试写入数据。我在
MPI\u文件\u Write\u All
期间遇到分段错误

代码如下:

program test
  implicit none

  include "mpif.h"

  integer :: myrank, nproc, fhandle, ierr
  integer :: xpos, ypos
  integer, parameter :: loc_x=10, loc_y=10
  integer :: loc_dim
  integer :: nx=2, ny=2
  real(8), dimension(loc_x, loc_y) :: data
  integer :: written_arr
  integer, dimension(2) :: wa_size, wa_subsize, wa_start

  call MPI_Init(ierr)
  call MPI_Comm_Rank(MPI_COMM_WORLD, myrank, ierr)
  call MPI_Comm_Size(MPI_COMM_WORLD, nproc, ierr)

  xpos = mod(myrank, nx)
  ypos = mod(myrank/nx, ny)

  data = myrank

  loc_dim    = loc_x*loc_y
  wa_size    = (/ nx*loc_x, ny*loc_y /)
  wa_subsize = (/ loc_x, loc_y /)
  wa_start   = (/ xpos, ypos /)*wa_subsize
  call MPI_Type_Create_Subarray(2, wa_size, wa_subsize, wa_start &
       , MPI_ORDER_FORTRAN, MPI_DOUBLE_PRECISION, written_arr, ierr)
  call MPI_Type_Commit(written_arr, ierr)

  call MPI_File_Open(MPI_COMM_WORLD, "file.dat" &
       & , MPI_MODE_WRONLY + MPI_MODE_CREATE, MPI_INFO_NULL, fhandle, ierr)
  call MPI_File_Set_View(fhandle, 0, MPI_DOUBLE_PRECISION, written_arr &
       , "native", MPI_INFO_NULL, ierr)
  call MPI_File_Write_All(fhandle, data, loc_dim, MPI_DOUBLE_PRECISION &
       , MPI_INFO_NULL, ierr)
  call MPI_File_Close(fhandle, ierr)

  call MPI_Finalize(ierr)

end program test

任何帮助都将不胜感激

错误输出参数之前的
MPI\u FILE\u WRITE\u ALL
的最后一个参数是MPI状态对象,而不是MPI信息对象。因此,使用
MPI\u INFO\u NULL
进行调用是错误的。如果您对写入操作的状态不感兴趣,则应通过
MPI\u status\u IGNORE
。使用
MPI\u INFO\u NULL
进行调用可能在某些MPI实现中有效,因为这两个常量的定义方式都很具体,但在其他MPI实现中可能会失败

例如,在Open MPI
MPI\u INFO\u NULL
中声明为:

parameter (MPI_INFO_NULL=0)
当传递而不是
MPI\u STATUS\u IGNORE
时,会导致调用
MPI\u File\u write\u all
的C实现,其状态参数指向一个常量(只读)内存位置,该位置保存
MPI\u INFO\u NULL
(Fortran如何实现按地址传递常量)。当C函数即将完成时,它尝试填充status对象,这导致尝试写入常量内存,最终导致分段错误


在编写新的Fortran程序时,建议不要使用非常旧的
mpif.h
接口,因为它不提供任何错误检查。相反,当更多的mpi实现与mpi-3.0兼容时,应该使用
mpi
模块甚至
mpi\u f08
。因此,您的计划的开始应该如下所示:

program test
   use mpi
   implicit none
   ...
end program test
使用
mpi
模块而不是
mpif.h
后,编译器可以对某些mpi调用执行参数类型检查,包括
mpi\u FILE\u SET\u VIEW
,并发现错误:

test.f90(34): error #6285: There is no matching specific subroutine for this generic subroutine call.   [MPI_FILE_SET_VIEW]
  call MPI_File_Set_View(fhandle, 0, MPI_DOUBLE_PRECISION, written_arr &
-------^
compilation aborted for test.f90 (code 1)
原因是
MPI\u FILE\u SET\u VIEW
的第二个参数类型为
INTEGER(KIND=MPI\u OFFSET\u KIND)
,在大多数现代平台上为64位。常量
0
仅为
INTEGER
类型,因此在大多数平台上为32位。发生的情况是,使用
mpif.h
编译器传递一个指向值为
0
整数
常量的指针,但子例程将其解释为指向更大整数的指针,并将相邻值解释为常量值的一部分。因此,作为文件内部偏移量传递的零最终成为非零值

0\u MPI\u OFFSET\u KIND
替换
MPI\u FILE\u SET\u视图中的
0
,或者声明一个类型为
INTEGER(KIND=MPI\u OFFSET\u KIND)
的常量和一个值为零,然后传递它

call MPI_File_Set_View(fhandle, 0_MPI_OFFSET_KIND, MPI_DOUBLE_PRECISION, ...


这两种方法都会产生大小为3200字节的输出文件(如预期)。

谢谢您的回答!然而,我仍然遇到一个严重的问题:编写的文件太大了,我现在还不知道为什么。如果你知道它为什么会这样…你找到输出文件如此巨大的原因了吗?除了被误用的
MPI\u INFO\u NULL
,我在你的代码中找不到其他错误。不,这对我来说仍然是个奇迹。我想我会专门针对这个问题创建一个新问题,因为如果我使用
MPI\u File\u Seek
而不是
MPI\u File\u Set\u View
,它似乎可以正常工作。我想我已经解决了您的问题-请参阅更新的答案。太好了,谢谢!它解决了我的问题。不幸的是,我不能对你的答案投两次赞成票,否则我会投的。
integer(kind=MPI_OFFSET_KIND), parameter :: zero_off = 0
...
call MPI_File_Set_View(fhandle, zero_off, MPI_DOUBLE_PRECISION, ...