mpi 相互发送和接收所有进程

mpi send and recv all processes to one another

我正在尝试在每个进程上都有一个数组的所有进程之间发送数据,例如

int local_data[] = {0*rank,1*rank,2*rank,3*rank};

我有一个相应的标志数组,其中该数组中的每个值都指向我应该发送该值的进程,例如:

int part[] = {0,1,3,2};

所以这意味着 local_data[0] 应该以等级 0 进行处理 local_data[2] 应该以等级 3 进行处理,依此类推。 标志 arr 中的值从一个进程更改为另一个进程(都在 0-P-1 范围内,其中 P 是可用进程的总数)。

使用这个,我目前正在做的是:

for(int i=0; i<local_len; i++){
        if(part[i] != rank){
            MPI_Send(&local_data[i], 1,MPI_INT, part[i], 0, MPI_COMM_WORLD);
            MPI_Recv(&temp,1, MPI_INT, rank, 0, MPI_COMM_WORLD, &status );
            recvbuf[j] = temp;
            j++;
        }
        else{
            recvbuf[j] = local_data[i];
            j++;
        }
    }

如果part[i] != rank,我只发送和接收数据,以避免从同一个进程发送和接收

recvbuf 是我接收每个进程的值的数组。它可以比初始 local_data 长度更长。

我也试过了

MPI_Sendrecv(&local_data[i], 1,MPI_INT, part[i], 0, &temp, 1, MPI_INT, rank, 0, MPI_COMM_WORLD, &status);

程序在两种情况下都卡住了

我该如何解决这个问题?

All-to-All 集体是正确的选择吗?

您的基本问题是您的发送调用转到了一个动态确定的目标,但是根本没有相应的逻辑来确定哪些进程需要进行接收,如果需要,从哪里接收。

如果您的应用程序逻辑暗示每个人都会发送给每个人,那么您可以使用MPI_Alltoall

如果每个人都发送给某些人,但您知道您将恰好收到四封邮件,那么您可以将 MPI_Isend 用于发送,MPI_Recv 来自 ANY_SOURCE。请注意,您需要 Isend 因为严格来说,您的代码会死锁。如果您的 MPI 具有针对小消息的“急切模式”,它可能会起作用。

如果发送的数量和目标是完全随机的,那么您需要 MPI_Ibarrier 之类的东西来检测是否一切都结束了。

但我怀疑您在这里遗漏了主要信息。为什么local_data的长度是4? part 数组是排列吗?等等。

按照@GillesGouaillardet 的建议,我使用了MPI_AlltoAllv

解决这个问题。