Содержание
- 2. История MPI Стандарт MPI 1.0 1995 год, MPI 2.0 1998 год. Определяет API (варианты для Си,
- 3. «Комплект поставки» MPI Библиотека. Средства компиляции и запуска приложения.
- 4. SPMD-модель. 0 1 2 3 Разные процессы выполняют разные части одного и того же кода.
- 5. Сборка MPI-приложения. Сборка MPI-приложения осуществляется с помощью специальной утилиты. В случае Си – mpicc. Пример: mpicc
- 6. MPI “Hello, World” #include #include main(int argc, char* argv[]) { MPI_Init(&argc, &argv); printf("Hello, World!\n"); MPI_Finalize(); }
- 7. Функции инициализации и завершения работы. int MPI_Init(int* argc,char*** argv) argc – указатель на счетчик аргументов командной
- 8. Тоже простая MPI-программа #include #include int main( int argc, char *argv[] ) { int rank, size;
- 9. Функции определения ранга и числа процессов. int MPI_Comm_size (MPI_Comm comm, int* size ) comm - коммуникатор
- 10. Точечные взаимодействия
- 11. Назначение точечных взаимодействий
- 12. Пример простейшей пересылки #include #include main(int argc, char* argv[]) { int rank; MPI_Status st; char buf[64];
- 13. Функции обменов точка-точка int MPI_Send( buf, count, datatype, dest, tag, comm ) void *buf; /* in
- 14. int MPI_Recv( buf, count, datatype, source, tag, comm, status ) void *buf; /* in */ int
- 15. typedef struct { int count; int MPI_SOURCE; int MPI_TAG; int MPI_ERROR; } MPI_Status; count - число
- 16. Численное интегрирование
- 17. MPI-программа численного интегрирования #include #include double f(double x) { return 4./(1 + x * x); }
- 18. MPI-программа численного интегрирования MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &r); MPI_Comm_size(MPI_COMM_WORLD, &p); if(r == 0) t = MPI_Wtime(); MPI_Barrier(MPI_COMM_WORLD);
- 19. MPI-программа численного интегрирования if(r == 0) { double s; for(i = 0; i MPI_Recv(&s, 1, MPI_DOUBLE,
- 20. Результаты вычислительного эксперимента Данные получены на MVS-15000BM.
- 21. Семантика точечных взаимодействий
- 22. Виды точечных взаимодействий
- 24. Буферизованная пересылка Процесс-отправитель выделяет буфер и регистрирует его в системе. Функция MPI_Bsend помещает данные выделенный буфер,
- 25. Буферизованная пересылка int MPI_Bsend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) Завершается
- 26. Функции работы с буфером обмена int MPI_Buffer_attach( buffer, size ) void *buffer; /* in */ int
- 27. Вычисление размера буфера int MPI_Pack_size(int incount, MPI_Datatype datatype, MPI_Comm comm, int *size) Вычисляет размер памяти для
- 28. Порядок организации буферизованных пересылок Вычислить необходимый объем буфера (MPI_Pack_size). Выделить память под буфер (malloc). Зарегистрировать буфер
- 29. Особенности работы с буфером Буфер всегда один. Для изменения размера буфера сначала следует отменить регистрацию, затем
- 30. MPI_Pack_size(1, MPI_INT, MPI_COMM_WORLD,&msize) blen = M * (msize + MPI_BSEND_OVERHEAD); buf = (int*) malloc(blen); MPI_Buffer_attach(buf, blen);
- 31. Неблокирующие пересылки Предназначены для перекрытия обменов и вычислений. Операция расщепляется на две: инициация и завершение.
- 32. Неблокирующая пересылка int MPI_Isend( buf, count, datatype, dest, tag, comm, request) MPI_Request *request; /* out */
- 33. Завершение: int MPI_Wait (MPI_Request * request, MPI_Status * status) int MPI_Test(MPI_Request *request, int *flag, MPI_Status *status)
- 34. Пример: кольцевой сдвиг данных
- 35. #include "mpi.h" #include int main (argc, argv) int argc; char *argv[]; { int numtasks, rank, next,
- 36. MPI_Irecv (&buf[0], 1, MPI_INT, prev, tag1, MPI_COMM_WORLD, &reqs[0]); MPI_Irecv (&buf[1], 1, MPI_INT, next, tag2, MPI_COMM_WORLD, &reqs[1]);
- 37. Прием по шаблону В качестве параметров source и tag в функции MPI_Recv могут быть использованы константы
- 38. Стратегия управляющий-рабочие
- 39. Адаптивная квадратура Частота разбиения выбирается в соответствии с плавностью изменения функции.
- 40. #include #include #define MYABS(A) (((A) double f(double x) { return sin(1. / x); } ПРИМЕР РЕАЛИЗАЦИИ
- 41. int adint(double (*f) (double), double left, double right, double eps, double *nint) { double mid; double
- 42. double recadint(double (*f)(double), double left, double right, double eps) { double I; if(adint(f, left, right, eps,
- 43. main(int argc, char* argv[]) { int r, p, n = 100000, s = 0; double a
- 44. if(r == 0) { while(s != (p-1)) { double Islave; MPI_Recv(&Islave, 1, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD,
- 45. if(r == 0) { t = MPI_Wtime() - t; printf("Integral value: %lf, time = %lf\n", I,
- 46. Результаты экспериментов данные получены на MVS 15000 BM
- 47. Deadlock if(rank == 0) { MPI_Ssend(… 1 …) MPI_Recv(…1…) } else { MPI_Ssend(… 0 …) MPI_Recv(…0…)
- 48. «Недетерминированный» deadlock if(rank == 0) { MPI_Send(… 1 …) MPI_Recv(…1…) } else { MPI_Send(… 0 …)
- 49. Недетерминизм за счет разницы в относительных скоростях процессов (race condition)
- 50. Коллективные взаимодействия процессов
- 51. Коллективные взаимодействия процессов MPI предоставляет ряд функций для коллективного взаимодейстия процессов. Эти функции называют коллективными, поскольку
- 52. int MPI_Bcast ( buffer, count, datatype, root, comm ) void* buffer - начальный адрес буфера для
- 53. int MPI_Reduce ( sendbuf, recvbuf, count, datatype, op, root, comm ) void *sendbuf; буфер операндов void
- 54. MPI_MAX максимум MPI_MIN минимум MPI_SUM сумма MPI_PROD произведение MPI_LAND логическое "и" MPI_BAND побитовое "и" MPI_LOR логическое
- 55. Вычисление числа Пи 1 2 3 4 1 2 3 4 1 2 3 4 1
- 56. Вычисление числа Pi #include "mpi.h" #include int main(argc,argv) int argc; char *argv[]; { int n, myid,
- 57. while (1) { if (myid == 0) { printf("Enter the number of intervals: (0 quits) ");
- 58. MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if (myid == 0) printf("pi is approximately %.16f, Error
- 59. Функция синхронизации процессов: int MPI_Barrier ( comm ) ; MPI_Comm comm; Функция синхронизации процессов: int MPI_Barrier
- 60. int MPI_Scatter ( sendbuf, sendcnt, sendtype, recvbuf, recvcnt, recvtype, root, comm ) void *sendbuf; int sendcnt;
- 61. 0 1 2 3 int MPI_Gather ( sendbuf, sendcnt, sendtype, recvbuf, recvcount, recvtype, root, comm )
- 62. int MPI_Allreduce ( sendbuf, recvbuf, count, datatype, op, comm ) void *sendbuf; void *recvbuf; int count;
- 63. int MPI_Alltoall( sendbuf, sendcount, sendtype, recvbuf, recvcnt, recvtype, comm ) void *sendbuf; int sendcount; MPI_Datatype sendtype;
- 64. Метод Якоби решения линейных систем , -
- 65. Условие остановки:
- 66. Матричная форма записи
- 67. Условие сходимости Диагональное преобладание – достаточное условие сходимости. Пример:
- 68. Последовательный алгоритм #define MAXITERS 1000 void init(int m, double* B, double* g, double* x) { int
- 69. double evalDiff(double* u, double* v, int m) { int i; double a = 0.0; for(i =
- 70. main(int argc, char* argv[]) { int m, I = 0; double *B, *g, *x, *xold, eps,
- 71. do { int i; for(i = 0; i int j; double a = 0.; double* row
- 72. Параллельный алгоритм B xold x цикл
- 73. main(int argc, char* argv[]) { int m, np, rk, chunk, i, I = 0; double *B,
- 74. MPI_Scatter(B, m * chunk, MPI_DOUBLE, Bloc, m * chunk, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(g, m, MPI_DOUBLE, 0,
- 75. if(rk == 0) { t = MPI_Wtime() - t; printf("%d iterations consumed %lf sec\n", I, t);
- 76. Группы и коммуникаторы
- 77. Интер- и интра-коммуникаторы Интра- коммуникаторы Интер- коммуникатор Интра-коммуникаторы объединяют процессы из одной группы. Интер-коммуникатор позволяет передавать
- 78. Назначение коммуникаторов Поддержка параллельных библиотек. Поддержка коллективных операций на части вычислительного пространства. Повышение уровня абстракции параллельных
- 79. #include "mpi.h" #include double g(double x) { return 4.0 / (1.0 + x * x); }
- 80. int main(int argc, char *argv[]) { int n, myid; double PI25DT = 3.141592653589793238462643; double pi; MPI_Init(&argc,&argv);
- 81. Создание коммуникаторов Разбиение коммуникатора на несколько: int MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm* newcomm) comm
- 82. int main(int argc, char **argv) { int n, myid; double PI25DT = 3.141592653589793238462643; double pi, res;
- 83. if(myid % 2) quad(n, g, comm, &pi); else quad(n, h, comm, &pi); if(myid
- 84. Группы и коммуникаторы Совокупности MPI-процессов образуют группы. Понятие ранга процесса имеет смысл только по отношению к
- 85. Информационные функции для работы с группами Определение размера группы: int MPI_Group_size(MPI_Group group, int *size) group –
- 86. Информационные функции для работы с группами Установление соответствия между номерами процессов в различных группах: int MPI_Group_translate_ranks
- 87. Информационные функции для работы с группами Сравнение двух групп процессов: int MPI_Group_compare(MPI_Group group1,MPI_Group group2, int *result)
- 88. Педопределенные группы: MPI_GROUP_EMPTY – «пустая» группа (не содержит процессов); MPI_GROUP_NULL – «нулевая группа» (не соответствует никакой
- 89. int MPI_Group_free(MPI_Group* group) group – идентификатор освобождаемой группы. Получение коммуникатора по группе: int MPI_Comm_group(MPI_Comm comm, MPI_Group
- 90. Объединение двух групп: int MPI_Group_union(MPI_Group gr1, MPI_Group g2, MPI_Group* gr3) gr1 – первая группа; gr2 –
- 91. Разность двух групп: int MPI_Group_difference(MPI_Group gr1, MPI_Group g2, MPI_Group* gr3) gr1 – первая группа; gr2 –
- 92. Переупорядочивание (с возможным удалением) процессов в существующей группе: int MPI_Group_incl(MPI_Group* group, int n, int* ranks, MPI_Group*
- 93. Удаление процессов из группы: int MPI_Group_excl(MPI_Group* group, int n, int* ranks, MPI_Group* newgroup) group – исходная
- 94. Дублирование коммуникатора Получение дубликата коммуникатора: int MPI_Comm_dup(MPI_Comm comm, MPI_Comm* newcomm) Используется для того, чтобы снабдить библиотечную
- 95. Создание коммуникатора по группе int MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm *newcomm) Требования: Конструктор вызывается на всех
- 96. Создание коммуникатора по группе Создание коммуникатора по группе процессов: int MPI_Comm_create(MPI_Comm comm,MPI_Group group, MPI_Comm *newcomm) comm
- 97. Удаление коммуникатора Освобождение коммуникатора: int MPI_Comm_free(MPI_Comm *comm) При освобождении коммуникатора все незавершенные операции будут завершены, только
- 98. Вычисление числа Pi методом Монте-Карло Из книги Gropp, Lusk, Skjellum
- 99. Схема вычислений server worker processes коммуникатор workers коммуникатор world
- 100. /* compute pi using Monte Carlo method */ #include #include "mpi.h" #define CHUNKSIZE 1000 #define INT_MAX
- 101. server = numprocs-1; if (myid == 0) sscanf( argv[1], "%lf", &epsilon ); MPI_Bcast( &epsilon, 1, MPI_DOUBLE,
- 102. else { /* I am a worker process */ request = 1; done = in =
- 103. MPI_Allreduce(&in, &totalin, 1, MPI_INT, MPI_SUM, workers); MPI_Allreduce(&out, &totalout, 1, MPI_INT, MPI_SUM, workers); Pi = (4.0*totalin)/(totalin +
- 104. if (myid == 0) { printf( "\npoints: %d\nin: %d, out: %d, to exit\n", totalin+totalout, totalin, totalout
- 105. Система типов сообщений MPI
- 106. Типы в MPI БАЗОВЫЕ ТИПЫ MPI_CHAR MPI_SHORT MPI_INT MPI_LONG MPI_UNSIGNED_CHAR MPI_UNSIGNED_SHORT MPI_UNSIGNED MPI_UNSIGNED_LONG MPI_FLOAT MPI_DOUBLE MPI_LONG_DOUBLE
- 107. БАЗОВЫЕ ТИПЫ
- 108. ПРОИЗВОДНЫЕ ТИПЫ MPI_TYPE_CONTIGUOUS – массив «без дырок»; MPI_TYPE_VECTOR, MPI_TYPE_HVECTOR – регулярно (с постоянным шагом) расположенные в
- 109. Назначение производных типов пересылка данных, расположенных в несмежных областях памяти в одном сообщении; пересылка разнотипных данных
- 110. MPI_TYPE_CONTIGUOUS MPI_Type_contiguous(int count, MPI_Datatype oldtype, MPI_Datatype *newtype) oldtype oldtype oldtype oldtype ... count
- 111. MPI_TYPE_VECTOR MPI_Type_vector(int count, int blocksize, int stride, MPI_Datatype oldtype, MPI_Datatype *newtype) oldtype oldtype oldtype oldtype ...
- 112. Отрицательный шаг oldtype oldtype oldtype oldtype stride = -4 oldtype oldtype oldtype oldtype stride = 4
- 113. MPI_TYPE_INDEXED MPI_Type_indexed(int count, int* blocksizes, int* displacements, MPI_Datatype oldtype, MPI_Datatype *newtype) oldtype oldtype oldtype count (число
- 114. MPI_TYPE_HVECTOR MPI_TYPE_HINDEXED основное отличие: смещение задается в байтах – необходимо знать точные значения размеров и требований
- 115. MPI_TYPE_STRUCT MPI_Type_struct(int count, int* blocksizes, int* displacements, MPI_Datatype *types, MPI_Datatype *newtype) types[0] types[1] count (число блоков)
- 116. РЕГИСТРАЦИЯ ТИПА Регистрация типа: int MPI_Type_commit(MPI_Datatype *datatype) Освобождение памяти: int MPI_Type_free(MPI_Datatype *datatype) типы, которые строились на
- 117. ПОРЯДОК РАБОТЫ С ПРОИЗВОДНЫМИ ТИПАМИ Создание типа с помощью конструктора. Регистрация. Использование. Освобождение памяти.
- 118. КАРТА И СИГНАТУРА ТИПА Карта типа - набор пар (базовый тип, смещение): ((type1, disp1), (type2, disp2),
- 119. СООТВЕТСТВИЕ ТИПОВ Соответствие типов отправителя и получателя: Сигнатура типа пришедшего сообщения является начальной подпоследовательностью сигнатуры типа,
- 120. ПРИМЕРЫ send: MPI_TYPE_VECTOR(3, 1, 2, MPI_DOUBLE) recv: MPI_TYPE_CONTIGUOUS(3, MPI_DOUBLE) double double double double double double send:MPI_TYPE_CONTIGUOUS(6,
- 121. ПРИМЕРЫ send: MPI_TYPE_VECTOR(3, 1, 2, MPI_DOUBLE) recv: MPI_TYPE_CONTIGUOUS(6, MPI_DOUBLE) double double double double double double double
- 122. ПРИМЕРЫ MPI_TYPE_HVECTOR(3, 1, 2, MPI_DOUBLE) MPI_TYPE_VECTOR(3, 1, 2, MPI_DOUBLE) double double double double double double MPI_TYPE_VECTOR(3,
- 123. ТРАНСПОНИРОВАНИЕ МАТРИЦЫ A AT Процесс #1 Процесс #2
- 124. #include #include #define N 3 int A[N][N]; void fill_matrix() { int i,j; for(i = 0; i
- 125. main(int argc, char* argv[]) { int r, i; MPI_Status st; MPI_Datatype typ; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &r);
- 126. else if(r == 1){ MPI_Type_vector(N, 1, N, MPI_INT, &typ); MPI_Type_commit(&typ); MPI_Barrier(MPI_COMM_WORLD); for(i = 0; i MPI_Recv(&(A[0][i]),
- 127. РЕЗУЛЬТАТ РАБОТЫ Transposed: 0 3 6 1 4 7 2 5 8 Source: 0 1 2
- 128. if(r == 0) { fill_matrix(); printf("\n Source:\n"); print_matrix(); MPI_Type_contiguous(N * N, MPI_INT, &typ); MPI_Type_commit(&typ); MPI_Barrier(MPI_COMM_WORLD); MPI_Send(&(A[0][0]),
- 129. УПАКОВКА СООБЩЕНИЙ дает возможность пересылать разнородные данные в одном сообщении; отделяет операцию формирования сообщения от операции
- 130. MPI_PACK int MPI_Pack(void* inbuf, int incount, MPI_Datatype datatype, void *outbuf, int outcount, int *position,, MPI_Comm comm)
- 131. MPI_UNPACK int MPI_Unpack(void* inbuf, int insize, int *position, void *outbuf, int outcount, MPI_Datatype datatype, MPI_Comm comm)
- 132. ОПРЕДЕЛЕНИЕ РАЗМЕРА СООБЩЕНИЯ int MPI_Pack_size(int incount, MPI_Datatype datatype, MPI_Comm comm, int *size) incount – число элементов
- 133. ПРИМЕР #include #include #include #define N 3 main(int argc, char* argv[]) { int r; int i;
- 134. ПРИМЕР if(r == 0){ int sz; int pos = 0; int a = 1; void* buf;
- 135. ПРИМЕР else { MPI_Status st; int A[N]; MPI_Recv(A, N, MPI_INT, 0, 0, MPI_COMM_WORLD, &st); for(i =
- 136. ХАРАКТЕРНЫЕ ОШИБКИ В MPI-ПРОГРАММАХ
- 137. ВИДЫ ОШИБОК Ошибки последовательных программ. Ошибки несоответствия типов. Ошибки работы с MPI-объектами. Взаимные блокировки. Недетерминизм.
- 138. Недетерминизм за счет разницы в относительных скоростях процессов (race condition)
- 139. Deadlock if(rank == 0) { MPI_Ssend(… 1 …) MPI_Recv(…1…) } else { MPI_Ssend(… 0 …) MPI_Recv(…0…)
- 141. Скачать презентацию