是否有一个等同于MPI_Reduce_scatter
的MPI函数,它只在一部分处理器中执行散射?如果没有这样的功能,这是最有效的MPI呼叫序列?
为清楚起见,假设reduce操作是总和。 来自
proc sendbuf
1 a1 | b1
2 a2 | b2
3 a3 | b3
4 a4 | b4
我想要
proc recvbuf
1 a
2 b
3
4
a = a1 + a2 + a3 + a4
和b = b1 + b2 + b3 + b4
。
MPI_Reduce
。第一个减少a
并且有1个作为根处理器。第二个减少b
s并且有2个作为根处理器。但是,当有很多字母时会变得很重。 (和许多处理器)。recv_count[proc]
属于处理器子集时才设置proc
与零不同。但是,在散布消息时,会有n_proc
个方形握手(大多数都没用,因为实际上没有发送消息)。答案 0 :(得分:1)
我同意,如果你希望MPI为你做(你可能会做大规模的),那么两个MPI_REDUCE
电话可能会和你一样好。
答案 1 :(得分:1)
你可能会过度思考 - 在上面的例子中,你可以用一个reduce和一个send / recv对来做到这一点:
#include <stdio.h>
#include <mpi.h>
int main(int argc, char **argv) {
int data[2], result[2];
int rank, size;
const int amaster=0, bmaster=1;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
data[0] = 2*rank;
data[1] = 3*rank;
MPI_Reduce(data, result, 2, MPI_INT, MPI_SUM, amaster, MPI_COMM_WORLD);
if (rank == amaster) {
int tota = result[0];
printf("%d: Total a = %d, expected = %d\n", rank, tota, 2*size*(size-1)/2);
MPI_Send(&(result[1]), 1, MPI_INT, bmaster, 0, MPI_COMM_WORLD);
}
if (rank == bmaster) {
int totb;
MPI_Recv(&totb, 1, MPI_INT, amaster, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("%d: Total b = %d, expected = %d\n", rank, totb, 3*size*(size-1)/2);
}
MPI_Finalize();
return 0;
}
多个数据的自然概括是分散的,所以你对MPI_Reduce_scatter
的直觉是正确的,但是这里因为两组任务重叠(所以你不能使用一个内部通信器)但不是同样,你必须做一个减少后跟散点图,散点图必须在另一个传播者身上:
#include <stdio.h>
#include <mpi.h>
int main(int argc, char **argv) {
const int ndata = 5;
int data[ndata], result[ndata];
int rank, size;
const int amaster=0;
MPI_Comm scattercomm;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (size < ndata) {
if (rank == 0) fprintf(stderr,"Too few ranks; exiting\n");
MPI_Abort(MPI_COMM_WORLD,1);
}
for (int i=0; i<ndata; i++)
data[i] = (i+2)*rank;
/* create scatter communicator; all of comm world must participate */
MPI_Group basegrp, scattergrp;
MPI_Comm_group(MPI_COMM_WORLD, &basegrp);
int mpiranks[ndata];
for (int i=0; i<ndata; i++)
mpiranks[i] = i;
MPI_Group_incl(basegrp, ndata, mpiranks, &scattergrp);
MPI_Comm_create(MPI_COMM_WORLD, scattergrp, &scattercomm);
MPI_Reduce(data, result, ndata, MPI_INT, MPI_SUM, amaster, MPI_COMM_WORLD);
if (rank < ndata) {
int item;
MPI_Scatter(result, 1, MPI_INT, &item, 1, MPI_INT, amaster, scattercomm);
printf("%d: Total = %d, expected = %d\n", rank, item, (rank+2)*size*(size-1)/2);
}
MPI_Finalize();
return 0;
}