为什么MPI_Alltoallv函数接口强制数据仅属于一个数组?

问题描述

假设我有3个进程,每个进程都想发送3个数组a0,a1,a2到进程0,1和2。 给定MPI_Alltoallv接口,即

int MPI_Alltoallv(const void *sendbuf,const int *sendcounts,const int *sdispls,MPI_Datatype sendtype,void *recvbuf,const int *recvcounts,const int *rdispls,MPI_Datatype recvtype,MPI_Comm comm)

该接口强制将a0,a2内容连接到sendbuf数组中(可能以非连续方式)。但这对于实现MPI_Alltoallv真的必要吗?我认为sendbuf最终将不得不重新拆分为a0,a2,因为最后,接收过程是不同的。 (recvbuf也是如此)

为什么界面不如下:

int MPI_Alltoallv(const void **sendbuf,void **recvbuf,MPI_Comm comm)

我要去的地方,例如int* sendbuf[3] = {a0,a2}? (与接收数组相同)

之所以使用MPI接口,是因为:

  1. 性能? (请参见下面)
  2. 是否与Fortran兼容?
  3. 还有什么?
  4. 这些原因也适用于MPI_Neighbor_alltoall_v吗?

我是唯一一个受此困扰的人吗?“将其复制到级联数组中,然后MPI仍将其拆分,然后您将收到另一个级联数组,可能必须立即再次拆分”?

=====================================

性能:经过一些研究

  1. 参考手册的“实施者建议”说:“ 实现可能使用树通信模式。消息可以由中间节点转发,这些中间节点在其中拆分(分散)或串联(收集)” ,如果这样更有效”。这可能就是为什么选择此接口的原因。另一方面,我认为只有由于sdispls,数组才是连续的,并且在这里是不可靠的,才有可能。

  2. This article提到了alltoall算法的3种主要可能实现。其中只有两个只是天真的“全部发送/全部接收”算法的改进。因此,实际上不需要为这两个请求连续数据。只有第三个方法,即“布鲁克算法”,使用分治法(据我所知,它需要连续的数据)。根据proc的数量和消息的大小,这3个程序的执行情况有所不同。

  3. 查看一些开源实现:

    1. MVAPICH实现了3种方法
    2. MPICH仅实现前两个(据我了解)
    3. 我不明白OpenMPI实现在做什么^^'

    但是似乎所有这些算法都有启发式方法,以便在算法之间进行选择,因此出于性能原因,“一个数组中的所有数据”接口不是必需的。

=====================================

旁注:非连续接口的临时实现,作为MPI_alltoallv的包装(基于@Gilles Gouaillardet的评论):

int my_Alltoallv(const void **sendbuf,const int *scounts,MPI_Datatype stype,const int *rcounts,MPI_Datatype rtype,MPI_Comm comm) {
  int n_rank;
  MPI_Comm_size(comm,&n_rank);
  int* sdispls = (*)malloc(n_rank*sizeof(int);
  int* rdispls = (*)malloc(n_rank*sizeof(int);
  for (int i=0; i<n_rank; ++i) {
    MPI_Aint sdispls_i;
    MPI_Aint rdispls_i;
    MPI_Get_address(sendbuf[i],&sdispls_i);
    MPI_Get_address(recvbuf[i],&rdispls_i);
    sdispls[i] = sdispls_i; // Warning: narrowing from MPI_Aint to int
    rdispls[i] = rdispls_i; // Warning: narrowing from MPI_Aint to int
  }
  return MPI_Alltoallv(MPI_BottOM,scounts,sdispls,stype,// is MPI_BottOM+sdispls[i] == sendbuf[i] regarding C and MPI ?
                       MPI_BottOM,rcounts,rdispls,rtype,// is MPI_BottOM+rdispls[i] == recvbuf[i] regarding C and MPI ?
                       comm);
}

我认为至少从MPI_Aint缩小到int会导致错误。另外,我不确定MPI_BottOM的作用是什么(因为我认为C仅允许在同一数组中使用指针算术[否则这是未定义的行为],在这里,没有理由{{1 }}和a [i]属于同一数组[除非MPI要求可以将每个进程的内存视为从MPI_BottOM开始的大数组,否则除外])。但我想确认一下。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)