Презентацию к данной лекции Вы можете скачать здесь.
Широковещательная рассылка выполняется подпрограммой
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm) MPI_Bcast(buffer, count, datatype, root, comm, ierr)
Параметры этой процедуры одновременно являются входными и выходными:
Пример
#include "mpi.h"
#include <stdio.h>
int main(int argc,char *argv[])
{
char data[24];
int myrank, count = 25;
MPI_Status status;
MPI_Init(argc, argv);
MPI_Comm_rank(MPI_COMM_WORLD, myrank);
if (myrank == 0)
{
strcpy(data, "Hi, Parallel Programmer!");
MPI_Bcast(data, count, MPI_BYTE, 0, MPI_COMM_WORLD);
printf("send: %s\n", data);
}
else
{
MPI_Bcast(data, count, MPI_BYTE, 0, MPI_COMM_WORLD);
printf("received: %s\n", data);
}
MPI_Finalize();
return 0;
}
Пример
#include "mpi.h"
#include <stdio.h>
int main(int argc, char *argv[])
{
int myrank;
int root = 0;
int count = 1;
float a, b;
int n;
MPI_Init(argc, argv);
MPI_Comm_rank(MPI_COMM_WORLD, myrank);
if (myrank == 0)
printf("Enter a, b, n\n");
scanf("%f %f %i", a, b, n);
MPI_Bcast(a, count, MPI_FLOAT, root, MPI_COMM_WORLD);
MPI_Bcast(b, count, MPI_FLOAT, root, MPI_COMM_WORLD);
MPI_Bcast(n, count, MPI_INT, root, MPI_COMM_WORLD);
}
else
{
MPI_Bcast(a, count, MPI_FLOAT, root, MPI_COMM_WORLD);
MPI_Bcast(b, count, MPI_FLOAT, root, MPI_COMM_WORLD);
MPI_Bcast(n, count, MPI_INT, root, MPI_COMM_WORLD);
printf("%i Process got %f %f %i\n", myrank, a, b, n);
}
MPI_Finalize();
return 0;
}
Пример
int MPI_Scatter(void *sendbuf, int sendcount, MPI_Datatype sendtype,
void *rcvbuf, int rcvcount, MPI_Datatype rcvtype, int root, MPI_Comm comm)
MPI_Scatter(sendbuf, sendcount, sendtype, rcvbuf, rcvcount, rcvtype, root, comm, ierr)
Входные параметры:
sendbuf - адрес буфера передачи;sendcount - количество элементов, пересылаемых каждому процессу;sendtype - тип передаваемых данных;rcvcount - количество элементов в буфере приема;rcvtype - тип принимаемых данных;root - ранг передающего процесса;comm - коммуникатор.Выходной параметр: rcvbuf - адрес буфера приема.
Процесс с рангом root распределяет содержимое буфера передачи sendbuf среди всех процессов. Содержимое буфера передачи разбивается на несколько фрагментов, каждый из которых содержит sendcount элементов. Первый фрагмент передается процессу 0, второй процессу 1 и т. д. Аргументы send… имеют значение только на стороне распределяющего процесса root
Сбор данных от остальных процессов в буфер главной задачи выполняется подпрограммой:
int MPI_Gather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
void *rcvbuf, int rcvcount, MPI_Datatype rcvtype, int root, MPI_Comm comm)
MPI_Gather(sendbuf, sendcount, sendtype, rcvbuf, rcvcount, rcvtype, root, comm, ierr)
Каждый процесс в коммуникаторе comm пересылает содержимое буфера передачи sendbuf процессу с рангом root. Процесс root склеивает полученные данные в буфере приема.
Порядок склейки определяется рангами процессов:
Аргументы rcvbuf, rcvcount и rcvtype играют роль только на стороне главного процесса. Аргумент rcvcount указывает количество элементов данных, полученных от каждого процесса (но НЕ суммарное их количество). При вызове подпрограмм MPI_Scatter и MPI_Gather из разных процессов следует использовать общий главный процесс.
int MPI_Allgather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
void *rcvbuf, int rcvcount, MPI_Datatype rcvtype, MPI_Comm comm)
MPI_Allgather(sendbuf, sendcount, sendtype, rcvbuf, rcvcount, rcvtype, comm, ierr)
Входные параметры:
Выходной параметр: rcvbuf - адрес буфера приема.
Блок данных, переданный от j-го процесса, принимается каждым процессом и размещается в j-м блоке буфера приема recvbuf
Операция приведения, результат которой передается одному процессу
int MPI_Reduce(void *buf, void *result, int count,
MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm)
MPI_Reduce(buf, result, count, datatype, op, root, comm, ierr)
Входные параметры:
MPI_Reduce применяет операцию приведения к операндам из buf, а результат каждой операции помещается в буфер результата result. MPI_Reduce должна вызываться всеми процессами в коммуникаторе comm, а аргументы count, datatype и op в этих вызовах должны совпадать
Пример
#include "mpi.h"
#include <stdio.h>
int main(int argc,char *argv[])
{
int myrank, i;
int count = 5, root = 1;
MPI_Group MPI_GROUP_WORLD, subgroup;
int ranks[4] = {1, 3, 5, 7};
MPI_Comm subcomm;
int sendbuf[5] = {1, 2, 3, 4, 5};
int recvbuf[5];
MPI_Init(argc, argv);
MPI_Comm_group(MPI_COMM_WORLD, MPI_GROUP_WORLD);
MPI_Group_incl(MPI_GROUP_WORLD, 4, ranks, subgroup);
MPI_Group_rank(subgroup, myrank);
MPI_Comm_create(MPI_COMM_WORLD, subgroup, subcomm);
if(myrank != MPI_UNDEFINED)
{
MPI_Reduce(sendbuf, recvbuf, count, MPI_INT, MPI_SUM, root, subcomm);
if(myrank == root) {
printf("Reduced values");
for(i = 0; i < count; i++){
printf(" %i ", recvbuf[i]);}
}
printf("\n");
MPI_Comm_free(subcomm);
MPI_Group_free(MPI_GROUP_WORLD);
MPI_Group_free(subgroup);
}
MPI_Finalize();
return 0;
}
Пример. Использование операции приведения: вычисление числа$$\pi$$ методом Монте-Карло
#include <stdlib.h>
#include <stdio.h>
#include "mpi.h"
double dboard (int trials);
#define trials 5000
#define ROUNDS 10
#define MASTER 0
main(int argc, char **argv)
{
double homepi, pisum, pi, avepi;
int mytid, nproc, rcode, ;
MPI_Init(argc, argv);
MPI_Comm_rank(MPI_COMM_WORLD, mytid);
MPI_Comm_size(MPI_COMM_WORLD, nproc);
printf ("MPI task ID = %d\n", mytid);
srandom (mytid);
avepi = 0;
for (i = 0; i < ROUNDS; i++) {
homepi = dboard(trials);
rcode = MPI_Reduce(homepi, pisum, 1, MPI_DOUBLE,
MPI_SUM, MASTER, MPI_COMM_WORLD);
if (rcode != 0)
printf("%d: failure on MPI_Reduce\n", mytid);
if (mytid == MASTER) {
pi = pisum/nproc;
avepi = ((avepi * i) + pi)/(i + 1);
printf(" After %3d throws, average value of pi =
%10.8f\n", (trials * (i + 1)),avepi);
}
}
MPI_Finalize();
}
#include <stdlib.h>
#define sqr(x) ((x)*(x))
long random(void);
double dboard(int trials)
{
double x_coord, y_coord, pi, r;
int score, n;
unsigned long cconst;
cconst = 2 << (31 - 1);
score = 0;
for (n = 1; n <= trials; n++) {
r = (double)random()/cconst;
x_coord = (2.0 * r) - 1.0;
r = (double)random()/cconst;
y_coord = (2.0 * r) - 1.0;
if ((sqr(x_coord) + sqr(y_coord)) <= 1.0)
score++;
}
pi = 4.0 * (double)score/(double)trials;
return(pi);
}
Синхронизация с помощью "барьера" выполняется с помощью подпрограммы:
int MPI_Barrier(MPI_Comm comm)
MPI_Barrier(comm, ierr)
Синхронизация с помощью "барьера" - простейшая форма синхронизации коллективных обменов. Она не требует пересылки данных. Обращение к подпрограмме MPI_Barrier блокирует выполнение каждого процесса из коммуникатора comm до тех пор, пока все процессы не вызовут эту подпрограмму.
В общем случае барьер характеризуется "толщиной". "Толщина" – количество процессов, которые должны обратиться к подпрограмме барьерной синхронизации для того, чтобы барьер был преодолен.
Векторная подпрограмма распределения данных:
int MPI_Scatterv(void *sendbuf, int *sendcounts, int *displs, MPI_Datatype sendtype,
void *rcvbuf, int rcvcount, MPI_Datatype rcvtype, int root, MPI_Comm comm)
MPI_Scatterv(sendbuf, sendcounts, displs, sendtype, rcvbuf, rcvcount, rcvtype, root, comm, ierr)
Входные параметры:
sendbuf - адрес буфера передачи;sendcounts - целочисленный одномерный массив, содержащий количество элементов, передаваемых каждому процессу (индекс равен рангу адресата). Его длина равна количеству процессов в коммуникаторе;displs - целочисленный массив, длина которого равна количеству процессов в коммуникаторе. Элемент с индексом i задает смещение относительно начала буфера передачи. Ранг адресата равен значению индекса i;sendtype - тип данных в буфере передачи;rcvcount - количество элементов в буфере приема;rcvtype - тип данных в буфере приема;root - ранг передающего процесса;comm - коммуникатор.Выходной параметр: rcvbuf - адрес буфера приема.
Сбор данных от всех процессов в заданном коммуникаторе и запись их в буфер приема с указанным смещением:
int MPI_Gatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf,
int *recvcounts, int *displs, MPI_Datatype recvtype, int root, MPI_Comm comm)
MPI_Gatherv(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, root, comm, ierr)
Список параметров у этой подпрограммы похож на список параметров подпрограммы MPI_Scatterv. В обменах, выполняемых подпрограммами MPI_Allgather и MPI_Alltoall, нет главного процесса. Детали отправки и приема важны для всех процессов, участвующих в обмене.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.