gpt4 book ai didi

fortran - MPI-IO:写入子数组

转载 作者:行者123 更新时间:2023-12-02 15:13:35 26 4
gpt4 key购买 nike

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

这段代码的逻辑非常简单:每个线程将处理一个本地数组,该数组是我想要编写的全局数组的一部分。我使用 MPI_Type_Create_Subarray 创建一个子数组类型来执行此操作。然后我只需打开文件,设置 View 并尝试写入数据。我在 MPI_File_Write_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_FILE_WRITE_ALL 的最后一个参数错误输出参数之前是 MPI 状态对象,而不是 MPI 信息对象。使用 MPI_INFO_NULL 调用电话因此是错误的。如果您对写入操作的状态不感兴趣,那么您应该传递 MPI_STATUS_IGNORE反而。使用 MPI_INFO_NULL 调用电话由于这两个常量的定义方式的具体原因,可能在某些 MPI 实现中有效,但在其他实现中却失败。

例如,在 Open MPI MPI_INFO_NULL 中声明为:

parameter (MPI_INFO_NULL=0)

当通过而不是 MPI_STATUS_IGNORE 时它导致 MPI_File_write_all 的 C 实现使用指向常量(只读)内存位置的状态参数进行调用,该位置保存 MPI_INFO_NULL 的值(Fortran 如何实现按地址传递常量)。当C函数即将完成时,它会尝试填充状态对象,这会导致尝试写入常量内存,最终导致段错误。

<小时/>

在编写新的 Fortran 程序时,建议不要使用非常旧的 mpif.h接口(interface),因为它不提供任何错误检查。相反,应该使用 mpi模块甚至mpi_f08当更多 MPI 实现符合 MPI-3.0 时。因此,程序的开头应该如下所示:

program test
use mpi
implicit none
...
end program test

一旦您使用mpi模块而不是 mpif.h ,编译器能够对某些 MPI 调用执行参数类型检查,包括 MPI_FILE_SET_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_FILE_SET_VIEW 的第二个参数类型为INTEGER(KIND=MPI_OFFSET_KIND) ,在大多数现代平台上都是 64 位。常数0只是类型 INTEGER因此在大多数平台上都是 32 位的。发生的情况是 mpif.h编译器传递一个指向 INTEGER 的指针值为 0 的常量,但子例程将其解释为指向更大整数的指针,并将相邻值解释为常量值的一部分。因此,您作为文件内偏移量传递的零最终会成为非零值。

替换 0MPI_FILE_SET_VIEW调用 0_MPI_OFFSET_KIND或者声明 INTEGER(KIND=MPI_OFFSET_KIND) 类型的常量和零值,然后传递它。

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

integer(kind=MPI_OFFSET_KIND), parameter :: zero_off = 0
...
call MPI_File_Set_View(fhandle, zero_off, MPI_DOUBLE_PRECISION, ...

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

关于fortran - MPI-IO:写入子数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17926249/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com