说,如果你做了两个MPI_Sends
和两个MPI_Recvs
,你可以指定MPI_Send
的内容将去哪个缓冲区,如果你有两个不同的缓冲区可用,每个MPI_Recvs
从每个缓冲区接收到什么?
if(rank == MASTER) {
for(kk=1; kk < size; kk++) {
MPI_Recv(printbuf, numcols, MPI_DOUBLE, kk, tag, MPI_COMM_WORLD, &status);
sum = sum + printbuf[kk-1];
}
}
else {
MPI_Send(sum, local_ncols + 2, MPI_DOUBLE, MASTER, tag, MPI_COMM_WORLD);
}
if(rank == MASTER) {
for(kk=1; kk < size; kk++) {
MPI_Recv(secondbuf, numcols, MPI_DOUBLE, kk, tag, MPI_COMM_WORLD, &status);
sum2 = sum2 + secondbuf[kk-1];
}
}
else {
MPI_Send(sum2, local_ncols + 2, MPI_DOUBLE, MASTER, tag, MPI_COMM_WORLD);
}
这是OpenMPI。每个排名都会计算sum
和sum2
。我想获得所有等级'sum
和sum2
的总和。有没有更好的办法?例如,通过指定要发送的sum
和sum2
缓冲区,可以压缩以下代码吗?
答案 0 :(得分:4)
Angelos的评论是正确的:如果您尝试对所有流程的结果进行求和,MPI_Reduce
(e.g., this Q/A,amongst others)就可以了。
回答提出的一般性问题:当您发送消息时,您无法控制接收过程对其执行的操作 - 您所做的就是发送消息。但是,您可以控制一个元数据,然后将其发送到的任务:标签。接收过程可以根据标记决定接收哪个缓冲区:
if (rank != MASTER) {
// worker process
MPI_Send(sum1, local_ncols + 2, MPI_DOUBLE, MASTER, tag1, MPI_COMM_WORLD);
MPI_Send(sum2, local_ncols + 2, MPI_DOUBLE, MASTER, tag2, MPI_COMM_WORLD);
} else {
// master process
MPI_Recv(printbuf, numcols, MPI_DOUBLE, kk, tag1, MPI_COMM_WORLD, &status);
MPI_Recv(secondbuf, numcols, MPI_DOUBLE, kk, tag2, MPI_COMM_WORLD, &status);
}
您还可以采取其他方法。您可以使用MPI的non-overtaking guarantee,它指出从任务1到任务2的两条消息的接收顺序与它们发送的顺序相同,如果它们可以被同一接收方接收 - 这可以确保接收进程可以区分从第二个消息发送的第一个消息。
另一种可以在某些情况下工作的方法是将它们打包到同一个消息中(这对短消息有用,以减少延迟)并在接收端解压缩它们;这是确保您知道哪个数据块进入哪个缓冲区的另一种方法。