- •Лекция 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,
Int mpi_Alltoall
(void *sbuf, int scount, MPI_Datatype stype,
Void *rbuf, int rcount, mpi_Datatype rtype,
MPI_Comm comm),
где
sbuf, scount, stype – параметры передаваемых сообщений;
rbuf, rcount, rtype – параметры принимаемых сообщений;
comm – коммуникатор, в рамках которого выполняется передача данных.
При выполнении функции MPI_Alltoall каждый процесс в коммуникаторе передает данные из scount элементов каждому процессу (общий размер отправляемых сообщений в процессах должен быть равен scount*p элементов, где p есть количество процессов в коммуникаторе comm) и принимает сообщения от каждого процесса. Вызов функции MPI_Alltoall при выполнении операции общего обмена данными должен быть выполнен в каждом процессе коммуникатора. Работу данной функции иллюстрирует следующий рисунок:
Существует вариант операции общего обмена данных, когда размеры передаваемых процессами сообщений могут быть различны. Для этого используется функция MPI_Alltoallv, которую студентам предлагается освоить самостоятельно.
Лекция 10 Редукция данных
Под термином «редукция» здесь понимается процесс автоматического сбора данных от всех процессов с последующей их обработкой. Предположим, что все процессы подготовили некоторый массив данных, и задачей ведущего процесса является формирование такого массива, в котором каждый элемент был бы равен сумме соответствующих элементов массивов всех процессов (включая свой массив). Данная задача может быть решена алгоритмическим путем с использованием операций MPI_Send и MPI_Recv, однако такой способ будет достаточно трудоемким и малоэффективным. Для наилучшего выполнения действий, связанных с редукцией данных, в MPI предусмотрена функция MPI_Reduce:
Int mpi_Reduce (void *sendbuf, void *recvbuf,
Int count, mpi_Datatype type,
MPI_Op op, int root, MPI_Comm comm)
где
sendbuf – буфер памяти с отправляемым сообщением;
recvbuf – буфер памяти для результирующего сообщения (только для процесса с рангом root);
count – количество элементов в сообщениях;
type – тип элементов сообщений;
op – операция, которая должна быть выполнена над данными;
root – ранг процесса, на котором должен быть получен результат;
comm – коммуникатор, в рамках которого выполняется операция.
В качестве параметра op могут быть использованы предопределенные в MPI операции, приведенные ниже:
MPI_MAX – определение максимального значения;
MPI_MIN – определение минимального значения;
MPI_SUM – определение суммы значений;
MPI_PROD – определение произведения значений;
MPI_LAND – выполнение логической операции «И» над значениями сообщений;
MPI_BAND – выполнение битовой операции «И» над значениями сообщений;
MPI_LOR – выполнение логической операции «ИЛИ» над значениями сообщений;
MPI_BOR – выполнение битовой операции «ИЛИ» над значениями сообщений;
MPI_LXOR – выполнение логической операции исключающего «ИЛИ» над значениями сообщений
MPI_BXOR – выполнение битовой операции исключающего «ИЛИ» над значениями сообщений;
MPI_MAXLOC – определение максимальных значений и их индексов;
MPI_MINLOC – определение минимальных значений и их индексов.
Помимо данного стандартного набора операций пользователем могут быть определены и новые дополнительные операции (см. документацию по библиотеке MPI).
Общая схема выполнения операции сбора и обработки данных изображена на следующем рисунке.
Также следует отметить следующее:
1. Функция MPI_Reduce определяет коллективную операцию и, тем самым, вызов функции должен быть выполнен всеми процессами указываемого коммуникатора, все вызовы функции должны содержать одинаковые значения параметров count, type, op, root, comm.
2. Передача сообщений должна быть выполнена всеми процессами, результат операции будет получен только процессом с рангом root.
3. Выполнение операции редукции осуществляется над отдельными элементами передаваемых сообщений. Так, например, если сообщения содержат по два элемента данных и выполняется операция суммирования MPI_SUM, то результат также будет состоять из двух значений, первое из которых будет содержать сумму первых элементов всех отправленных сообщений, а второе значение будет равно сумме вторых элементов сообщений соответственно (см. рисунок).
Наряду с функцией MPI_Reduce, в библиотеке MPI есть функция MPI_Allreduce, которая выполняет редукцию данных, после чего рассылает результаты редукции всем процессам. Студентам предлагается самостоятельно исследовать возможности данной функции.
