Возможно, вы слишком много думаете об этом — в приведенном выше случае вы могли бы сделать это с помощью одного сокращения и одной пары отправки/получения:
#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;
}
person
Jonathan Dursi
schedule
19.06.2014