Семейство функций сбора блоков данных от всех процессов группы состоит из четырех подпрограмм: MPI_Gather, MPI_Allgather, MPI_Gatherv, MPI_Allgatherv. Каждая из указанных подпрограмм расширяет функциональные возможности предыдущих.
Функция MPI_Gather производит сборку блоков данных, посылаемых всеми процессами группы, в один массив процесса с номером root. Длина блоков предполагается одинаковой. Объединение происходит в порядке увеличения номеров процессов-отправителей.
int MPI_Gather(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype,int root, MPI_Comm comm)
sendbuf -адрес начала размещения посылаемых данных; sendcount -число посылаемых элементов; sendtype - тип посылаемых элементов; recvbuf - адрес начала буфера приема (используется только в процессе-получателе root); recvcount -число элементов, получаемых от каждого процесса (используется только в процессе-получателе root); recvtype - тип получаемых элементов; root - номер процесса-получателя; comm - коммуникатор.
MPI_Comm comm;
int array[100];
int root, *rbuf;
...
MPI_Comm_size(comm, &gsize);
rbuf = (int *) malloc(gsize * 100 * sizeof(int));
MPI_Gather(array, 100, MPI_INT, rbuf, 100, MPI_INT, root, comm);
Функция MPI_Allgather выполняется так же, как MPI_Gather, но получателями являются все процессы группы. Данные, посланные процессом i из своего буфера sendbuf, помещаются в i-ю порцию буфера recvbuf каждого процесса. После завершения операции содержимое буферов приема recvbuf у всех процессов одинаково.
int MPI_Allgather(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm)
Функция MPI_Gatherv позволяет собирать блоки с разным числом элементов от каждого процесса, так как количество элементов, принимаемых от каждого процесса, задается индивидуально с помощью массива recvcounts. Эта функция обеспечивает также большую гибкость при размещении данных в процессе-получателе, благодаря введению в качестве параметра массива смещений displs.
int MPI_Gatherv(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* rbuf, int *recvcounts, int *displs, MPI_Datatype recvtype, int root, MPI_Comm comm)
Функция MPI_Alltoall совмещает в себе операции Scatter и Gather и является по сути дела расширением операции Allgather, когда каждый процесс посылает различные данные разным получателям. Процесс i посылает j-ый блок своего буфера sendbuf процессу j, который помещает его в i-ый блок своего буфера recvbuf. Количество посланных данных должно быть равно количеству полученных данных для каждой пары процессов.
int MPI_Alltoall(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm)
Функция MPI_Allreduce сохраняет результат редукции в адресном пространстве всех процессов, поэтому в списке параметров функции отсутствует идентификатор корневого процесса root. В остальном, набор параметров такой же, как и в предыдущей функции.
int MPI_Allreduce(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
Напишите программу параллельного скалярного умножения векторов.
int main(int argc,char **argv)
{
int size,rank,i,n=6;
float *a,*b;
a=new float[n];
b=new float[n];
for(i=0;i<n;i++)
{
a[i]=i+1;
b[i]=i+1;
}
MPI_Status status;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
float f=0,s=0,s1=0;
int nachalo,konec,shag;
shag=n/(size-1);
if(rank!=size-1)
{
nachalo=rank*shag;
konec=rank*shag+shag;
for(i=nachalo;i<konec;i++)
s=s+a[i]*b[i];
MPI_Send(&s,1,MPI_FLOAT,size-1,1,MPI_COMM_WORLD);
}
if(rank==size-1){
for(i=0;i<size-1;i++)
{ MPI_Recv(&s,1,MPI_FLOAT,i,1,MPI_COMM_WORLD,&status);
f=f+s; }
printf("%f\n",f);
}
MPI_Finalize();}
Сурак