- •Лекция 1 Классификация многопроцессорных систем
- •Сетевой закон Амдала
- •Лекция 2 Техническая реализация многопроцессорных систем
- •Лекция 3 Система передачи сообщений mpi
- •Принципы работы mpich
- •Лекция 4 Структура mpi-программы
- •Int main(int argc, char* argv[]) { int procs_rank, procs_count; // Определяем переменные
- •Int mpi_Init (int* argc, char*** argv)
- •Int mpi_Comm_size(mpi_Comm comm, int *size)
- •Int mpi_Comm_rank(mpi_Comm comm, int *rank)
- •Int mpi_Finalize(void)
- •Определение времени выполнения mpi программы
- •Понятие коммуникатора
- •Лекция 5 Передача сообщений
- •Общие сведения о функциях передачи сообщений
- •Передача сообщения «точка-точка»
- •Int mpi_Send(void *buf, int count, mpi_Datatype type, int dest, int tag, mpi_Comm comm)
- •Прием сообщений «точка-точка» с блокировкой
- •Int mpi_Recv(void *buf, int count, mpi_Datatype type, int source, int tag, mpi_Comm comm, mpi_Status *status)
- •Int main(int argc, char* argv[])
- •Int ProcNum, ProcRank, RecvRank;
- •Лекция 6 Определение времени выполнения программы
- •Int s1; // Место под результат
- •Int size; // Размер принимаемого массива
- •Int Summa; // Сумма его элементов
- •Input n: 1000
- •Лекция 7 Функции неблокирующего обмена данными
- •Int mpi_Test(mpi_Request *request, int *flag,
- •Int mpi_Wait(mpi_Request *request, mpi_status *status)
- •Одновременное выполнение приема и передачи данных
- •Int mpi_Sendrecv (void *sbuf, int scount,
- •Int stag, void *rbuf, int rcount,
- •Int rtag, mpi_Comm comm,
- •Int mpi_Sendrecv_replace (void *buf, int count,
- •Int stag, int source,
- •Int rtag, mpi_Comm comm,
- •Лекция 8 Коллективные операции передачи данных
- •Функция синхронизации процессов
- •Int mpi_Barrier(mpi_Comm comm);
- •Широковещательная рассылка данных
- •Int mpi_Bcast (void* buffer, int count,
- •Int main(int argc, char* argv[])
- •Int proc_rank, proc_count;
- •Широковещательная рассылка индивидуальных данных
- •Int mpi_Scatter
- •Void *rbuf, int rcount, mpi_Datatype rtype,
- •Int root, mpi_Comm comm)
- •Лекция 9 Функции сбора блоков данных от всех процессов группы
- •Int mpi_Gather
- •Void* recvbuf, int recvcount, mpi_Datatype recvtype,
- •Int root, mpi_Comm comm);
- •Int array[100];
- •Int root, *rbuf, proc_count;
- •Int mpi_Allgather
- •Void *rbuf, int rcount, mpi_Datatype rtype,
- •Передача данных от всех процессов всем процессам
- •Int mpi_Alltoall
- •Void *rbuf, int rcount, mpi_Datatype rtype,
- •Лекция 10 Редукция данных
- •Int mpi_Reduce (void *sendbuf, void *recvbuf,
- •Int count, mpi_Datatype type,
Лекция 9 Функции сбора блоков данных от всех процессов группы
Семейство функций сбора блоков данных от всех процессов группы состоит из четырех функций: MPI_Gather, MPI_Allgather, MPI_Gatherv и MPI_Allgatherv.
Функция MPI_Gather производит сборку блоков данных, посылаемых всеми процессами группы, в один массив процесса с номером root. Длина блоков предполагается одинаковой. Объединение происходит в порядке увеличения номеров процессов-отправителей. То есть данные, посланные процессом с номером i из своего буфера sendbuf, помещаются в i-ю порцию буфера recvbuf процесса 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 – коммуникатор.
Тип посылаемых элементов sendtype должен совпадать с типом recvtype получаемых элементов, а число sendcount должно равняться числу recvcount. То есть, recvcount в вызове из процесса root – это число собираемых от каждого процесса элементов, а не общее количество собранных элементов.
Например:
MPI_Comm comm;
Int array[100];
Int root, *rbuf, proc_count;
...
MPI_Comm_size(comm, proc_count);
rbuf = (int *) malloc( proc_count * 100 * sizeof(int));
MPI_Gather(array, 100, MPI_INT, rbuf, 100, MPI_INT, root, comm);
В данном примере общее количество процессов помещается в переменную proc_count, после чего выделяется динамическая память под proc_count блоков, каждый из которых содержит 100 элементов типа int. Затем данный массив заполняется с помощью функции MPI_Gather.
Работа функции MPI_Gather иллюстрируется следующим рисунком:
Отметим, что при использовании функции MPI_Gather сборка данных осуществляется только на одном процессе. Для получения всех собираемых данных на каждом из процессов коммуникатора необходимо использовать функцию сбора и рассылки:
Int mpi_Allgather
(void *sbuf, int scount, MPI_Datatype stype,
Void *rbuf, int rcount, mpi_Datatype rtype,
MPI_Comm comm).
Если размеры передаваемых процессами сообщений различны, выполнение операции сбора данных обеспечивается при помощи функций MPI_Gatherv и MPI_Allgatherv. Студентам предлагается самостоятельно изучить данные функции по документации к библиотеке MPI и материалам в сети Интернет.
Передача данных от всех процессов всем процессам
Наиболее общей операцией передачи данных является передача данных от всех процессов всем процессам. Выполнение данной операции может быть обеспечено при помощи функции:
