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
解决这个问题。
我正在尝试在每个进程上都有一个数组的所有进程之间发送数据,例如
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
解决这个问题。