Donzis&Aditya的一篇论文表明,有可能使用可能在模板上有延迟的有限差分方案.这是什么意思?FD方案可能用于解决热方程和读取(或简化它)
u[t+1,i] = u[t,i] + c (u[t,i-1]-u[t,i+1])
Run Code Online (Sandbox Code Playgroud)
意思是,下一个时间步的值取决于同一位置的值及其前一时间步的邻居.
通过将(在我们的示例中为1D)域分割到不同的处理器上,可以容易地将该问题平行化.但是,在计算处理器的边界节点时我们需要通信,因为该元素u[t,i+-1]仅在另一个处理器上可用.
问题在下图中说明,该图取自引用的论文.

MPI实现可能使用MPI_Send和MPI_Recv进行同步计算.由于计算本身相当容易,因此通信可能成为可能的瓶颈.
该论文给出了该问题的解决方案:
尽管它可能是较早时间步长的值,但只需获取可用的边界音符而不是同步过程.然后该方法仍然收敛(在某些假设下)
对于我的工作,我想实现异步MPI案例(这不是本文的一部分).同步部件使用MPI_Send并且MPI_Recv工作正常.我将内存扩展了两个元素作为相邻元素的ghost单元格,并通过发送和接收发送所需的值.下面的代码基本上是上图的实现,并且在计算之前的每个时间步骤期间执行.
MPI_Send(&u[NpP],1,MPI_DOUBLE,RIGHT,rank,MPI_COMM_WORLD);
MPI_Recv(&u[0],1,MPI_DOUBLE,LEFT,LEFT,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
MPI_Send(&u[1],1,MPI_DOUBLE,LEFT,rank,MPI_COMM_WORLD);
MPI_Recv(&u[NpP+1],1,MPI_DOUBLE,RIGHT,RIGHT,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
Run Code Online (Sandbox Code Playgroud)
现在,我绝不是MPI专家.我想,这MPI_Put可能是我需要的异步情况和阅读一点,我想出了以下实现.
在时间循环之前:
MPI_Win win;
double *boundary;
MPI_Alloc_mem(sizeof(double) * 2, MPI_INFO_NULL, &boundary);
MPI_Info info;
MPI_Info_create(&info);
MPI_Info_set(info,"no_locks","true");
MPI_Win_create(boundary, 2*sizeof(double), sizeof(double), info, MPI_COMM_WORLD, &win);
Run Code Online (Sandbox Code Playgroud)
在时间循环内:
MPI_Put(&u[1],1,MPI_DOUBLE,LEFT,1,1,MPI_DOUBLE,win);
MPI_Put(&u[NpP],1,MPI_DOUBLE,RIGHT,0,1,MPI_DOUBLE,win);
MPI_Win_fence(0,win);
u[0] = boundary[0];
u[NpP+1] = boundary[1];
Run Code Online (Sandbox Code Playgroud)
它将所需的元素放在窗口中,即boundary(具有两个元素的数组)在相邻的处理器上u[0]并u[NpP+1]从boundary数组本身获取值.这个实现工作正常,我得到了相同的结果MPI_Send/Recv.但是,由于我还在使用MPI_Win_fence,这并不是真正的异步,据我所知,这确保了同步.
问题是:如果我取出MPI_Win_fence里面的值boundary永远不会更新并保持初始值.我的理解是,如果没有MPI_Win_fence …
我在使用基本通信和组MPI2方法方面有相当多的经验,并且使用MPI进行了相当多的令人尴尬的并行仿真工作.到目前为止,我已经构建了我的代码,以便有一个调度节点和一堆工作节点.调度节点具有将与模拟器一起运行的参数文件列表.它使用参数文件为每个工作节点播种.工作节点运行其模拟,然后请求调度节点提供的另一个参数文件.运行所有参数文件后,调度节点会在关闭自身之前关闭每个工作节点.
参数文件通常命名为"Par_N.txt",其中N是标识整数(例如,-N = 1-1000).所以我在想,如果我可以创建一个计数器,并且可以在所有节点上同步这个计数器,我就可以省去调度节点,并使系统更简单一些.理论上这听起来很简单,在实践中我怀疑它有点困难,因为我需要确保计数器在被改变时被锁定等等.并且认为可能存在MPI的内置方式处理这个(事情.有什么想法吗?我在想这个吗?
只要包含MPI_GET调用,以下简短的Fortran90程序就会崩溃.等级1尝试从等级0读取值并在MPI_WIN_UNLOCK中挂起.排名0尝试在MPI_BARRIER中发生崩溃并出现分段错误.
我反复检查命令的语法,但它们似乎是正确的.C/C++中的类似代码在同一系统上运行.
我正在使用OpenMPI 1.4.3和gfortran 4.4.5.
PROGRAM mpitest
USE mpi
IMPLICIT NONE
INTEGER :: ierr, npe, rnk, win
INTEGER (KIND=MPI_ADDRESS_KIND) lowerbound, sizeofreal
REAL :: val = 1.0, oval = 2.0
CALL MPI_INIT( ierr )
CALL MPI_COMM_RANK( MPI_COMM_WORLD, rnk, ierr )
CALL MPI_COMM_SIZE( MPI_COMM_WORLD, npe, ierr )
CALL MPI_TYPE_GET_EXTENT(MPI_REAL, lowerbound, sizeofreal, ierr)
CALL MPI_WIN_CREATE(val, sizeofreal, sizeofreal, MPI_INFO_NULL, MPI_COMM_WORLD, win, ierr)
IF( rnk .EQ. 1 ) THEN
CALL MPI_WIN_LOCK( MPI_LOCK_SHARED, 0, 0, win, ierr )
CALL MPI_GET( oval, 1, MPI_REAL, 0, 0, 1, …Run Code Online (Sandbox Code Playgroud) 我想在进程之间使用共享内存。我尝试了 MPI_Win_allocate_shared 但当我执行程序时它给了我一个奇怪的错误:
文件./src/mpid/ch3/include/mpid_rma_shm.h第 592 行断言失败:local_target_rank >= 0
internal ABORT
这是我的来源:
# include <stdlib.h>
# include <stdio.h>
# include <time.h>
# include "mpi.h"
int main ( int argc, char *argv[] );
void pt(int t[], int s);
int main ( int argc, char *argv[] )
{
int rank, size, shared_elem = 0, i;
MPI_Init ( &argc, &argv );
MPI_Comm_rank ( MPI_COMM_WORLD, &rank );
MPI_Comm_size ( MPI_COMM_WORLD, &size );
MPI_Win win;
int *shared;
if (rank == 0) shared_elem = …Run Code Online (Sandbox Code Playgroud)