MPI_seminars.pptx
- Количество слайдов: 17
MPI (Message Passing Interface) MPI (интерфейс передачи сообщений) – API для передачи информации ( сообщений), между процессами выполняющими одну задачу. MPI поддерживает MIMD, но чаще используется SPМD модель параллельного программирования Библиотека, версии 1. 1, 2. 0 для Fortran и С. Подмножество MPI для Python, Java Standardization-Portability-Performance-Functionality-Availability MPI программа – множество параллельных процессов, обменивающиеся сообщениям. Общих данных у процессов нет. Distributed Memory model. Группа процессов – упорядоченное множество процессов с идентификаторами. Группы могут пересекаться, входить одна в другую. Процесс в каждой группе имеет свой уникальный идентификатор в промежутке от 0 до количества процессов в группе – 1. Коммуникаторы – объекты, обеспечивающие коммуникацию между процессами в группе ( описатели областей связи). Intracommunicator - описывает область связи некоторой группы процессов Intercommunicator - служит для связи между процессами двух различных групп Процессы взаимодействуют только внутри некоторого коммуникатора. MPI_COMM_WORLD, MPI_COMM_SELF, MPI_COMM_NULL
MPI (Message Passing Interface) Коммуникатор может задавать топологию: наиболее распространены линейная, двумерная и трехмерная сетка. Сообщение – данные некоторого типа с атрибутами ( кто, кому отправил, тег для различения сообщений от одного и того же процесса) Общая структура MPI программы: mpi. h -> инициализация MPI окружения-> паралельное исполнение, вызовы функций коммуникации -> удаление MPI окружения. Базовые функции • MPI_Init (*argc, *argv). Инициализация, обязательно в начале каждой MPI программы и только один раз. Создает группу процессов для всех процессов приложения и соответствующий коммуникатор MPI_COMM_WORLD и коммуникатор MPI_COMM_SELF для каждого отдельного процесса. Другие процедуры могут быть вызваны только после инициализации. • MPI_Initialized (*flag) Был ли вызван MPI_Init
MPI (Message Passing Interface) • MPI_Finalize () Закрывает все процессы и коммуникаторы. Перед вызовом должны быть завершены все коммуникации процесса. После нельзя вызвать никакие процедуры MPI. • MPI_Comm_size (comm, *size). Возвращает число процессов в коммуникаторе. • MPI_Comm_rank (comm, *rank). Возвращает номер процесса в коммуникаторе, которые ее вызвал. • MPI_Abort (comm, errorcode). Удаляет все процессы в коммуникаторе comm. Основные функции библиотеки MPI: • Создание и удаление процессов ( с версии 2. 0 и в ходе выполнения) • Создание топологии процессов • Коммуникация типа точка-точка • Коммуникация в группе и работа с коммуникаторами • Коллективные операции, работа со структурами данных Возвращают код успеха MPI_SUCCESS или код соотв. ошибки.
MPI: пример #include "mpi. h" #include <stdio. h> int main(int argc, char *argv) { int numtasks, rank, res; res = MPI_Init(&argc, &argv); if (res != MPI_SUCCESS) { printf (“ MPI Initialization failed! n"); MPI_Abort(MPI_COMM_WORLD, res); } MPI_Comm_size(MPI_COMM_WORLD, &numtasks); MPI_Comm_rank(MPI_COMM_WORLD, &rank); printf ("Number of tasks= %d My rank= %dn", numtasks, rank); MPI_Finalize(); } Ømpicc test. c –o test. out Ømpirun –np 4 test. out
MPI (Message Passing Interface) MPI функции по способу выполнения • локальная - выполнение внутри вызывающего процесса, завершение не требует коммуникаций. • нелокальная – для завершения требуется выполнение MPI процедуры другим процессом. • глобальная - выполняют все процессы группы. • блокирующая - возврат управления из этой функции гарантирует полное выполнение операции. Вызывающий процесс блокируется, пока операция не будет завершена. • неблокирующая функция - возврат из этой функции происходит немедленно, без ожидания окончания операции.
MPI (Message Passing Interface) Процедуры передачи сообщений в MPI Блокирующие функциии передачи – завершаются, когда все пересылаемые данные помещаются в буфер Блокирующие функции приема - завершаются, когда все данные из буфера помещены в адресное пространство принимающего процесса. Неблокирующие функции передачи и приема - инициализации соответствующих операций. Для опроса состояния операции и ее завершения используются дополнительные функции.
MPI (Message Passing Interface) Различные режимы выполнения передачи данных: Синхронный – передача заканчивается только тогда, когда прием инициализирован получателем. Функции нелокальные. Буфферизованный – передача заканчивается, когда все данные помещены в буфер. Локальная. Согласованный – передача начинается только, когда принимающей процесс установил признак готовности. Стандартный - выполняется независимо от приема ( помещается в системный буфер). Типы данных MPI: MPI_CHAR signed char MPI_SHORT signed short int MPI_INT signed int MPI_LONG signed long int MPI_UNSIGNED_CHAR unsigned char MPI_UNSIGNED_SHORT unsigned short int MPI_UNSIGNED unsigned int MPI_UNSIGNED_LONG unsigned long int MPI_FLOAT float MPI_DOUBLE double MPI_LONG_DOUBLE long double MPI_BYTE 8 binary digits MPI_PACKED data packed or unpacked with MPI_Pack()/ MPI_Unpack
MPI (Message Passing Interface) 1. Коммуникационные операции точка-точка Взаимодействие только двух процессов программы , один – отправитель, другой получатель. Отправителю нужен коммуникатор и номер получателя в коммуникаторе, получателю нужен только коммуникатор. Блокирующие: MPI_Send(buffer, count, type, dest, tag, comm) - блокирующая передача сообщения с идентификатором tag массива buffer длиной count типа type процессу dest в коммуникаторе comm. MPI_PROC_NULL несуществующий процесс – всегда успех операции. Не гарантируется что сообщение получено и даже, что отправлено. Блокировка обеспечивает безопасное изменение данных после вызова. В реализациях это может быть копирование в промежуточный буфер или непосредственная передача получателю. MPI_Bsend – блокирующая передача с буферизацией. Если прием не инициализирован, то сообщение пишется в специальный буфер, задаваемый MPI_Buffer_attach (*buffer, size) / MPI_Buffer_detach (*buffer, size) MPI_Ssend – блокирующая передача с синхронизацией. Завершается только, если прием будет инициализирован получателем. MPI_Rsend – блокирующая согласованная передача. Используется только, если получатель инициализировал прием, иначе поведение неопределено. Для инициализации приема функции синхронизации, например MPI_BARRIER
MPI (Message Passing Interface) MPI_Recv (*buf, count, datatype, src, tag, comm, *status) – блокирующий прием сообщения c идентификатором tag в буффер buf длиной count типа type от процесса src в коммуникаторе comm, атрибуты входящего сообщения пишутся в status. Можно использовать MPI_ANY_SOURCE и MPI_ANY_TAG. Блокировка обеспечивает принятие всех элементов сообщения в буфер. Узнать размер сообщения можно с помощью MPI_Probe (src, tag, comm, *status) - получение в status информации о сообщении int MPI_Get_count( status, datatype, count) – по status определяет число элементов Прием от одного и того же процесса в порядке отправки, от разных – порядок не определен Неблокирующие: Возврат из таких процедур происходит сразу, это по сути инициализации соответствующих операций, которые выполняются асинхронно. MPI_Isend (*buf, count, datatype, dest, tag, comm, *request) - неблокирующая передача сообщения с идентификатором tag из массива buffer count элементов типа type процессу dest в коммуникаторе comm. Буфер без получения дополнительной информации использовать нельзя, ее можно получить используя request и процедур MPI_WAIT и MPI_TEST
MPI (Message Passing Interface) MPI_Wait (*request, *status) – блокируется, пока не завершится операция c идентификатором request. По завершению request = MPI_REQUEST_NULL MPI_Waitall (count, *array_of_requests, *array_of_statuses) – ожидание завершения всех операций, задающихся массивом array_of_requests MPI_Waitany (count, *array_of_requests, *index, *status) – ожидание завершения хотя бы одной MPI_Waitsome (incount, *array_of_requests, *outcount, *array_of_indexes, *array_of_statuses) - ожидание завершения хотя бы одной с выводом результатов по всем операциям. MPI_Test (*request, *flag, *status), all, any, some – проверка завершилась или нет по флагу flag MPI_Irecv (*buf, count, datatype, source, tag, comm, *request) – неблокирующий прием сообщения c идентификатором tag в буфер buf count элементов типа type от процесса src в коммуникаторе comm, атрибуты входящего сообщения пишутся в status. Аналогично версии MPI_Ibsend, MPI_Issend, MPI_Irsend Отложенные операции: MPI_Send_Init и MPI_Start MPI_Sendrecv. Взаимный обмен данными между процессами.
MPI ( примеры) Блокировки ( Deadlock) Передача самому себе Обмен данными ( процессы 0 и 1 ждут друга ) MPI_Comm_rank(MPI_COMM_WORLD, &rank); if ( rank == 0 ) { MPI_Recv(buff, BUFSIZE, MPI_CHAR, MPI_Send(buff, BUFSIZE, MPI_CHAR, } else if ( rank == 1 ) { MPI_Recv(buff, BUFSIZE, MPI_CHAR, MPI_Send(buff, BUFSIZE, MPI_CHAR, } 1, TAG, MPI_COMM_WORLD, &stat); 1, TAG, MPI_COMM_WORLD); 0, TAG, MPI_COMM_WORLD, &stat); 0, TAG, MPI_COMM_WORLD); Поменять порядок Send<->Recv ? Как избавиться от блокировки? (семафор и иерархия ресурсов )
MPI: пример #define BUFSIZE 128 #define TAG 0 int main(int argc, char *argv[]) { char idstr[32]; char buff[BUFSIZE]; int numprocs, myid, int I; MPI_Status stat; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &numprocs); MPI_Comm_rank(MPI_COMM_WORLD, &myid); if(myid == 0) { printf("%d: We have %d processorsn", myid, numprocs); for(i=1; i<numprocs; i++) { sprintf(buff, "Hello %d! ", i); MPI_Send(buff, BUFSIZE, MPI_CHAR, i, TAG, MPI_COMM_WORLD); } for(i=1; i<numprocs; i++) { MPI_Recv(buff, BUFSIZE, MPI_CHAR, i, TAG, MPI_COMM_WORLD, &stat); printf("%d: %sn", myid, buff); } } else { /* receive from rank 0: */ MPI_Recv(buff, BUFSIZE, MPI_CHAR, 0, TAG, MPI_COMM_WORLD, &stat); sprintf(idstr, "Processor %d ", myid); strncat(buff, idstr, BUFSIZE-1); strncat(buff, "reporting for dutyn", BUFSIZE-1); /* send to rank 0: */ MPI_Send(buff, BUFSIZE, MPI_CHAR, 0, TAG, MPI_COMM_WORLD); } MPI_Finalize(); return 0; }
MPI: пример #include "mpi. h" #include <stdio. h> int main( int argc, char *argv) { int numtasks, rank, next, prev, buf[2], tag 1=1, tag 2=2; MPI_Request reqs[4]; MPI_Status stats[4]; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); MPI_Comm_rank(MPI_COMM_WORLD, &rank); prev = rank-1; next = rank+1; if (rank == 0) prev = numtasks - 1; if (rank == (numtasks - 1)) next = 0; MPI_Irecv(&buf[0], 1, MPI_INT, prev, tag 1, MPI_COMM_WORLD, &reqs[0]); MPI_Irecv(&buf[1], 1, MPI_INT, next, tag 2, MPI_COMM_WORLD, &reqs[1]); MPI_Isend(&rank, 1, MPI_INT, prev, tag 2, MPI_COMM_WORLD, &reqs[2]); MPI_Isend(&rank, 1, MPI_INT, next, tag 1, MPI_COMM_WORLD, &reqs[3]); MPI_Waitall(4, reqs, stats); MPI_Finalize(); }
MPI ( Задачи) Задачи 1. Коммуникация каждый с каждым, эстафета, сдвиг, master-slave 2. Обмен сообщениями между 2 процессами (пинг-понг), зависимость времени обмена от длины сообщения. Задаем максимальный размер сообщения и количество повторов измерений. MPI_Wtime () – возвращает астрономическое время в сек с некоторого момента. MPI_Wtick () – возвращает точность таймера в сек. MPI_Get_processor_name (*name, *resultlength) – возвращает имя процесса, на котором вызвана и его длину.
MPI (Message Passing Interface) Коллективные операции В операции участвуют все процессы коммуникатора. 1. Синхронизация всех процессов с помощью барьеров (MPI_Barrier) 2. Рассылка информации от одного процесса всем остальным членам некоторого коммуникатора (MPI_Bcast) 3. Сборка распределенного по процессам массива в один массив с сохранением его в адресном пространстве выделенного процесса (MPI_Gather, MPI_Gatherv) 4. Сборка распределенного массива в один массив с рассылкой его всем процессам некоторого коммуникатора (MPI_Allgather, MPI_Allgatherv) 5. Разбиение массива и рассылка его фрагментов всем процессам коммуникатора (MPI_Scatter, MPI_Scatterv) 6. Различные совмещенные операции Scatter/Gather (MPI_Alltoall, MPI_Alltoallv). 7. Простейшие вычислительные операции над данными, расположенными в адресных пространствах различных процессов и различными вариантами сохранение результата (MPI_Reduce, MPI_Allreduce, MPI_Reduce_scatter, MPI_Scan)
MPI (Message Passing Interface) • Создание производных типов данных для пересылки ( MPI_Type_contiguous, MPI_Type_vector, MPI_Type_struct. . . -> MPI_Type_commit -> MPI_Type_free) • Упаковка/распаковка данных при пересылке/получении ( MPI_Pack, MPI_Unpack) • Работа с группами и коммуникаторами MPI_Comm_dup, MPI_Comm_create, MPI_Comm_split - создание новых коммуникаторов MPI_Comm_test_inter – задает тип коммуникатора. MPI_Comm_compare – сравнение коммуникаторов. MPI_Comm_free – удаление коммуникатора. MPI_Comm_group – создание группы с помощью коммуникатора. MPI_Group_union, MPI_Group_intersection, MPI_Group_difference – теоретикомножественные операции над группами • Задание топологии процессов Декартова топология - процессы интерпретируются как узлы некоторой nмерной решетки Топологии графа - процессы интерпретируются как вершины некоторого графа; при этом связи между процессами определяются посредством задания набора ребер для этого графа.
MPI (Message Passing Interface) При наличии топологии можно выделять различные подмножества регулярной структуры ( сечения, подпространства и т. д. ) MPI_Cart_create – создание коммуникатора с декартовой топологией. MPI_Graph_create – создание коммуникатора с топологией графа. MPI_Cartdim_get – опрос числа измерений топологии. MPI_Cart_coords – определение координат процесса по его идентификатору. MPI_Topo_test – определение топологии коммуникатора (топология графа, декартова топология, топология не задана) MPI_Cart_sub – выделение подпространства в декартовой топологии. MPI_Graph_neighbors – определение непосредственных соседей данной вершины графа.
MPI_seminars.pptx