Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
Семинар 10
Стандарт MPI (часть 3)
Михаил Курносов
E-mail: mkurnosov@gmail.com
WWW: www.mkurnosov.net
Цикл семинаров «Основы параллельного программирования»
Институт физики полупроводников им. А. В. Ржанова СО РАН
Новосибирск, 2015 CC-BY
Коммуникационные режимы блокирующих обменов
 Стандартный режим (Standard communication mode, local/non-local) –
реализация определяет будет ли исходящее сообщение буферизовано:
a) сообщение помещается в буфер, вызов MPI_Send завершается до вызова
советующего MPI_Recv
b) буфер недоступен, вызов MPI_Send не завершится пока не будет вызван
соответствующий MPI_Recv (non-local)
 Режим с буферизацией (Buffered mode, local) – завершение MPI_Bsend не зависит
от того, вызван ли соответствующий MPI_Recv; исходящее сообщение помещается
в буфер, вызов MPI_Bsend завершается
 Синхронный режим (Synchronous mode, non-local + synchronization) – вызов MPI_Ssend
завершается если соответствующий вызова MPI_Recv начал прием сообщения
 Режим с передачей по готовности (Ready communication mode) – вызов MPI_Rsend
может начать передачу сообщения если соответствующий MPI_Recv уже вызван
(позволяет избежать процедуры “рукопожатия” для сокращения времени обмена)
Неблокирующие функции Send/recv (non-blocking)
 Возврат из функции происходит сразу после инициализации процесса
передачи/приема
 Буфер использовать нельзя до завершения операции
 Передача
 MPI_Isend(..., MPI_Request *request)
 MPI_Ibsend(..., MPI_Request *request)
 MPI_Issend(..., MPI_Request *request)
 MPI_Irsend(..., MPI_Request *request)
 Прием
 MPI_Irecv(..., MPI_Request *request)
Ожидание завершения неблокирующей операции
 Блокирующее ожидание завершения операции
 int MPI_Wait(MPI_Request *request, MPI_Status *status)
 int MPI_Waitany(int count, MPI_Request array_of_requests[], int *index,
MPI_Status *status)
 int MPI_Waitall(int count, MPI_Request array_of_requests[],
MPI_Status array_of_statuses[])
 Блокирующая проверка состояния операции
 int MPI_Test(MPI_Request *request, int *flag, MPI_Status *status)
 int MPI_Testany(int count, MPI_Request array_of_requests[], int *index,
int *flag, MPI_Status *status)
 int MPI_Testall(int count, MPI_Request array_of_requests[], int *flag,
MPI_Status array_of_statuses[])
Совмещение обменов и вычислений (overlaping)
Waiting Computations
MPI_Send
User code
MPI lib.
User code
MPI lib.
MPI_Wait
t
t
MPI_Isend MPI_Test
Использование блокирующих функций
Использование неблокирующих функций MPI_Isend(buf, count, MPI_INT, 1, 0,
MPI_COMM_WORLD, &req);
do {
//
// Вычисления (не использовать buf)
MPI_Test(&req, &flag, &status);
} while (!flag)
Ring example
 Двусторонние обмены (point-to-point communication)
✔
Один процесс инициирует передачу сообщения (send), другой его
принимает (receive)
✔
Изменение памяти принимающего процесса происходит при его явном
участии
✔
Обмен совмещен с синхронизацией процессов
 Односторонние обмены (one-sided communication, remote memory access)
✔
Только один процесс явно инициирует передачу/прием сообщения из
памяти удаленного процесса
✔
Синхронизация процессов отсутствует
Неблокирующая проверка сообщений
int MPI_Iprobe(int source, int tag, MPI_Comm comm, int *flag,
MPI_Status *status)
 В параметре flag возвращает значение 1, если сообщение с подходящими
атрибутами уже может быть прочитано и 0 в противном случае
 В параметре status возвращает информацию об обнаруженном сообщении
(если flag == 1)
Постоянные запросы (persistent)
 Постоянные функции привязывают аргументы к дескриптору запроса
(persistent request), дальнейшие вызовы операции осуществляется
по дескриптору запроса
 Позволяет сократить время выполнения запроса
 int MPI_Send_init(const void* buf, int count, MPI_Datatype datatype,
int dest, int tag, MPI_Comm comm, MPI_Request *request)
 int MPI_Recv_init(void* buf, int count, MPI_Datatype datatype, int source,
int tag, MPI_Comm comm, MPI_Request *request)
 Запуск операции (например, в цикле)
 int MPI_Start(MPI_Request *request)
 int MPI_Startall(int count, MPI_Request array_of_requests[])
Коллективные обмены (collective communications)
Трансляционный обмен (One-to-all)
 MPI_Bcast
 MPI_Scatter
 MPI_Scatterv
Коллекторный обмен (All-to-one)
 MPI_Gather
 MPI_Gatherv
 MPI_Reduce
Трансляционно-циклический обмен (All-to-all)
 MPI_Allgather
 MPI_Allgatherv
 MPI_Alltoall
 MPI_Alltoallv
 MPI_Allreduce
 MPI_Reduce_scatter
 Участвуют все
процессы коммуникатора
 Коллективная функция должна
быть вызвана каждым процессом
коммуникатора
 Коллективные и двусторонние
обмены в рамках одного
коммуникатора используют
различные контексты
MPI_Bcast
int MPI_Bcast(void *buf, int count, MPI_Datatype datatype,
int root, MPI_Comm comm)
Элементы
A
Элементы
A
A
A
A
MPI_Bcast
 MPI_Bcast – рассылка всем процессам сообщения buf
 Если номер процесса совпадает с root, то он отправитель, иначе – приемник
Рассылка всем
одинакового сообщения
ПроцессыПроцессы
Процессы
MPI_Scatter
int MPI_Scatter(void *sendbuf, int sendcnt, MPI_Datatype sendtype,
void *recvbuf, int recvcnt, MPI_Datatype recvtype,
int root, MPI_Comm comm)
Элементы
A0 A1 A2 A3
Элементы
A0
A1
A2
A3
MPI_Scatter
 Размер sendbuf = sizeof(sendtype) * sendcnt * commsize
 Размер recvbuf = sizeof(sendtype) * recvcnt
Рассылка всем
разных сообщений
Процессы
Процессы
MPI_Gather
int MPI_Gather(void *sendbuf, int sendcnt, MPI_Datatype sendtype,
void *recvbuf, int recvcount, MPI_Datatype recvtype,
int root, MPI_Comm comm)
Элементы
A0 A1 A2 A3
Элементы
A0
A1
A2
A3
MPI_Gather
 Размер sendbuf: sizeof(sendtype) * sendcnt
 Размер recvbuf: sizeof(sendtype) * sendcnt * commsize
Прием от всех
разных сообщений
Процессы
Процессы
MPI_Alltoall
int MPI_Alltoall(void *sendbuf, int sendcount, MPI_Datatype sendtype,
void *recvbuf, int recvcnt, MPI_Datatype recvtype,
MPI_Comm comm)
Элементы
A0 A1 A2 A3
B0 B1 B2 B3
C0 C1 C2 C3
D0 D1 D2 D3
Элементы
A0 B0 C0 D0
A1 B1 C1 D1
A2 B2 C2 D2
A3 B3 C3 D3
MPI_Alltoall
 Размер sendbuf: sizeof(sendtype) * sendcount * commsize
 Размер recvbuf: sizeof(recvtype) * recvcount * commsize
В каждом процессе
собираются сообщения
всех процессов
Процессы
Процессы
All-to-all
int MPI_Allgather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
void *recvbuf, int recvcount, MPI_Datatype recvtype,
MPI_Comm comm)
int MPI_Allgatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
void *recvbuf, int *recvcounts,
int *displs,
MPI_Datatype recvtype,
MPI_Comm comm)
int MPI_Allreduce(void *sendbuf, void *recvbuf,
int count, MPI_Datatype datatype,
MPI_Op op, MPI_Comm comm)
MPI_Reduce
int MPI_Reduce(void *sendbuf, void *recvbuf, int count,
MPI_Datatype datatype, MPI_Op op, int root,
MPI_Comm comm)
1 2 3 1 7
Rank 0 (root) Rank 1 Rank 2
+ + +
recvbuf
 Размер sendbuf: sizeof(datatype) * count
 Размер recvbuf: sizeof(datatype) * count
Формирование в процессе root массива значений,
полученных применением операции op
4 5 6 1 3 7 8 9 9 3
12 15 18 11 13
Операции MPI_Reduce
int MPI_Op_create(MPI_User_function *function,
int commute, MPI_Op *op)
 MPI_MAX
 MPI_MIN
 MPI_MAXLOC
 MPI_MINLOC
 MPI_SUM
 MPI_PROD
 MPI_LAND
 MPI_LOR
 MPI_LXOR
 MPI_BAND
 MPI_BOR
 MPI_BXOR
 Операция пользователя должна быть ассоциативной
A * (B * C) = (A * B) * C
 Если commute = 1, то операция коммутативная
A * B = B * A
Барьерная синхронизация
int MPI_Barrier(MPI_Comm comm)
 Блокирует работу процессов коммуникатора, вызвавших данную функцию,
до тех пор, пока все процессы не выполнят эту процедуру
Задание
 Разработать на MPI параллельную программу численного интегрирования
методом прямоугольников (семинар 2, пример 1_integrate)
 Провести анализ эффективности параллельной программы

More Related Content

Семинар 10. Параллельное программирование на MPI (часть 3)

  • 1. Семинар 10 Стандарт MPI (часть 3) Михаил Курносов E-mail: mkurnosov@gmail.com WWW: www.mkurnosov.net Цикл семинаров «Основы параллельного программирования» Институт физики полупроводников им. А. В. Ржанова СО РАН Новосибирск, 2015 CC-BY
  • 2. Коммуникационные режимы блокирующих обменов  Стандартный режим (Standard communication mode, local/non-local) – реализация определяет будет ли исходящее сообщение буферизовано: a) сообщение помещается в буфер, вызов MPI_Send завершается до вызова советующего MPI_Recv b) буфер недоступен, вызов MPI_Send не завершится пока не будет вызван соответствующий MPI_Recv (non-local)  Режим с буферизацией (Buffered mode, local) – завершение MPI_Bsend не зависит от того, вызван ли соответствующий MPI_Recv; исходящее сообщение помещается в буфер, вызов MPI_Bsend завершается  Синхронный режим (Synchronous mode, non-local + synchronization) – вызов MPI_Ssend завершается если соответствующий вызова MPI_Recv начал прием сообщения  Режим с передачей по готовности (Ready communication mode) – вызов MPI_Rsend может начать передачу сообщения если соответствующий MPI_Recv уже вызван (позволяет избежать процедуры “рукопожатия” для сокращения времени обмена)
  • 3. Неблокирующие функции Send/recv (non-blocking)  Возврат из функции происходит сразу после инициализации процесса передачи/приема  Буфер использовать нельзя до завершения операции  Передача  MPI_Isend(..., MPI_Request *request)  MPI_Ibsend(..., MPI_Request *request)  MPI_Issend(..., MPI_Request *request)  MPI_Irsend(..., MPI_Request *request)  Прием  MPI_Irecv(..., MPI_Request *request)
  • 4. Ожидание завершения неблокирующей операции  Блокирующее ожидание завершения операции  int MPI_Wait(MPI_Request *request, MPI_Status *status)  int MPI_Waitany(int count, MPI_Request array_of_requests[], int *index, MPI_Status *status)  int MPI_Waitall(int count, MPI_Request array_of_requests[], MPI_Status array_of_statuses[])  Блокирующая проверка состояния операции  int MPI_Test(MPI_Request *request, int *flag, MPI_Status *status)  int MPI_Testany(int count, MPI_Request array_of_requests[], int *index, int *flag, MPI_Status *status)  int MPI_Testall(int count, MPI_Request array_of_requests[], int *flag, MPI_Status array_of_statuses[])
  • 5. Совмещение обменов и вычислений (overlaping) Waiting Computations MPI_Send User code MPI lib. User code MPI lib. MPI_Wait t t MPI_Isend MPI_Test Использование блокирующих функций Использование неблокирующих функций MPI_Isend(buf, count, MPI_INT, 1, 0, MPI_COMM_WORLD, &req); do { // // Вычисления (не использовать buf) MPI_Test(&req, &flag, &status); } while (!flag)
  • 6. Ring example  Двусторонние обмены (point-to-point communication) ✔ Один процесс инициирует передачу сообщения (send), другой его принимает (receive) ✔ Изменение памяти принимающего процесса происходит при его явном участии ✔ Обмен совмещен с синхронизацией процессов  Односторонние обмены (one-sided communication, remote memory access) ✔ Только один процесс явно инициирует передачу/прием сообщения из памяти удаленного процесса ✔ Синхронизация процессов отсутствует
  • 7. Неблокирующая проверка сообщений int MPI_Iprobe(int source, int tag, MPI_Comm comm, int *flag, MPI_Status *status)  В параметре flag возвращает значение 1, если сообщение с подходящими атрибутами уже может быть прочитано и 0 в противном случае  В параметре status возвращает информацию об обнаруженном сообщении (если flag == 1)
  • 8. Постоянные запросы (persistent)  Постоянные функции привязывают аргументы к дескриптору запроса (persistent request), дальнейшие вызовы операции осуществляется по дескриптору запроса  Позволяет сократить время выполнения запроса  int MPI_Send_init(const void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request)  int MPI_Recv_init(void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request)  Запуск операции (например, в цикле)  int MPI_Start(MPI_Request *request)  int MPI_Startall(int count, MPI_Request array_of_requests[])
  • 9. Коллективные обмены (collective communications) Трансляционный обмен (One-to-all)  MPI_Bcast  MPI_Scatter  MPI_Scatterv Коллекторный обмен (All-to-one)  MPI_Gather  MPI_Gatherv  MPI_Reduce Трансляционно-циклический обмен (All-to-all)  MPI_Allgather  MPI_Allgatherv  MPI_Alltoall  MPI_Alltoallv  MPI_Allreduce  MPI_Reduce_scatter  Участвуют все процессы коммуникатора  Коллективная функция должна быть вызвана каждым процессом коммуникатора  Коллективные и двусторонние обмены в рамках одного коммуникатора используют различные контексты
  • 10. MPI_Bcast int MPI_Bcast(void *buf, int count, MPI_Datatype datatype, int root, MPI_Comm comm) Элементы A Элементы A A A A MPI_Bcast  MPI_Bcast – рассылка всем процессам сообщения buf  Если номер процесса совпадает с root, то он отправитель, иначе – приемник Рассылка всем одинакового сообщения ПроцессыПроцессы Процессы
  • 11. MPI_Scatter int MPI_Scatter(void *sendbuf, int sendcnt, MPI_Datatype sendtype, void *recvbuf, int recvcnt, MPI_Datatype recvtype, int root, MPI_Comm comm) Элементы A0 A1 A2 A3 Элементы A0 A1 A2 A3 MPI_Scatter  Размер sendbuf = sizeof(sendtype) * sendcnt * commsize  Размер recvbuf = sizeof(sendtype) * recvcnt Рассылка всем разных сообщений Процессы Процессы
  • 12. MPI_Gather int MPI_Gather(void *sendbuf, int sendcnt, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm) Элементы A0 A1 A2 A3 Элементы A0 A1 A2 A3 MPI_Gather  Размер sendbuf: sizeof(sendtype) * sendcnt  Размер recvbuf: sizeof(sendtype) * sendcnt * commsize Прием от всех разных сообщений Процессы Процессы
  • 13. MPI_Alltoall int MPI_Alltoall(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcnt, MPI_Datatype recvtype, MPI_Comm comm) Элементы A0 A1 A2 A3 B0 B1 B2 B3 C0 C1 C2 C3 D0 D1 D2 D3 Элементы A0 B0 C0 D0 A1 B1 C1 D1 A2 B2 C2 D2 A3 B3 C3 D3 MPI_Alltoall  Размер sendbuf: sizeof(sendtype) * sendcount * commsize  Размер recvbuf: sizeof(recvtype) * recvcount * commsize В каждом процессе собираются сообщения всех процессов Процессы Процессы
  • 14. All-to-all int MPI_Allgather(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm) int MPI_Allgatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int *recvcounts, int *displs, MPI_Datatype recvtype, MPI_Comm comm) int MPI_Allreduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
  • 15. MPI_Reduce int MPI_Reduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm) 1 2 3 1 7 Rank 0 (root) Rank 1 Rank 2 + + + recvbuf  Размер sendbuf: sizeof(datatype) * count  Размер recvbuf: sizeof(datatype) * count Формирование в процессе root массива значений, полученных применением операции op 4 5 6 1 3 7 8 9 9 3 12 15 18 11 13
  • 16. Операции MPI_Reduce int MPI_Op_create(MPI_User_function *function, int commute, MPI_Op *op)  MPI_MAX  MPI_MIN  MPI_MAXLOC  MPI_MINLOC  MPI_SUM  MPI_PROD  MPI_LAND  MPI_LOR  MPI_LXOR  MPI_BAND  MPI_BOR  MPI_BXOR  Операция пользователя должна быть ассоциативной A * (B * C) = (A * B) * C  Если commute = 1, то операция коммутативная A * B = B * A
  • 17. Барьерная синхронизация int MPI_Barrier(MPI_Comm comm)  Блокирует работу процессов коммуникатора, вызвавших данную функцию, до тех пор, пока все процессы не выполнят эту процедуру
  • 18. Задание  Разработать на MPI параллельную программу численного интегрирования методом прямоугольников (семинар 2, пример 1_integrate)  Провести анализ эффективности параллельной программы