Стандарт mpi (message passing interface)

76
Лекция 10: Стандарт MPI (MPI Message Passing Interface) Курносов Михаил Георгиевич к.т.н. доцент Кафедры вычислительных систем Сибирский государственный университет телекоммуникаций и информатики http://www.mkurnosov.net

Upload: mikhail-kurnosov

Post on 25-Dec-2014

510 views

Category:

Documents


0 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Стандарт MPI (Message Passing Interface)

Лекция 10:

Стандарт MPI

(MPI – Message Passing Interface)

Курносов Михаил Георгиевич

к.т.н. доцент Кафедры вычислительных систем

Сибирский государственный университет

телекоммуникаций и информатики

http://www.mkurnosov.net

Page 2: Стандарт MPI (Message Passing Interface)

Стандарт MPI

22

Message Passing Interface (MPI) – это стандарт

на программный интерфейс коммуникационных

библиотек для создания параллельных программ

в модели передачи сообщений (message passing)

Стандарт определяет интерфейс для языков

программирования C и Fortran

http://www.mpi-forum.org

1994

MPI 1.0

1995

MPI 1.1

1997

MPI 1.2, 2.0

2008

MPI 1.3, 2.1

2009

MPI 2.2 MPI 3.0

2012

http://www.mpi-forum.org/docs/mpi-3.0/mpi30-report.pdf

Page 3: Стандарт MPI (Message Passing Interface)

Реализации стандарт MPI (библиотеки)

33

MPICH2 (Open source, Argone NL)

http://www.mcs.anl.gov/research/projects/mpich2

MVAPICH2

IBM MPI

Cray MPI

Intel MPI

HP MPI

SiCortex MPI

Open MPI (Open source, BSD License)

http://www.open-mpi.org

Oracle MPI

Page 4: Стандарт MPI (Message Passing Interface)

Различия в реализациях стандарта MPI

44

Спектр поддерживаемых архитектур процессоров:

Intel, IBM, ARM, Fujitsu, NVIDIA, AMD

Типы поддерживаемых коммуникационных технологий/сетей:

InfiniBand, 10 Gigabit Ethernet, Cray Gemeni, IBM PERCS/5D torus,

Fujitsu Tofu, Myrinet, SCI

Реализованные протоколы дифференцированных обменов

(Point-to-point): хранение списка процессов, подтверждение

передачи (ACK), буферизация сообщений, …

Коллективные операции обменов информацией:

коммуникационная сложность алгоритмов, учет структуры

вычислительной системы (torus, fat tree, …), неблокирующие

коллективные обмены (MPI 3.0, методы хранение collective schedule)

Алгоритмы вложения графов программ в структуры

вычислительных систем (MPI topology mapping)

Возможность выполнения MPI-функций в многопоточной среде

и поддержка ускорителей (GPU NVIDIA/AMD, Intel Xeon Phi)

Page 5: Стандарт MPI (Message Passing Interface)

Стандарт MPI

55

Сеть InfiniBand (вычислительная сеть)

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Compute node 1 Compute node 2 Compute node 3 Compute node 4

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Frontend (login node)

Сеть Gigabit Ethernet (сервисная сеть: NFS, DNS, DHCP, ssh, …)

Пр

оц

есс

0

MPI_COMM_WORLD

Пр

оц

есс

1

Пр

оц

есс

4

Пр

оц

есс

5

Пр

оц

есс

3

Пр

оц

есс

2

Коммуникатор (communicator) – множество процессов,

образующих логическую область для выполнения

коллективных операций (обменов информацией и др.)

В рамках коммуникатора ветви имеют номера: 0, 1, …, n – 1

Page 6: Стандарт MPI (Message Passing Interface)

MPI: Hello World

6

#include <mpi.h>

int main(int argc, char *argv[]){

int rank, commsize;

MPI_Init(&argc, &argv);MPI_Comm_size(MPI_COMM_WORLD, &commsize);MPI_Comm_rank(MPI_COMM_WORLD, &rank);

printf(“Hello, World: process %d of %d\n”, rank, commsize);

MPI_Finalize();return 0;

}

6

Page 7: Стандарт MPI (Message Passing Interface)

Компиляция MPI-программ

77

Компиляция C-программы:

$ mpicc –o prog ./prog.c

Компиляция C++-программы:

$ mpicxx –o prog ./prog.cpp

Компиляция Fortran-программы:

$ mpif90 –o prog ./prog.f

Компиляция C-программы компилятором Intel C/C++:

$ mpicc –cc=icc –o prog ./prog.c

Page 8: Стандарт MPI (Message Passing Interface)

Запуск MPI-программ на кластере Jet

88

1. Формируем job-файл с ресурсным запросом (task.job):

#PBS –N MyTask

#PBS -l nodes=4:ppn=1 # 4 узла, 1 процесс на узел

#PBS -j oe

cd $PBS_O_WORKDIR

mpiexec ./prog

2. Ставим задачу в очередь системы пакетной обработки

заданий TORQUE

$ qsub task.job

7719.jetJob ID

Page 9: Стандарт MPI (Message Passing Interface)

Выполнение MPI-программ

99

Сеть InfiniBand (вычислительная сеть)

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Compute node 1 Compute node 2 Compute node 3 Compute node 4

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Frontend (login node)

Сеть Gigabit Ethernet (сервисная сеть: NFS, DNS, DHCP, ssh, …)П

ро

цес

с 0

MPI_COMM_WORLD

Пр

оц

есс

1

Пр

оц

есс

3

Пр

оц

есс

2

Система TORQUE запустит задачу, когда для нее будут

доступны ресурсы

В данном примере на каждом узле могут также присутствовать 3 процесса других задач (пользователей)

Page 10: Стандарт MPI (Message Passing Interface)

Состояние заданий в очереди TORQUE

1010

$ qstat

Job id Name User Time Use S Queue

------------- ---------------- --------------- -------- - -----

7732.jet simmc mkurnosov 00:00:00 C debug

7733.jet Heat2D mkurnosov 0 R debug

7734.jet simmc mkurnosov 00:00:00 C debug

7735.jet mpitask mkurnosov 00:00:00 C debug

7736.jet simmc mkurnosov 00:00:00 C debug

7737.jet mpitask mkurnosov 00:00:00 C debug

7738.jet Heat2D mkurnosov 0 R debug

Job state

C – completed R – running Q – waiting in queue

Page 11: Стандарт MPI (Message Passing Interface)

Формирование ресурсных запросов (Job)

1111

8 ветвей – все ветви на одном узле

#PBS -l nodes=1:ppn=8

6 ветвей – две ветви на каждом узле

#PBS -l nodes=3:ppn=2

Команды управления задачами в очереди

o qdel – удаление задачи из очереди

o qstat – состояние очереди

o pbsnodes – состояние вычислительных узлов

Page 12: Стандарт MPI (Message Passing Interface)

Стандарт MPI

1212

Двусторонние обмены (Point-to-point communication)

Составные типы данных (Derived datatypes)

Коллективные обмены (Collective communication)

Группы процессов, коммуникаторы

(Groups, communicators)

Виртуальные топологии процессов

Управление средой выполнения

(Environmental management)

Управление процессами (Process management)

Односторонние обмены (One-sided communication)

Файловый ввод-вывод (I/O)

Page 13: Стандарт MPI (Message Passing Interface)

Двусторонние обмены (Point-to-point)

1313

Двусторонний обмен (Point-to-point communication) –

это обмен сообщением между двумя процессами:

один инициирует передачу (send), а другой – получение

сообщения (receive)

Каждое сообщение снабжается конвертом (envelope):

− номер процесса отправителя (source)

− номер процесса получателя (destination)

− тег сообщения (tag)

− коммуникатор (communicator)

Page 14: Стандарт MPI (Message Passing Interface)

Постоянные (Persistent)

MPI_Bsend_init MPI_Recv_init MPI_Send_init ... MPI_Start MPI_Startall

Двусторонние обмены (Point-to-point)

1414

Блокирующие (Blocking)

MPI_Bsend MPI_Recv MPI_Rsend MPI_Send MPI_Sendrecv MPI_Sendrecv_replace MPI_Ssend ...

Неблокирующие(Non-blocking)

MPI_Ibsend MPI_Irecv MPI_Irsend MPI_Isend MPI_Issend ...

Проверки состояния запросов (Completion/Testing)

MPI_Iprobe MPI_Probe MPI_Test{, all, any, some} MPI_Wait{, all, any, some} ...

Page 15: Стандарт MPI (Message Passing Interface)

MPI_Send/MPI_Recv

1515

int MPI_Send(void *buf,

int count,

MPI_Datatype datatype,

int dest,

int tag,

MPI_Comm comm)

buf – указатель на буфер с информацией

count – количество передаваемых элементов типа datatype

dest – номер процесса получателя сообщения

tag – тег сообщения

int MPI_Recv(void *buf, int count,

MPI_Datatype datatype,

int source, int tag,

MPI_Comm comm, MPI_Status *status)

Page 16: Стандарт MPI (Message Passing Interface)

int main(int argc, char **argv){

int rank;MPI_Status status;

MPI_Init(&argc, &argv);MPI_Comm_rank(MPI_COMM_WORLD, &rank);

if (rank == 0)MPI_Send(buf, BUFSIZE, MPI_DOUBLE, 1, 1,

MPI_COMM_WORLD);else

MPI_Recv(buf, BUFSIZE, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD, &status);

MPI_Finalize();return 0;

}

Пример MPI_Send/MPI_Recv

1616

Page 17: Стандарт MPI (Message Passing Interface)

int main(int argc, char **argv){

int rank;MPI_Status status;

MPI_Init(&argc, &argv);MPI_Comm_rank(MPI_COMM_WORLD, &rank);

if (rank == 0)MPI_Send(buf, BUFSIZE, MPI_DOUBLE, 1, 1,

MPI_COMM_WORLD);else

MPI_Recv(buf, BUFSIZE, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD, &status);

MPI_Finalize();return 0;

}

Пример MPI_Send/MPI_Recv

1717

Infinite waiting(if commsize > 2)

Page 18: Стандарт MPI (Message Passing Interface)

Бесконечное ожидание (commsize = 3)

1818

Сеть InfiniBand (вычислительная сеть)

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Compute node 1 Compute node 2 Compute node 3 Compute node 4

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Frontend (login node)

Сеть Gigabit Ethernet (сервисная сеть: NFS, DNS, DHCP, ssh, …)

Пр

оц

есс

0

Пр

оц

есс

1

Пр

оц

есс

2

MPI_Send MPI_Recv MPI_Recv

waiting for

a message

Нет парного MPI_Send

Page 19: Стандарт MPI (Message Passing Interface)

int main(int argc, char **argv){

int rank;MPI_Status status;

MPI_Init(&argc, &argv);MPI_Comm_rank(MPI_COMM_WORLD, &rank);

if (rank == 0)MPI_Send(buf, BUFSIZE, MPI_DOUBLE, 1, 1,

MPI_COMM_WORLD);else if (rank == 1)

MPI_Recv(buf, BUFSIZE, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD, &status);

MPI_Finalize();return 0;

}

Пример MPI_Send/MPI_Recv

1919

Page 20: Стандарт MPI (Message Passing Interface)

Режимы передачи сообщений

2020

Standard (MPI_Send) – библиотека сама принимает

решение буферизовать сообщение и сразу выходить

из функции или дожидаться окончания передачи данных

получателю (например, если нет свободного буфера)

Buffered (MPI_Bsend) – отправляемое сообщение

помещается в буфер и функция завершает свою работу.

Сообщение будет отправлено библиотекой.

Synchronous (MPI_Ssend) – функция завершает своё

выполнение когда процесс-получатель вызвал MPI_Recv

и начал копировать сообщение. После вызова функции

можно безопасно использовать буфер.

Ready (MPI_Rsend) – функция успешно выполняется только

если процесс-получатель уже вызвал функцию MPI_Recv

Page 21: Стандарт MPI (Message Passing Interface)

int MPI_Isend(const void *buf, int count, MPI_Datatype datatype, int dest,int tag, MPI_Comm comm, MPI_Request *request)

Неблокирующие двусторонние обмены

2121

Неблокирующие передача/прием сообщений

(Nonblocking point-to-point communication) –

операция, выход из которой осуществляется не дожидаясь

завершения передачи информации

Пользователю возвращается дескриптор запроса (request),

который он может использовать для проверки состояния

операции

Цель – обеспечить возможность совмещения вычислений

и обменов информацией (Overlap computations &

communications)

Page 22: Стандарт MPI (Message Passing Interface)

Network offload

2222

Высокопроизводительные сетевые контроллеры аппаратурно реализуют

часть функций сетевого стека => низкая латентность передачи

сообщений, совмещение обменов и вычислений

MPI

TCP/UDP

IP

Операционная

система

MAC

PHY

Сетевой

интерфейс

MPI

Операционная система

MAC

PHY

TOE

сетевой

интерфейс

TCP/UDP

IP

Page 23: Стандарт MPI (Message Passing Interface)

InfiniBand aware MPI

2323http://www.mn.uio.no/astro/english/services/it/help/programming/mpi.html

Page 24: Стандарт MPI (Message Passing Interface)

Неблокирующие двусторонние обмены

2424

int MPI_Wait(MPI_Request *request,

MPI_Status *status)

Блокирует выполнение процесса пока не закончится

операция, ассоциированная с запросом request

int MPI_Test(MPI_Request *request, int *flag,

MPI_Status *status)

Возвращает flag = 1 если операция, ассоциированная

с запросом request, завершена

Page 25: Стандарт MPI (Message Passing Interface)

Совмещение обменов и вычислений

2525

MPI_Isend(buf, count, MPI_INT, 1, 0,

MPI_COMM_WORLD, &req);

do {

//

// Вычисления ... (не использовать buf)

//

MPI_Test(&req, &flag, &status);

} while (!flag)

Page 26: Стандарт MPI (Message Passing Interface)

Неблокирующие двусторонние обмены

2626

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_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[])

Page 27: Стандарт MPI (Message Passing Interface)

Типы данных MPI (Datatypes)

27

MPI_PACKED 1

MPI_BYTE 1

MPI_CHAR 1

MPI_UNSIGNED_CHAR 1

MPI_SIGNED_CHAR 1

MPI_WCHAR 2

MPI_SHORT 2

MPI_UNSIGNED_SHORT 2

MPI_INT 4

MPI_UNSIGNED 4

MPI_LONG 4

MPI_UNSIGNED_LONG 4

MPI_FLOAT 4

MPI_DOUBLE 8

MPI_LONG_DOUBLE 16

MPI_CHARACTER 1

MPI_LOGICAL 4

MPI_INTEGER 4

MPI_REAL 4

MPI_DOUBLE_PRECISION 8

MPI_COMPLEX 2*4

MPI_DOUBLE_COMPLEX 2*8

В MPI имеется возможность создавать пользовательские

типы данных (Derived Datatypes, структуры, части массивов)27

Page 28: Стандарт MPI (Message Passing Interface)

Коллективные обмены (блокирующие)

2828

Трансляционный обмен (One-to-all)

o MPI_Bcast

o MPI_Scatter

o MPI_Scatterv

Коллекторный обмен (All-to-one)

o MPI_Gather

o MPI_Gatherv

o MPI_Reduce

Трансляционно-циклический обмен (All-to-all)

o MPI_Allgather

o MPI_Allgatherv

o MPI_Alltoall

o MPI_Alltoallv

o MPI_Allreduce

o MPI_Reduce_scatter

Page 29: Стандарт MPI (Message Passing Interface)

MPI_Bcast (One-to-all broadcast)

2929

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, то он отправитель, иначе – приемник

Рассылка всемодинакового сообщения

Page 30: Стандарт MPI (Message Passing Interface)

int main(int argc, char *argv[]){

double buf[n];MPI_Init(&argc,&argv);

/* Code */

// Передать массив buf всем процессам (и себе)MPI_Bcast(&buf, n, MPI_DOUBLE, 0, MPI_COMM_WORLD);

MPI_Finalize();return 0;

}

MPI_Bcast (One-to-all broadcast)

3030

int MPI_Bcast(void *buf, int count,

MPI_Datatype datatype,

int root, MPI_Comm comm)

Page 31: Стандарт MPI (Message Passing Interface)

MPI_Scatter (One-to-all broadcast)

3131

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

Рассылка всем разных сообщений

Page 32: Стандарт MPI (Message Passing Interface)

MPI_Gather (All-to-one)

3232

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

Прием от всех разных сообщений

Page 33: Стандарт MPI (Message Passing Interface)

MPI_Reduce (All-to-one)

33

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 33

Формирование в процессе root массива значений, полученных применением

операции op

4 5 6 1 3 7 8 9 9 3

12 15 18 11 13

Page 34: Стандарт MPI (Message Passing Interface)

Операции MPI_Reduce

3434

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

Page 35: Стандарт MPI (Message Passing Interface)

Пользовательская операция MPI_Reduce

35

typedef struct {double real, imag;

} Complex;

Complex sbuf[100], rbuf[100];MPI_Op complexmulop;MPI_Datatype ctype;

MPI_Type_contiguous(2, MPI_DOUBLE, &ctype);MPI_Type_commit(&ctype);

// Умножение комплексных чиселMPI_Op_create(complex_mul, 1, &complexmulop);

MPI_Reduce(sbuf, rbuf, 100, ctype, complexmulop,root, comm);

MPI_Op_free(&complexmulop);MPI_Type_free(&ctype);

35

Page 36: Стандарт MPI (Message Passing Interface)

Пользовательская операция MPI_Reduce

36

// Умножение массивов комплексных чиселvoid complex_mul(void *inv, void *inoutv, int *len,

MPI_Datatype *datatype){

int i;Complex c;Complex *in = (Complex *)inv;

*inout = (Complex *)inoutv;

for (i = 0; i < *len; i++) {c.real = inout->real * in->real -

inout->imag * in->imag;c.imag = inout->real * in->imag +

inout->imag * in->real;*inout = c;in++; inout++;

}}

36

Page 37: Стандарт MPI (Message Passing Interface)

MPI_Alltoall

3737

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

В каждом процессе собираются сообщения

всех процессов

Page 38: Стандарт MPI (Message Passing Interface)

MPI_Barrier

3838

int MPI_Barrier(MPI_Comm comm)

Барьерная синхронизация процессов – ни один процесс

не завершит выполнение этой функции пока все не

войдут в неё

int main(int argc, char *argv[]){

/* Code */

MPI_Barrier(MPI_COMM_WORLD);

/* Code */

MPI_Finalize();return 0;

}

Page 39: Стандарт MPI (Message Passing Interface)

All-to-all

39

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)39

Page 40: Стандарт MPI (Message Passing Interface)

Реализация коллективных операций

4040

Аппаратная реализация коллективных операций –

специализированные коммуникационные сети:

IBM BlueGene/P Tree network, barrier network

Программная реализация – коллективная операция

реализуется на основе операций Send/Recv

Программная реализация коллективных операций имеет

наибольшее распространение (MPICH2, Open MPI)

Page 41: Стандарт MPI (Message Passing Interface)

Алгоритмы коллективных операций

4141

One-to-all Broadcast (MPI_Bcast, MPI_Scatter)

Алгоритм биномиального дерева (Binomial tree)

Scatter + Allgather

All-to-one Broadcast (MPI_Reduce, MPI_Gather):

Алгоритм биномиального дерева

Reduce_Scatter + Gather

All-to-all Broadcast

(MPI_Allgather, MPI_Allreduce)

Алгоритм рекурсивного

сдваивания (Recursive doubling)

Алгоритм Дж. Брука

(J. Bruck, 1997)

MPI_Recv MPI_Recv

MPI_Send

MPI_Recv

MPI_Send

MPI_Recv

MPI_Send

MPI_Send

MPI_Send

0

1

2

3

4

5

MPI_Recv

t

a1

а2 + a3

a4 + а5

a3

a5

а0 + a1 а0 + a1 + а2 + a3 а0 + … + a5

Диаграмма выполнения операции MPI_Reduce

алгоритмом биномиального дерева

(суммирование элементов 6 ветвей)

Page 42: Стандарт MPI (Message Passing Interface)

int MPIR_Allgather_intra(...){

// ...tot_bytes = (MPI_Aint)recvcount * comm_size * type_size;if ((tot_bytes < MPIR_PARAM_ALLGATHER_LONG_MSG_SIZE) &&

!(comm_size & (comm_size - 1))) {/* Short or medium size message and power-of-two no.

of processes. Use recursive doubling algorithm */ // ...

else if (tot_bytes < MPIR_PARAM_ALLGATHER_SHORT_MSG_SIZE) {/* Short message and non-power-of-two no. of processes.

Use Bruck algorithm (see description above). */// ...

else { /* Long message or medium-size message and non-power-of-two

no. of processes. Use ring algorithm. */// ...

}}

Реализация коллективных операций

4242

Как правило, для каждой коллективной операции имеется несколько

алгоритмов ее реализации – выбор алгоритма основан на эвристике

mpich2-3.0.4

Page 43: Стандарт MPI (Message Passing Interface)

Выбор алгоритма коллективной операции

4343

Как динамически (во время вызова функции)

выбирать алгоритм реализации коллективной

операции?

Учитывать только размер сообщения?

Такой выбор будет оптимальным только для той системы,

на которой провели предварительные замеры времени

выполнения операций (MPICH2, Open MPI)

Использовать данные предварительных замеров

времени выполнения алгоритмов (при установке

библиотеки на вычислительную систему)?

Оценивать время выполнения алгоритма на модели

(LogP, LogGP, PLogP, …)?

Page 44: Стандарт MPI (Message Passing Interface)

Алгоритмы реализации MPI_Allgather

4444

0

1

2

3 a3 a1

a0

a2

0

1

2

3 a2 a3 a0 a1

a0 a3

a1 a2

0

1

2

3a0 a1 a2 a3 a0 a1 a2 a3

a0 a1 a2 a3

a0 a1 a2 a3

1

0

2

3 a1 a2 a3 a0 a1 a3

a0 a2 a3

a0 a1 a2

Кольцевой алгоритм (ring)

Каждая ветвь выполняет 2(n – 1) обменов (Send/Recv)

Page 45: Стандарт MPI (Message Passing Interface)

Алгоритмы реализации MPI_Allgather

4545

a0

0 1 2 3

4 5 6 7

a1

a3

a2

a4

a5

a7

a6

a0

0 1 2 3

4 5 6 7

a1

a3

a2

a4

a5

a7

a6

a1

a0

a2

a3

a4

a5

a6

a7

a0

0 1 2 3

4 5 6 7

a1

a3

a2

a4

a5

a7

a6

a1

a0

a2

a3

a4

a5

a6

a7

a2

a3

a0

a1 a1

a0

a3

a2

a4

a5

a4

a5

a6

a7

a6

a7

a0

0 1 2 3

4 5 6 7

a1

a3

a2

a4

a5

a7

a6

a1

a0

a2

a3

a4

a5

a6

a7

a2

a3

a0

a1 a1

a0

a3

a2

a4

a5

a4

a5

a6

a7

a6

a7

a0

a1

a2

a3

a0

a1

a2

a3

a0

a1

a2

a3

a0

a1

a2

a3

a4

a5

a6

a7

a4

a5

a6

a7

a4

a5

a6

a7

a4

a5

a6

a7

a0

0 1 2 3

4 5 6 7

a1

a3

a2

a4

a5

a7

a6

a0

0 1 2 3

4 5 6 7

a1

a3

a2

a4

a5

a7

a6

a1 a3a2 a4 a5 a7a6 a0

a0

0 1 2 3

4 5 6 7

a1

a3

a2

a4

a5

a7

a6

a1 a3a2 a4 a5 a7a6 a0

a2

a3

a3a2 a4 a5 a7a6 a0 a1

a4 a5 a7a6 a0 a1 a2

a0

0 1 2 3

4 5 6 7

a1

a3

a2

a4

a5

a7

a6

a1 a3a2 a4 a5 a7a6 a0

a2

a3

a3a2 a4 a5 a7a6 a0 a1

a4 a5 a7a6 a0 a1 a2

a4 a5 a7a6 a0 a1 a2

a5 a7a6 a0 a1 a2

a7a6 a0 a1 a2

a7 a0 a1 a2

a3

a4

a5

a6

a3

a4

a5

a3

a4a3

a0

0 1 2 3

4 5 6 7

a1

a3

a2

a4

a5

a7

a6

a1

a0

a2

a3

a4

a5

a6

a7

a2

a3

a0

a1 a1

a0

a3

a2

a4

a5

a4

a5

a6

a7

a6

a7

a0

a1

a2

a3

a0

a1

a2

a3

a0

a1

a2

a3

a0

a1

a2

a3

a4

a5

a6

a7

a4

a5

a6

a7

a4

a5

a6

a7

a4

a5

a6

a7

Алгоритм рекурсивного сдваивания (recursive doubling)

Алгоритм Дж. Брука(J. Bruck et al., 1997)

На каждом шаге размер передаваемого блока удваивается: m, 2m, 4m

Количество обменов: 2log2n Количество обменов: 2log2n

Только для n равного степени двойки На шаге k ветвь i взаимодействует с ветвями (i – 2k + n) mod n

и (i + 2k) mod n

Page 46: Стандарт MPI (Message Passing Interface)

Таймер

4646

double MPI_Wtime()

int main(int argc, char **argv){

double t = 0.0

t -= MPI_Wtime();/* Code */ t += MPI_Wtime();

printf(“Elapsed time: %.6f seconds\n", t); }

Page 47: Стандарт MPI (Message Passing Interface)

Неблокирующие коллективные операции

4747

Неблокирующий коллективный обмен

(Non-blocking collective communication) –

коллективная операция, выход из которой осуществляется

не дожидаясь завершения операций обменов

Пользователю возвращается дескриптор запроса (request),

который он может использовать для проверки состояния

операции

Цель – обеспечить возможность совмещения вычислений

и обменов информацией

int MPI_Ibcast(void *buf, int count,

MPI_Datatype datatype,

int root, MPI_Comm comm,

MPI_Request *request)

MPI 3.0

Page 48: Стандарт MPI (Message Passing Interface)

MPI_Ibcast

4848

MPI_Request req;

MPI_Ibcast(buf, count, MPI_INT, 0,

MPI_COMM_WORLD, &req);

while (!flag) {

// Вычисления...

// Проверяем состояние операции

MPI_Test(&req, &flag, MPI_STATUS_IGNORE);

}

MPI_Wait(&req, MPI_STATUS_IGNORE);

MPI 3.0

Page 49: Стандарт MPI (Message Passing Interface)

Non-blocking MPI Collectives

4949

MPI 3.0

Waiting Computations

MPI_Bcast

User code

MPI lib.

User code

MPI lib. MPI_Ibcast

Computations

MPI_Wait

Блокирующие коллективные операции (Blocking MPI Collectives)

t

t

Неблокирующие коллективные операции (Non-blocking collectives)

tcomptinittwait

tblocking

toverlap

Page 50: Стандарт MPI (Message Passing Interface)

Non-blocking MPI Collectives

5050

MPI 3.0

Waiting Computations

MPI_Bcast

User code

MPI lib.

User code

MPI lib. MPI_Ibcast

Computations

MPI_Wait

Блокирующие коллективные операции

(Blocking MPI Collectives)

t

t

Неблокирующие коллективные операции

(Non-blocking collectives)

tcomptinittwait

tblocking

toverlap

Коэффициент 𝜶 совмещения вычисления и обменов информацией

𝜶 = 𝟏 −𝒕𝒐𝒗𝒆𝒓𝒍𝒂𝒑 − 𝒕𝒄𝒐𝒎𝒑

𝒕𝒃𝒍𝒐𝒄𝒌𝒊𝒏𝒈

Page 51: Стандарт MPI (Message Passing Interface)

MPI_Request req;

MPI_Ibcast(buf, count, MPI_INT, 0, MPI_COMM_WORLD, &req);

while (!flag) {

// Вычисления...

// Проверяем состояние и продвигаем обмены по расписанию

MPI_Test(&req, &flag, MPI_STATUS_IGNORE);

}

MPI_Wait(&req, MPI_STATUS_IGNORE);

Неблокирующие коллективные операции

5151

При вызове неблокирующией коллективной операции

создается расписание выполнения обменов

(collective schedule)

Progress engine – механизм, который в фоновом режиме

реализует обмены по созданному расписанию – как правило

обмены выполняются при вызове MPI_Test (в противном

случае необходим дополнительный поток)

Page 52: Стандарт MPI (Message Passing Interface)

Вычисление числа π

5252

0,00

0,50

1,00

1,50

2,00

2,50

3,00

3,50

4,00

4,50

0,00 0,10 0,20 0,30 0,40 0,50 0,60 0,70 0,80 0,90

𝜋 =

0

14

1 + 𝑥2𝑑𝑥 𝜋 ≈ ℎ

𝑖=1

𝑛4

1 + (ℎ(𝑖 − 0.5))2

ℎ =1

𝑛

Page 53: Стандарт MPI (Message Passing Interface)

Вычисление числа π (sequential version)

5353

int main()

{

int i, nsteps = 1000000;

double step = 1.0 / (double)nsteps;

double pi, x, sum = 0.0;

for (i = 1; i <= nsteps; i++) {

x = step * ((double)i - 0.5);

sum += 4.0 / (1.0 + x * x);

}

pi = step * sum;

printf(“PI = %.16f\n”, pi);

return 0;

}

Page 54: Стандарт MPI (Message Passing Interface)

Вычисление числа π (parallel version)

5454

int main(int argc, char *argv[])

{

int i, rank, commsize, nsteps = 1000000;

double step, local_pi, pi, x, sum = 0.0;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &commsize);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

// Передаем все количество шагов интегрирования

MPI_Bcast(&nsteps, 1, MPI_INT, 0,

MPI_COMM_WORLD);

step = 1.0 / (double)nsteps;

Page 55: Стандарт MPI (Message Passing Interface)

// Процесс rank получает точки x:

// rank + 1, rank + 1 + p, rank + 1 + 2p, …

for (i = rank + 1; i <= nsteps; i += commsize) {

x = step * ((double)i - 0.5);

sum += 4.0 / (1.0 + x * x);

}

local_pi = step * sum;

// Формируем результирующую сумму

MPI_Reduce(&local_pi, &pi, 1, MPI_DOUBLE,

MPI_SUM, 0, MPI_COMM_WORLD);

if (rank == 0)

printf(“PI = %.16f\n”, pi);

MPI_Finalize();

return 0;

}

Вычисление числа π (parallel code)

5555

Page 56: Стандарт MPI (Message Passing Interface)

Эффективность параллельных программ

5656

Коэффициент S ускорения параллельной

программы (Speedup)

𝑆 =𝑇1𝑇𝑛,

где:

T1 – время выполнения последовательной программы,

Tn – время выполнения параллельной программы на n

процессорных ядрах (n процессов)

Коэффициент E эффективности параллельной

программы

𝐸 =𝑆

𝑛=𝑇1𝑛𝑇𝑛

Page 57: Стандарт MPI (Message Passing Interface)

Эффективность программы π

5757

0

2

4

6

8

10

12

14

16

1 2 4 8 16

S

n

n = 107

Linear

Зависимость коэффициента ускорения S

от числа n процессорных ядер

(вычислительные узлы: 2 x Intel Xeon E5420, коммуникационная

сеть Gigabit Ethernet; MPICH2 1.4.1p1, GCC 4.4.6;

на каждом вычислительном узле 1 процесс)

Page 58: Стандарт MPI (Message Passing Interface)

Heat 2D

5858[*] Blaise Barney. Introduction to Parallel Computing (LLNL)

Уравнение теплопроводности

описывает изменение температуры

в заданной области с течением

времени

Приближенное решение можно

найти методом конечных разностей

Область покрывается сеткой

Производные аппроксимируются

конечными разностями

Известна температура на границе

области в начальный момент времени

Page 59: Стандарт MPI (Message Passing Interface)

do iy = 2, ny - 1

do ix = 2, nx - 1

u2(ix, iy) = u1(ix, iy) +

cx * (u1(ix + 1, iy) +

u1(ix - 1, iy) – 2.0 * u1(ix, iy)) +

cy * (u1(ix, iy + 1) +

u1(ix, iy - 1) – 2.0 * u1(ix, iy))

end do

end do

Heat 2D (serial code)

5959[*] Blaise Barney. Introduction to Parallel Computing (LLNL)

Температура хранится в двумерном массиве – расчетная

область

Page 60: Стандарт MPI (Message Passing Interface)

Heat 2D (parallel version)

6060[*] Blaise Barney. Introduction to Parallel Computing (LLNL)

Каждый процесс будет обрабатывать свою часть области

for t = 1 to nsteps

1. Update time

2. Send neighbors my border

3. Receive from neighbors

4. Update my cells

end for

Расчетная область разбита на вертикальные полосы –

массив распределен

Page 61: Стандарт MPI (Message Passing Interface)

Wave Equation

6161[*] Blaise Barney. Introduction to Parallel Computing (LLNL)

A(i, t + 1) = 2.0 * A(i, t) - A(i, t - 1) +

c * (A(i - 1, t) - (2.0 * A(i, t) +

A(i + 1, t))

Page 62: Стандарт MPI (Message Passing Interface)

Wave Equation (data decomposition)

6262[*] Blaise Barney. Introduction to Parallel Computing (LLNL)

A(i, t + 1) = 2.0 * A(i, t) - A(i, t - 1) +

c * (A(i - 1, t) - (2.0 * A(i, t) +

A(i + 1, t))

Расчетная область разбита на вертикальные полосы –массив распределен (одномерное разбиение)

Page 63: Стандарт MPI (Message Passing Interface)

Intel Trace Analyzer and Collector

6363

Intel Trace Analyzer & Collector – профилировщик для

MPI-программ, показывает timeline с обменами между процессами,

статистику по переданным сообщениям; позволяет находить

дисбаланс загрузки процессов

Page 64: Стандарт MPI (Message Passing Interface)

Профилировщики MPI

6464

Intel Trace Analyzer & Collector

mpiP

VamirTrace + Vampir

Tau

Allinea MAP

MPICH2 MPE (Jumpshot)

Oracle Solaris Studio (collect)

Page 65: Стандарт MPI (Message Passing Interface)

Интерфейс профилирования PMPI

6565

Каждая функция MPI имеет 2 версии:

MPI_Function

PMPI_Function

Функции с именами MPI_Function можно перехватывать

– подменять функциями врапперами (wrapper) с такими

же именами

Во врапперах осуществляется регистрация времени

выполнения, собирается статистика по размерам

сообщения и пр.

Из враппера вызывается оригинальная MPI-функция

PMPI_Function

Page 66: Стандарт MPI (Message Passing Interface)

static int totalBytes = 0;

static double totalTime = 0.0;

// Wrapper for Send

int MPI_Send(const void* buffer, int count,

MPI_Datatype datatype, int dest, int tag,

MPI_Comm comm)

{

double tstart = MPI_Wtime();

int extent;

// Call original (real) send

int rc = PMPI_Send(buffer, count, datatype, dest,

tag, comm);

totalTime += MPI_Wtime() - tstart;

MPI_Type_size(datatype, &extent); /* Message size */

totalBytes += count * extent;

return rc;

}

sendprof.c

6666

Page 67: Стандарт MPI (Message Passing Interface)

$ mpicc –c –o sendprof.o ./sendprof.c

$ ar rcs libsendprof.a sendprof.o

$ mpicc –o mpiprog ./mpiprog.c \

–L. -lsendprof

Использование sendprof.c

6767

Какие функции перехватывать?

MPI_Initialize(), MPI_Init_threads() –

инициализируем профилировщик

MPI_Finalize() – вывод отчета

MPI_Pcontrol() – связь профилировщика

с пользовательской программой

Если необходимо профилировать Fortran-программы,

то имена врапперов должны соответствовать правилам Fortran

(нет указателей, преобразование констант Fortran -> C, …)

Page 68: Стандарт MPI (Message Passing Interface)

MPI Process mapping

6868

Сеть InfiniBand (вычислительная сеть)

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Compute node 1 Compute node 2 Compute node 3 Compute node 4

Общая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Frontend (login node)

Сеть Gigabit Ethernet (сервисная сеть: NFS, DNS, DHCP, ssh, …)П

ро

цес

с 0

Пр

оц

есс

1

Пр

оц

есс

3

Пр

оц

есс

2

Время выполнения обменов зависит от того как процессы размещены

по процессорным ядрами (process mapping/pining, task mapping, task

allocation, task assignment)

Распределение процессов задается при старте программы (mpiexec)

или при формировании виртуальной топологии (MPI Virtual topolgy)

Page 69: Стандарт MPI (Message Passing Interface)

Пример вложения программы в ВС

6969

Вложение теста High Performance Linpack в подсистему:

5

1

6 7 8

2 3 4

High Performance Linpack (HPL)

Вычислительный кластер

с иерархической структурой

(2 узла по 2 Intel Xeon 5150)

Сеть связи Gigabit Ethernet

Общая память

Ядро Ядро

Кэш L2

Процессор

Ядро Ядро

Кэш L2

Процессор

Общая память

Ядро Ядро

Кэш L2

Процессор

Ядро Ядро

Кэш L2

Процессор

Граф программы

Page 70: Стандарт MPI (Message Passing Interface)

Пример вложения программы в ВС

7070

1 2 3 4 5 6 7 8

Вложение теста High Performance Linpack в подсистему:

5

1

6 7 8

2 3 4

High Performance Linpack (HPL)

Вычислительный кластер

с иерархической структурой

(2 узла по 2 Intel Xeon 5150)

Сеть связи Gigabit Ethernet

Общая память

Ядро Ядро

Кэш L2

Процессор

Ядро Ядро

Кэш L2

Процессор

Общая память

Ядро Ядро

Кэш L2

Процессор

Ядро Ядро

Кэш L2

Процессор

Граф программы

стандартными MPI-утилитами (mpiexec) –время выполнения 118 сек. (44 GFLOPS)

Page 71: Стандарт MPI (Message Passing Interface)

Пример вложения программы в ВС

7171

1 2 3 4 5 6 7 8

Вложение теста High Performance Linpack в подсистему:

5

1

6 7 8

2 3 4

High Performance Linpack (HPL)

Вычислительный кластер

с иерархической структурой

(2 узла по 2 Intel Xeon 5150)

Сеть связи Gigabit Ethernet

Общая память

Ядро Ядро

Кэш L2

Процессор

Ядро Ядро

Кэш L2

Процессор

Общая память

Ядро Ядро

Кэш L2

Процессор

Ядро Ядро

Кэш L2

Процессор

1 3 5 7 2 4 6 8

Граф программы

с учетом структуры ВС – время выполнения 100 сек. (53 GFLOPS)

стандартными MPI-утилитами (mpiexec) –время выполнения 118 сек. (44 GFLOPS)

Page 72: Стандарт MPI (Message Passing Interface)

Иерархический метод вложения программ

7272

Метод вложения на основе многоуровневых (multilevel) алгоритмов разбиения

графов G = (V, E) параллельных программ

1. Граф G разбивается на k подмножеств; k – количество узлов, составляющих ВС. В каждое из

подмножеств включаются ветви, интенсивно обменивающиеся данными.

2. Параллельные ветви из i-го подмножества распределяются по ядрам i-го вычислительного

узла, 𝑖 ∈ {1, 2, . . , 𝑘}.

Сеть связи Gigabit Ethernet

Разделяемая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Разделяемая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Разделяемая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

Разделяемая память

Ядро

Процессор

Ядро Ядро

Процессор

Ядро

13

14

15

16

1

2

3

4

5

6

7

8

9

10

11

12V1 V2 V3 V4

Вложение MPI-программы Conjugate Gradient (CG) из пакета NAS Parallel Benchmarks, реализующей решение системы линейных алгебраических уравнений методом

сопряженных градиентов в вычислительный кластер

Page 73: Стандарт MPI (Message Passing Interface)

Иерархический метод вложения программ

7373

The Parallel Ocean Program, NP = 128

Моделирование процессов в мировом океане

Page 74: Стандарт MPI (Message Passing Interface)

Иерархический метод вложения программ

7474

Подсистем 1 (8 ядер) Подсистема 2 (16 ядер) Подсистема 3 (16 ядер)

The Parallel Ocean Program (POP), NP = 40

Page 75: Стандарт MPI (Message Passing Interface)

Иерархический метод вложения программ

7575

Подсистем 1 (8 ядер) Подсистема 2 (16 ядер) Подсистема 3 (16 ядер)

The Parallel Ocean Program (POP), NP = 40

Page 76: Стандарт MPI (Message Passing Interface)

Иерархический метод вложения программ

7676

Подсистем 1 (8 ядер) Подсистема 2 (16 ядер) Подсистема 3 (16 ядер)

The Parallel Ocean Program (POP), NP = 40