Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.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共享内存通信_Fortran_Mpi_Intel Fortran - Fatal编程技术网

Fortran 带滑动访问的MPI共享内存通信

Fortran 带滑动访问的MPI共享内存通信,fortran,mpi,intel-fortran,Fortran,Mpi,Intel Fortran,关于使用mpi共享内存通信,我有两个问题 1) 如果我有一个MPI列组,它是唯一一个写入窗口的列组,那么是否有必要使用MPI_win_lock和MPI_win_unlock? 我知道我的应用程序永远不会有其他人试图写入该窗口。他们只读取窗口的内容,我确保他们在MPI_屏障后读取,因此窗口的内容已更新 2) 在我的应用程序中,我有一个MPI列组,它分配一个共享窗口,该窗口需要由1:N个其他MPI列组读取 MPI等级1应仅为:rma(1:10) MPI等级2只能读取rma(11:20) MPI等级N

关于使用mpi共享内存通信,我有两个问题

1) 如果我有一个MPI列组,它是唯一一个写入窗口的列组,那么是否有必要使用MPI_win_lock和MPI_win_unlock? 我知道我的应用程序永远不会有其他人试图写入该窗口。他们只读取窗口的内容,我确保他们在MPI_屏障后读取,因此窗口的内容已更新

2) 在我的应用程序中,我有一个MPI列组,它分配一个共享窗口,该窗口需要由1:N个其他MPI列组读取

MPI等级1应仅为:rma(1:10)

MPI等级2只能读取rma(11:20)

MPI等级N只能读取rma(10*(N-1)+1:10*N)

目前,所有1到N个列组都在查询整个共享窗口,即大小为“10*N”的MPI\u WIN\u shared\u查询

我在问是否可以应用MPI_WIN_SHARED_查询功能,以便MPI排名1只能从1:10访问窗口,排名2只能从11:20访问窗口,等等

这样,每个列组都有一个1:10的本地访问,但它们引用的是共享窗口的不同块?这可能吗

非常感谢

更新

根据下面的答案,似乎做了我想要的。但在使用MPI\u WIN\u SHARED\u查询时,它不起作用


但是,我不明白本地指针是如何自动指向数组的不同部分的。它怎么知道怎么做。您正在做的唯一一件事就是执行大小为nlocal=5的
c\u f\u指针
调用。它如何知道,例如,等级3的rma必须从16-20开始访问5个位置。我真的不清楚,我担心它是否是可移植的,即我可以依赖它吗?

首先,我建议使用MPI_Win_fence进行同步,而不是使用MPI_屏障-这确保了时间同步,就像屏障一样,但也确保了窗口上的所有操作都是可见的(例如,写入应该刷新到内存中)

如果您使用MPI\u Win\u allocate\u shared(),那么您将自动实现您想要的功能—每个列组都会获得一个指向其本地部分的指针。但是,内存是连续的,因此您可以通过对数组元素进行上/下索引来访问所有内存(您可以使用普通的Fortran指针指向纯粹由秩0分配的数组的一个子部分,但我认为MPI_Win_allocate_shared()更优雅)

下面是一些说明这一点的代码-创建一个共享数组,由秩0初始化,但由所有秩读取

这在我的笔记本电脑上似乎可以正常工作:

me@laptop:~$ mpirun -n 4 ./rmatest
 Running on            4  processes with n =           20
 Rank            2  in COMM_WORLD is rank            2  in nodecomm on node laptop
 Rank            3  in COMM_WORLD is rank            3  in nodecomm on node laptop
 Rank            0  in COMM_WORLD is rank            0  in nodecomm on node laptop
 Rank            1  in COMM_WORLD is rank            1  in nodecomm on node laptop
 rank, noderank, arr:            0           0           1           2           3           4           5
 rank, noderank, arr:            3           3          16          17          18          19          20
 rank, noderank, arr:            2           2          11          12          13          14          15
 rank, noderank, arr:            1           1           6           7           8           9          10
虽然一般来说,这只适用于同一共享内存节点中的所有列组

program rmatest

  use iso_c_binding, only: c_ptr, c_f_pointer

  use mpi

  implicit none

! Set the size of the road

  integer, parameter :: nlocal = 5
  integer :: i, n
  integer, dimension(MPI_STATUS_SIZE) :: status

  integer, pointer, dimension(:) :: rma

  integer :: comm, nodecomm, nodewin
  integer :: ierr, size, rank, nodesize, noderank, nodestringlen
  integer(MPI_ADDRESS_KIND) :: winsize
  integer :: intsize, disp_unit
  character*(MPI_MAX_PROCESSOR_NAME) :: nodename
  type(c_ptr) :: baseptr

  comm = MPI_COMM_WORLD

  call MPI_Init(ierr)

  call MPI_Comm_size(comm, size, ierr)
  call MPI_Comm_rank(comm, rank, ierr)

  ! Create node-local communicator

  call MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, &
                           MPI_INFO_NULL, nodecomm, ierr)

  ! Check it all went as expected

  call MPI_Get_processor_name(nodename, nodestringlen, ierr)
  call MPI_Comm_size(nodecomm, nodesize, ierr)
  call MPI_Comm_rank(nodecomm, noderank, ierr)

  n = nlocal*nodesize

  if (rank == 0) then

     write(*,*) "Running on ", size, " processes with n = ", n

  end if

  write(*,*) "Rank ", rank," in COMM_WORLD is rank ", noderank, &
             " in nodecomm on node ", nodename(1:nodestringlen)

  call MPI_Type_size(MPI_INTEGER, intsize, ierr)

  winsize = nlocal*intsize

  ! displacements counted in units of integers

  disp_unit = intsize

  call MPI_Win_allocate_shared(winsize, disp_unit, &
       MPI_INFO_NULL, nodecomm, baseptr, nodewin, ierr)

  ! coerce baseptr to a Fortran array: global on rank 0, local on others

  if (noderank == 0) then

     call c_f_pointer(baseptr, rma, [n])

  else

     call c_f_pointer(baseptr, rma, [nlocal])

  end if

  ! Set the local arrays

  rma(1:nlocal) = 0

  ! Set values on noderank 0

  call MPI_Win_fence(0, nodewin, ierr)

  if (rank == 0) then
     do i = 1, n
        rma(i) = i
     end do
  end if

  call MPI_Win_fence(0, nodewin, ierr)

  ! Print the values  

  write(*,*) "rank, noderank, arr: ", rank, noderank, (rma(i), i=1,nlocal)

  call MPI_Finalize(ierr)

end program rmatest

谢谢你的回答,大卫。我不确定我是否完全理解这一点。假设等级3只允许从rma(21:25)访问等级0,这在这里有效吗?此外,“0”在mpi_win_围栏中意味着什么?我的第一个问题与之相关:除了0之外,每个级别都有一个本地大小的rma指针。但我如何知道,例如秩1,它有一个指向窗口非局部大小的指针rma,在哪里?i、 e.我如何知道例如秩1 rma是指向窗口的1:5还是窗口的2:6等。我的想法是,例如,我希望我的秩1仅指向窗口的1:5,以及下一个5的秩2,即6:10等。在你的示例中,您确实会相应地调整这些列组的指针大小,但我如何知道它们是否指向全局窗口的每个部分?我的问题对您有意义吗?对于延迟响应,我深表歉意。MPI_Win_fence可以使用各种“断言”来提供更多信息,但为了简单起见,我这里不提供值为0的信息。按照编写代码的方式,每个列组分配一个大小为“nlocal”的数组。然而,我称之为MPI_Win_allocate_shared的方式保证了这些数据在内存中全局排列,即秩2的数据紧跟在秩1的数据之后。副作用是,如果访问秩2上的数组(0),则这与秩1上的数组(nlocal)相同,但在Fortran中必须小心,因为这超出了数组边界。