ЯиМП_Лекция 25_Паралл_прогр_передача данных.ppt
- Количество слайдов: 33
Лекция 25. Параллельное программирование. Обмен данными между процессами параллельной программы. Языки и методы программирования. доцент М. А. Сокольская
План. 1. Операции передачи процессорами – – – 2. 3. 4. 5. 2 6. данных между двумя Режимы передачи данных Организация неблокирующих обменов данными между процессорами Одновременное выполнение передачи и приема Определение времени выполнения MPI программы. Широковещательная рассылка Пример: вычисление суммы элементов вектора. Передача данных от всех процессов одному процессу… Синхронизация вычислений
Режимы передачи данных Неблоки рующий Буферизова нный Блокиру ющий 3 Стандартный Блокиру ющий Режимы передачи данных По готовности Синхронный Неблоки рующий
Стандартный (Standard) – – 4 обеспечивается функцией MPI_Send, на время выполнения функции процесс-отправитель сообщения блокируется, после завершения функции буфер может быть использован повторно, состояние отправленного сообщения может быть различным - сообщение может располагаться в процессе-отправителе, может находиться в процессе передачи, может храниться в процессе-получателе или же может быть принято процессом-получателем при помощи функции MPI_Recv.
Стандартный (Standard) Выполняется достаточно быстро, но может приводить к большим расходам ресурсов (памяти), рекомендуется для передачи коротких сообщений Неблокирующий стандартный режим: int MPI_Isend(void *buf, int count, MPI_Datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request); Наименование неблокирующих аналогов образуется из названий соответствующих функций путем добавления префикса I (Immediate). 5
Синхронный (Synchronous) завершение функции отправки сообщения происходит только при получении от процесса-получателя подтверждения о начале приема отправленного сообщения: MPI_Ssend – функция отправки сообщения в синхронном режиме - наиболее медленный, т. к. требует подтверждения приема. В тоже время, этот режим наиболее надежен – можно рекомендовать его для передачи длинных сообщений. – Неблокирующий вариант: int MPI_Issend(void *buf, int count, MPI_Datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request); 6
Передача по готовности (Ready) может быть использован только, если операция приема сообщения уже инициирована. Буфер сообщения после завершения функции отправки сообщения может быть повторно использован. MPI_Rsend – функция отправки сообщения в режиме по готовности Формально является наиболее быстрым, но используется достаточно редко, т. к. обычно сложно гарантировать готовность операции приема – Неблокирующая функция: int MPI_Irsend(void *buf, int count, MPI_Datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request); 7
Буферизованный (Buffered) используются дополнительные системные буферы для копирования в них отправляемых сообщений; функция отправки сообщения завершается сразу же после копирования сообщения в буфер, MPI_Bsend – функция отправки сообщения в буферизованном режиме, – выполняется достаточно быстро, но может приводить к большим расходам ресурсов (памяти), рекомендуется для передачи коротких сообщений Неблокирующая функция: int MPI_Ibsend(void *buf, int count, MPI_Datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request); – 8
Блокирующие и неблокирующие обмены l l Блокирующие функции приостанавливают выполнение процессов до момента завершения работы вызванных функций (по умолчанию), Неблокирующие функции обмена данными выполняются без блокировки процессов для совмещения процессов передачи сообщений и вычислений (требуют специальных функций): – – 9 Более сложны для использования, Могут в значительной степени уменьшить потери эффективности параллельных вычислений за счёт ускорения обменов данными.
Организация неблокирующих обменов данными между процессорами… Функция неблокирующего приёма сообщений: int MPI_Irecv(void *buf, int count, MPI_Datatype, int source, int tag, MPI_Comm comm, MPI_Request *request); 10
Организация неблокирующих обменов данными между процессорами… Проверка состояния выполняемой неблокирующей операции передачи данных выполняется при помощи функции: int MPI_Test( MPI_Request *request, int *flag, MPI_status *status), где request - дескриптор операции, определенный при вызове неблокирующей функции, flag - результат проверки (= true, если операция завершена), status - результат выполнения операции обмена (только для завершенной операции). Операция проверки является неблокирующей. 11
Организация неблокирующих обменов данными между процессорами… Возможная схема вычислений и выполнения неблокирующей операции обмена: MPI_Isend(buf, count, type, dest, tag, comm, &request); … do { … MPI_Test(&request, &flag, &status); } while ( !flag ); Блокирующая операция ожидания завершения операции: 12 int MPI_Wait( MPI_Request *request, MPI_status *status);
Одновременное выполнение передачи и приема 13 int MPI_Sendrecv (void *sbuf, int scount, MPI_Datatype stype, int dest, int stag, void *rbuf, int rcount, MPI_Datatype rtype, int source, int rtag, MPI_Comm comm, MPI_Status *status), где - sbuf, scount, stype, dest, stag - параметры передаваемого сообщения, - rbuf, rcount, rtype, source, rtag - параметры принимаемого сообщения, - comm - коммуникатор, в рамках которого выполняется передача данных, - status – структура данных с информацией о результате выполнения операции.
Передача данных от чётных процессов нечётным и наоборот … if (Rank%2) MPI_Sendrecv (&chislo, 1, MPI_INT, (Rank+1)%Size, 0, &chislo 1, 1, MPI_INT, (Rank+Size-1)%Size, 0, MPI_COMM_WORLD, &Status); else MPI_Sendrecv (&chislo, 1, MPI_INT, (Rank+1)%Size, 0, &chislo 1, 1, MPI_INT, (Rank-1)%Size, 0, MPI_COMM_WORLD, &Status); … 14
Определение времени выполнения MPI программы Необходимо определять время выполнения вычислений для оценки достигаемого ускорения за счет использования параллелизма, – Получение времени текущего момента выполнения программы обеспечивается при помощи функции: double MPI_Wtime(void); – Точность измерения времени может зависеть от среды выполнения параллельной программы. Для определения текущего значения точности может быть использована функция: double MPI_Wtick(void); (время в секундах между двумя последовательными показателями времени аппаратного таймера используемой системы) – 15
Коллективные операции передачи данных Для примера рассмотрим задачу суммирования элементов вектора x: – – 16 Для решения необходимо разделить данные на равные блоки, передать эти блоки процессам, выполнить в процессах суммирование полученных данных, собрать значения вычисленных частных сумм на одном из процессов и сложить значения частичных сумм для получения общего результата решаемой задачи, Для более простого изложения примера процессам программы будут передаваться весь суммируемый вектор, а не отдельные блоки этого вектора.
Передача данных от одного процесса всем процессам программы… Необходимо передать значения вектора x всем процессам параллельной программы, Можно воспользоваться рассмотренными ранее функциями парных операций передачи данных: MPI_Comm_size(MPI_COMM_WORLD, &Proc. Num); for (i=1; i<Proc. Num; i++) MPI_Send(&x, n, MPI_DOUBLE, i, 0, MPI_COMM_WORLD); Повторение операций передачи приводит к суммированию затрат (латентностей) на подготовку передаваемых сообщений и, в итоге, замедлению передачи 17 Данная операция может быть выполнена за меньшее число операций передачи данных.
Передача данных от одного процесса всем процессам программы… Широковещательная рассылка данных может быть обеспечена при помощи функции MPI: int MPI_Bcast(void *buf, int count, MPI_Datatype, int root, MPI_Comm comm), где - buf, count, type – буфер памяти с отправляемым сообщением (для процесса с рангом 0), и для приема сообщений для всех остальных процессов, - root - ранг процесса, выполняющего рассылку данных, - comm - коммуникатор, в рамках которого выполняется передача данных. 18
Передача данных от одного процесса всем процессам программы… Функция MPI_Bcast осуществляет рассылку данных из буфера buf, содержащего count элементов типа type с процесса, имеющего номер root, всем процессам, входящим в коммуникатор comm 19
Передача данных от одного процесса всем процессам программы… – – 20 Функция MPI_Bcast определяет коллективную операцию, вызов функции MPI_Bcast должен быть осуществлен всеми процессами указываемого коммуникатора, Указываемый в функции MPI_Bcast буфер памяти имеет различное назначение в разных процессах: l Для процесса с рангом root, с которого осуществляется рассылка данных, в этом буфере должно находиться рассылаемое сообщение. l Для всех остальных процессов указываемый буфер предназначен для приема передаваемых данных.
Суммирование элементов массива 21 #include “mpi. h” int main (int argc, char *argv[ ]) { double x [100], Total. Sum, Proc. Sum = 0. 0; int Proc. Rank, Proc. Num, N=100, k, i 1, i 2; MPI_Status; //Инициализация MPI_Init (&argc, &argv); MPI_Comm_size (MPI_COMM_WORLD, &Proc. Num); MPI_Comm_rank (MPI_COMM_WORLD, &Proc. Rank);
22 //Подготовка данных if (Proc. Rank == 0) Data. Init (x, N); //Рассылка данных на все процессы MPI_Bcast (x, N, MPI_DOUBLE, 0, MPI_COMM_WORLD); //Вычисление частичной суммы на каждом из //процессоров //на каждом процессоре суммируются элементы //вектора x от i 1 до i 2 k = N / Proc. Num; i 1 = k * Proc. Rank; i 2 = k * (Proc. Rank + 1);
23 if (Proc. Rank == Proc. Num – 1) i 2 = N; for (int i = i 1; i < i 2; i++) Proc. Sum = Proc. Sum + x [ i ]; if (Proc. Rank == 0) //Сборка частичных сумм { // на процессоре с рангом 0 Total. Sum = Proc. Sum; for (int i = i 1; i < i 2; i++) { MPI_Recv (&Proc. Sum, 1, MPI_DOUBLE, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &Status); Total. Sum = Total. Sum + Proc. Sum; } }
else //все процессы отсылают свои частичные суммы MPI_Send (&Proc. Sum, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); //Вывод результата if (Proc. Rank == 0) cout<<“n. Total Sum = ”<<Total. Sum; MPI_Finalize(); return 0; } 24
Самостоятельно Добавить в программу возможность измерения времени выполнения программы 25
Передача данных от всех процессов одному процессу… Процедура сбора и последующего суммирования данных является примером часто выполняемой коллективной операции передачи данных от всех процессов одному процессу, в которой над собираемыми значениями осуществляется та или иная обработка данных. 26
Передача данных от всех процессов одному процессу… 27 int MPI_Reduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype, MPI_Op op, int root, MPI_Comm comm), где - sendbuf - буфер памяти с отправляемым сообщением, - recvbuf – буфер памяти для результирующего сообщения (только для процесса с рангом root), - count - количество элементов в сообщениях, - type – тип элементов сообщений, - op - операция, которая должна быть выполнена над данными, - root - ранг процесса, на котором должен быть получен результат, - comm - коммуникатор, в рамках которого выполняется операция.
Типы операций MPI для функций редукции данных… Операция MPI_MAX Определение максимального значения MPI_MIN Определение минимального значения MPI_SUM Определение суммы значений MPI_PROD Определение произведения значений MPI_LAND Выполнение логической операции "И" над значениями сообщений MPI_LOR Выполнение логической операции "ИЛИ" над значениями сообщений MPI_LXOR Выполнение логической операции исключающего "ИЛИ" над значениями сообщений MPI_MAXLOC Определение максимальных значений и их индексов MPI_MINLOC 28 Описание Определение минимальных значений и их индексов
Типы операций MPI для функций редукции данных… – – MPI_SUM вычисляет поэлементную сумму векторов; – MPI_PROD вычисляет поэлементное произведение векторов; – MPI_LAND, MPI_LOR, MPI_LXOR, - логические и двоичные операции И, ИЛИ, исключающее ИЛИ; – 29 MPI_MAX и MPI_MIN ищут поэлементные максимум и минимум; MPI_MAXLOC, MPI_MINLOC - поиск индексированного минимума/максимума
Передача данных от всех процессов одному процессу… – – – 30 Функция MPI_Reduce определяет коллективную операцию и, тем самым, вызов функции должен быть выполнен всеми процессами указываемого коммуникатора, все вызовы функции должны содержать одинаковые значения параметров count, type, op, root, comm, Передача сообщений должна быть выполнена всеми процессами, результат операции будет получен только процессом с рангом root, Выполнение операции редукции осуществляется над отдельными элементами передаваемых сообщений. ;
Передача данных от всех процессов одному процессу (пример для операции суммирования) 31
Самостоятельно 1. 2. 32 Изменить пример суммирования вектора использовав функцию MPI_Reduce. Сравнить время работы программы с предыдущей версией на достаточно больших по размеру векторах.
Итоги Мы рассмотрели: Передачу данных от всех процессов одному процессу, передачу данных от одного процесса всем процессам (широковещательную рассылку), режимы передачи данных, организацию неблокирующих обменов данными между процессорами 33
ЯиМП_Лекция 25_Паралл_прогр_передача данных.ppt