问题描述
假设我有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接口,是因为:
- 性能? (请参见下面)
- 是否与Fortran兼容?
- 还有什么?
- 这些原因也适用于
MPI_Neighbor_alltoall_v
吗?
我是唯一一个受此困扰的人吗?“将其复制到级联数组中,然后MPI仍将其拆分,然后您将收到另一个级联数组,可能必须立即再次拆分”?
=====================================
性能:经过一些研究
-
参考手册的“实施者建议”说:“ 实现可能使用树通信模式。消息可以由中间节点转发,这些中间节点在其中拆分(分散)或串联(收集)” ,如果这样更有效”。这可能就是为什么选择此接口的原因。另一方面,我认为只有由于
sdispls
,数组才是连续的,并且在这里是不可靠的,才有可能。 -
This article提到了alltoall算法的3种主要可能实现。其中只有两个只是天真的“全部发送/全部接收”算法的改进。因此,实际上不需要为这两个请求连续数据。只有第三个方法,即“布鲁克算法”,使用分治法(据我所知,它需要连续的数据)。根据proc的数量和消息的大小,这3个程序的执行情况有所不同。
-
查看一些开源实现:
- MVAPICH实现了3种方法
- MPICH仅实现前两个(据我了解)
- 我不明白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 (将#修改为@)