SlideShare a Scribd company logo
Семинар 11
Стандарт MPI (часть 4)
Михаил Курносов
E-mail: mkurnosov@gmail.com
WWW: www.mkurnosov.net
Цикл семинаров «Основы параллельного программирования»
Институт физики полупроводников им. А. В. Ржанова СО РАН
Новосибирск, 2015 CC-BY
Пользовательские типы данных (MPI Derived Data Types)
 Как передать структуру C/C++ в другой процесс?
 Как передать другом процессу столбец матрицы?
(в C/C++ массивы хранятся в памяти строка за строкой – row-major order,
в Fortran столбец за столбцом – column-major order)
 Как реализовать прием сообщений различных размеров
(заголовок сообщения содержит его тип, размер)?
Пользовательские типы данных (MPI Derived Data Types)
typedef struct {
double x;
double y;
double z;
double f;
int data[8];
} particle_t;
int main(int argc, char **argv)
{
int rank;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
int nparticles = 1000;
particle_t *particles = malloc(sizeof(*particles) * nparticles);
Как передать массив частиц другому процессу?
Пользовательские типы данных (MPI Derived Data Types)
/* Create data type for message of type particle_t */
MPI_Datatype types[5] = {MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE,
MPI_INT};
int blocklens[5] = {1, 1, 1, 1, 8};
MPI_Aint displs[0];
displs[0] = offsetof(particle_t, x);
displs[1] = offsetof(particle_t, y);
displs[2] = offsetof(particle_t, z);
displs[3] = offsetof(particle_t, f);
displs[4] = offsetof(particle_t, data);
MPI_Datatype parttype;
MPI_Type_create_struct(5, blocklens, displs,
types, &parttype);
MPI_Type_commit(&parttype);
Компилятор выравнивает структуру
// size = 72
struct {
double x; // offset 0
double y; // offset 8
double z; // offset 16
int type // offset 24
double f; // offset 32
int data[8]; // offset 40
}
// size = 64
struct {
double x; // offset 0
double y; // offset 8
double z; // offset 16
double f; // offset 24
int data[8]; // offset 32
}
Пользовательские типы данных (MPI Derived Data Types)
/* Init particles */
if (rank == 0) {
// Random positions in simulation box
for (int i = 0; i < nparticles; i++) {
particles[i].x = rand() % 10000;
particles[i].y = rand() % 10000;
particles[i].z = rand() % 10000;
particles[i].f = 0.0;
}
}
MPI_Bcast(particles, nparticles, parttype, 0, MPI_COMM_WORLD);
// code ...
MPI_Type_free(&parttype);
free(particles);
MPI_Finalize( );
return 0;
}
MPI_Type_contiguous
int MPI_Type_contiguous(int count, MPI_Datatype oldtype,
MPI_Datatype *newtype)
 Непрерывная последовательность в памяти (массив) элементов типа oldtype
 Одномерный массив
 Пример
 oldtype = {(double, 0), (char, 8)}
(1 double и 1 char, 0 и 8 — это смещения)

MPI_Type_contiguous(3, MPI_Datatype oldtype, &newtype)

newtype = {(double, 0), (char, 8), (double, 16), (char, 24), (double, 32), (char, 40)}
contig.
Пользовательские типы данных (MPI Derived Data Types)
 T. Hoefler. Advanced Parallel Programming with MPI // EuroMPI'14 Tutorial http://htor.inf.ethz.ch/teaching/mpi_tutorials/eurompi14/
Пользовательские типы данных (MPI Derived Data Types)
 int MPI_Type_vector(int count, int blocklength, int stride,
MPI_Datatype oldtype, MPI_Datatype *newtype)
 int MPI_Type_indexed(int count, const int array_of_blocklengths[],
const int array_of_displacements[],
MPI_Datatype oldtype, MPI_Datatype *newtype)
 int MPI_Type_create_struct(int count,
const int array_of_blocklengths[],
const MPI_Aint array_of_displacements[],
const MPI_Datatype array_of_types[],
MPI_Datatype *newtype)
 int MPI_Type_create_subarray(int ndims, const int array_of_sizes[],
const int array_of_subsizes[],
const int array_of_starts[],
int order, MPI_Datatype oldtype,
MPI_Datatype *newtype)
 ...
Выбор типа данных
1. Предопределенные типы
(MPI_DOUBLE, MPI_INT, MPI_CHAR, ...)
2. contig
3. vector
4. index_block
5. index
6. struct
Slower
Упаковка данных (MPI_Pack)
int main(int argc, char **argv)
{
int rank, packsize, position;
int a;
double b;
uint8_t packbuf[100];
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) {
a = 15;
b = 3.14; Как передать int a и double b
одним сообщением ?
Упаковка данных (MPI_Pack)
packsize = 0; /* Pack data into the buffer */
MPI_Pack(&a, 1, MPI_INT, packbuf, 100, &packsize, MPI_COMM_WORLD);
MPI_Pack(&b, 1, MPI_DOUBLE, packbuf, 100, &packsize, MPI_COMM_WORLD);
}
MPI_Bcast(&packsize, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Bcast(packbuf, packsize, MPI_PACKED, 0, MPI_COMM_WORLD);
if (rank != 0) {
position = 0; /* Unpack data */
MPI_Unpack(packbuf, packsize, &position, &a, 1, MPI_INT, MPI_COMM_WORLD);
MPI_Unpack(packbuf, packsize, &position, &b, 1, MPI_DOUBLE,
MPI_COMM_WORLD);
}
printf("Process %d unpacked %d and %lfn", rank, a, b);
MPI_Finalize( );
return 0;
}
Обработка изображения (contrast)
width
height
1)Вычисляется среднее квадратичное
значений всех пикселей (RMS)
RMS = sqrt( sum( L[i][j] * L[i][j] ) / (H * W) )
2) Каждый пиксель L[i,j] преобразуется
L[i,j] = 2 * L[i, j] — RMS
if (L[i,j] < 0) then L[i,j] = 0
if (L[i,j] > 255) then L[i,j] = 255
Обработка изображения (contrast)
width
height
npixels = width * height;
npixels_per_process = npixels / commsize;
P0
P1
P2
…
PN-1
1D decomposition
Обработка изображения (contrast)
int main(int argc, char *argv[]) {
MPI_Init(&argc, &argv);
int rank, commsize;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &commsize);
int width, height, npixels, npixels_per_process;
uint8_t *pixels = NULL;
if (rank == 0) {
width = 15360; // 15360 x 8640: 16K Digital Cinema (UHDTV) ~ 127 MiB
height = 8640;
npixels = width * height;
pixels = xmalloc(sizeof(*pixels) * npixels);
for (int i = 0; i < npixels; i++)
pixels[i] = rand() % 255;
}
MPI_Bcast(&npixels, 1, MPI_INT, 0, MPI_COMM_WORLD); // Send size of image
npixels_per_process = npixels / commsize;
uint8_t *rbuf = xmalloc(sizeof(*rbuf) * npixels_per_process);
// Send a part of image to each process
MPI_Scatter(pixels, npixels_per_process, MPI_UINT8_T, rbuf, npixels_per_process, MPI_UINT8_T,
0, MPI_COMM_WORLD);
Обработка изображения (contrast)
int sum_local = 0;
for (int i = 0; i < npixels_per_process; i++)
sum_local += rbuf[i] * rbuf[i];
/* Calculate global sum of the squares */
int sum = 0;
// MPI_Reduce(&sum_local, &sum, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
MPI_Allreduce(&sum_local, &sum, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
double rms;
// if (rank == 0)
rms = sqrt((double)sum / (double)npixels);
//MPI_Bcast(&rms, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
Обработка изображения (contrast)
/* Contrast operation on subimage */
for (int i = 0; i < npixels_per_process; i++) {
int pixel = 2 * rbuf[i] - rms;
if (pixel < 0)
rbuf[i] = 0;
else if (pixel > 255)
rbuf[i] = 255;
else
rbuf[i] = pixel;
}
MPI_Gather(rbuf, npixels_per_process, MPI_UINT8_T, pixels,
npixels_per_process, MPI_UINT8_T, 0, MPI_COMM_WORLD);
if (rank == 0)
// Save image...
free(rbuf);
if (rank == 0)
free(pixels);
MPI_Finalize();
}
Обработка изображения (contrast)
 Равномерно ли пиксели изображения распределяются по процессам?
npixels_per_process = npixels / commsize;
 Загрузка исходного изображения
✔ Корневой процесс загружает изображение и рассылает части остальным 
(изображение может не поместиться в память одного узла)
✔ Каждый процесс загружает часть изображения (MPI I/O, NFS, Lustre)
 Обработка изображения
✔ Вычисление RMS: MPI_Reduce + MPI_Bcast или MPI_Allreduce
 Сохранение изображения
✔ Сборка Gather — изображение формируется в памяти процесс 0
✔ Сборка Send/Recv — части изображения последовательно сохраняются в файл
Домашнее чтение
 Pavan Balaji, William Gropp, Torsten Hoefler, Rajeev Thakur. Advanced MPI Programming 
// Tutorial at SC14, November 2014, http://www.mcs.anl.gov/~thakur/sc14-mpi-tutorial/
 Torsten Hoefler. Advanced MPI 2.2 and 3.0 Tutorial // 
http://htor.inf.ethz.ch/teaching/mpi_tutorials/cscs12/hoefler_tutorial_advanced-mpi-2.2-and-mpi-3.0_cscs
.pdf

More Related Content

PDF
Векторизация кода (семинар 1)
Mikhail Kurnosov
 
PDF
Семинар 5. Многопоточное программирование на OpenMP (часть 5)
Mikhail Kurnosov
 
PDF
Семинар 1. Многопоточное программирование на OpenMP (часть 1)
Mikhail Kurnosov
 
PDF
Лекция 6. Стандарт OpenMP
Mikhail Kurnosov
 
PDF
Лекция 8. Intel Threading Building Blocks
Mikhail Kurnosov
 
PDF
Семинар 4. Многопоточное программирование на OpenMP (часть 4)
Mikhail Kurnosov
 
PDF
Семинар 2. Многопоточное программирование на OpenMP (часть 2)
Mikhail Kurnosov
 
PDF
Лекция 2. Оптимизация ветвлений и циклов (Branch prediction and loop optimiz...
Mikhail Kurnosov
 
Векторизация кода (семинар 1)
Mikhail Kurnosov
 
Семинар 5. Многопоточное программирование на OpenMP (часть 5)
Mikhail Kurnosov
 
Семинар 1. Многопоточное программирование на OpenMP (часть 1)
Mikhail Kurnosov
 
Лекция 6. Стандарт OpenMP
Mikhail Kurnosov
 
Лекция 8. Intel Threading Building Blocks
Mikhail Kurnosov
 
Семинар 4. Многопоточное программирование на OpenMP (часть 4)
Mikhail Kurnosov
 
Семинар 2. Многопоточное программирование на OpenMP (часть 2)
Mikhail Kurnosov
 
Лекция 2. Оптимизация ветвлений и циклов (Branch prediction and loop optimiz...
Mikhail Kurnosov
 

What's hot (20)

PDF
Семинар 6. Многопоточное программирование на OpenMP (часть 6)
Mikhail Kurnosov
 
PDF
Семинар 8. Параллельное программирование на MPI (часть 1)
Mikhail Kurnosov
 
PDF
Семинар 3. Многопоточное программирование на OpenMP (часть 3)
Mikhail Kurnosov
 
PDF
Лекция 7. Язык параллельного программирования Intel Cilk Plus
Mikhail Kurnosov
 
PDF
Семинар 9. Параллельное программирование на MPI (часть 2)
Mikhail Kurnosov
 
PDF
Векторизация кода (семинар 3)
Mikhail Kurnosov
 
PDF
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Mikhail Kurnosov
 
PDF
Лекция 7. Стандарт OpenMP (подолжение)
Mikhail Kurnosov
 
PDF
Семинар 12. Параллельное программирование на MPI (часть 5)
Mikhail Kurnosov
 
PDF
Лекция 6. Стандарт OpenMP
Mikhail Kurnosov
 
PDF
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Mikhail Kurnosov
 
PDF
Семинар 7. Многопоточное программирование на OpenMP (часть 7)
Mikhail Kurnosov
 
PDF
ПВТ - весна 2015 - Лекция 1. Актуальность параллельных вычислений. Анализ пар...
Alexey Paznikov
 
PDF
Лекция 3. Оптимизация доступа к памяти (Memory access optimization, cache opt...
Mikhail Kurnosov
 
PDF
Лекция 4. Векторизация кода (Code vectorization: SSE, AVX)
Mikhail Kurnosov
 
PDF
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Alexey Paznikov
 
PDF
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Yandex
 
PDF
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Yandex
 
PDF
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
Alexey Paznikov
 
PDF
Использование Time-Stamp Counter для измерения времени выполнения кода на пр...
Mikhail Kurnosov
 
Семинар 6. Многопоточное программирование на OpenMP (часть 6)
Mikhail Kurnosov
 
Семинар 8. Параллельное программирование на MPI (часть 1)
Mikhail Kurnosov
 
Семинар 3. Многопоточное программирование на OpenMP (часть 3)
Mikhail Kurnosov
 
Лекция 7. Язык параллельного программирования Intel Cilk Plus
Mikhail Kurnosov
 
Семинар 9. Параллельное программирование на MPI (часть 2)
Mikhail Kurnosov
 
Векторизация кода (семинар 3)
Mikhail Kurnosov
 
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Mikhail Kurnosov
 
Лекция 7. Стандарт OpenMP (подолжение)
Mikhail Kurnosov
 
Семинар 12. Параллельное программирование на MPI (часть 5)
Mikhail Kurnosov
 
Лекция 6. Стандарт OpenMP
Mikhail Kurnosov
 
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Mikhail Kurnosov
 
Семинар 7. Многопоточное программирование на OpenMP (часть 7)
Mikhail Kurnosov
 
ПВТ - весна 2015 - Лекция 1. Актуальность параллельных вычислений. Анализ пар...
Alexey Paznikov
 
Лекция 3. Оптимизация доступа к памяти (Memory access optimization, cache opt...
Mikhail Kurnosov
 
Лекция 4. Векторизация кода (Code vectorization: SSE, AVX)
Mikhail Kurnosov
 
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Alexey Paznikov
 
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Yandex
 
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Yandex
 
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
Alexey Paznikov
 
Использование Time-Stamp Counter для измерения времени выполнения кода на пр...
Mikhail Kurnosov
 
Ad

Viewers also liked (9)

PDF
Лекция 1. Амортизационный анализ (amortized analysis)
Mikhail Kurnosov
 
PDF
Лекция 11. Методы разработки алгоритмов
Mikhail Kurnosov
 
PDF
Лекция 6. Фибоначчиевы кучи (Fibonacci heaps)
Mikhail Kurnosov
 
PDF
Лекция 4. Префиксные деревья (tries, prefix trees)
Mikhail Kurnosov
 
PDF
Лекция 10. Графы. Остовные деревья минимальной стоимости
Mikhail Kurnosov
 
PDF
Лекция 3. АВЛ-деревья (AVL trees)
Mikhail Kurnosov
 
PDF
Лекция 2. Красно-чёрные деревья (Red-black trees). Скошенные деревья (Splay t...
Mikhail Kurnosov
 
PDF
Лекция 6: Хеш-таблицы
Mikhail Kurnosov
 
PDF
Векторизация кода (семинар 2)
Mikhail Kurnosov
 
Лекция 1. Амортизационный анализ (amortized analysis)
Mikhail Kurnosov
 
Лекция 11. Методы разработки алгоритмов
Mikhail Kurnosov
 
Лекция 6. Фибоначчиевы кучи (Fibonacci heaps)
Mikhail Kurnosov
 
Лекция 4. Префиксные деревья (tries, prefix trees)
Mikhail Kurnosov
 
Лекция 10. Графы. Остовные деревья минимальной стоимости
Mikhail Kurnosov
 
Лекция 3. АВЛ-деревья (AVL trees)
Mikhail Kurnosov
 
Лекция 2. Красно-чёрные деревья (Red-black trees). Скошенные деревья (Splay t...
Mikhail Kurnosov
 
Лекция 6: Хеш-таблицы
Mikhail Kurnosov
 
Векторизация кода (семинар 2)
Mikhail Kurnosov
 
Ad

Similar to Семинар 11. Параллельное программирование на MPI (часть 4) (20)

PDF
Лекция 4. Производные типы данных в стандарте MPI
Alexey Paznikov
 
PPTX
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
Pavel Tsukanov
 
PDF
Стандарт MPI (Message Passing Interface)
Mikhail Kurnosov
 
PDF
20140420 parallel programming_kalishenko_lecture10
Computer Science Club
 
PDF
Что такое size_t и ptrdiff_t
Tatyanazaxarova
 
PDF
Урок 9. Паттерн 1. Магические числа
Tatyanazaxarova
 
PDF
C++ осень 2013 лекция 2
Technopark
 
PDF
Лекция 12 (часть 1): Языки программирования семейства PGAS: Cray Chapel
Mikhail Kurnosov
 
PDF
Язык параллельного программирования Cray Chapel
Mikhail Kurnosov
 
PDF
Урок 13. Паттерн 5. Адресная арифметика
Tatyanazaxarova
 
PDF
Урок 17. Паттерн 9. Смешанная арифметика
Tatyanazaxarova
 
PDF
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Alexey Paznikov
 
PPTX
ADD 2011: Статический анализ Си++ кода
Andrey Karpov
 
PPTX
Статический анализ Си++ кода
Tatyanazaxarova
 
PDF
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...
Alexey Paznikov
 
PPT
инструменты параллельного программирования
Alexander Petrov
 
PPTX
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Sergey Platonov
 
PPTX
PVS-Studio, решение для разработки современных ресурсоемких приложений
OOO "Program Verification Systems"
 
PPTX
20090720 hpc exercise1
Michael Karpov
 
PDF
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Yandex
 
Лекция 4. Производные типы данных в стандарте MPI
Alexey Paznikov
 
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
Pavel Tsukanov
 
Стандарт MPI (Message Passing Interface)
Mikhail Kurnosov
 
20140420 parallel programming_kalishenko_lecture10
Computer Science Club
 
Что такое size_t и ptrdiff_t
Tatyanazaxarova
 
Урок 9. Паттерн 1. Магические числа
Tatyanazaxarova
 
C++ осень 2013 лекция 2
Technopark
 
Лекция 12 (часть 1): Языки программирования семейства PGAS: Cray Chapel
Mikhail Kurnosov
 
Язык параллельного программирования Cray Chapel
Mikhail Kurnosov
 
Урок 13. Паттерн 5. Адресная арифметика
Tatyanazaxarova
 
Урок 17. Паттерн 9. Смешанная арифметика
Tatyanazaxarova
 
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Alexey Paznikov
 
ADD 2011: Статический анализ Си++ кода
Andrey Karpov
 
Статический анализ Си++ кода
Tatyanazaxarova
 
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...
Alexey Paznikov
 
инструменты параллельного программирования
Alexander Petrov
 
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Sergey Platonov
 
PVS-Studio, решение для разработки современных ресурсоемких приложений
OOO "Program Verification Systems"
 
20090720 hpc exercise1
Michael Karpov
 
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Yandex
 

More from Mikhail Kurnosov (9)

PDF
Лекция 7. Декартовы деревья (Treaps, дучи, дерамиды)
Mikhail Kurnosov
 
PDF
Лекция 5. Основы параллельного программирования (Speedup, Amdahl's law, Paral...
Mikhail Kurnosov
 
PDF
Лекция 5. B-деревья (B-trees, k-way merge sort)
Mikhail Kurnosov
 
PDF
Семинар 10. Параллельное программирование на MPI (часть 3)
Mikhail Kurnosov
 
PDF
Лекция 9. Поиск кратчайшего пути в графе
Mikhail Kurnosov
 
PDF
Лекция 8. Графы. Обходы графов
Mikhail Kurnosov
 
PDF
Лекция 7. Бинарные кучи. Пирамидальная сортировка
Mikhail Kurnosov
 
PDF
Лекция 6. Хеш-таблицы
Mikhail Kurnosov
 
PDF
Лекция 5. Бинарные деревья поиска
Mikhail Kurnosov
 
Лекция 7. Декартовы деревья (Treaps, дучи, дерамиды)
Mikhail Kurnosov
 
Лекция 5. Основы параллельного программирования (Speedup, Amdahl's law, Paral...
Mikhail Kurnosov
 
Лекция 5. B-деревья (B-trees, k-way merge sort)
Mikhail Kurnosov
 
Семинар 10. Параллельное программирование на MPI (часть 3)
Mikhail Kurnosov
 
Лекция 9. Поиск кратчайшего пути в графе
Mikhail Kurnosov
 
Лекция 8. Графы. Обходы графов
Mikhail Kurnosov
 
Лекция 7. Бинарные кучи. Пирамидальная сортировка
Mikhail Kurnosov
 
Лекция 6. Хеш-таблицы
Mikhail Kurnosov
 
Лекция 5. Бинарные деревья поиска
Mikhail Kurnosov
 

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

  • 1. Семинар 11 Стандарт MPI (часть 4) Михаил Курносов E-mail: [email protected] WWW: www.mkurnosov.net Цикл семинаров «Основы параллельного программирования» Институт физики полупроводников им. А. В. Ржанова СО РАН Новосибирск, 2015 CC-BY
  • 2. Пользовательские типы данных (MPI Derived Data Types)  Как передать структуру C/C++ в другой процесс?  Как передать другом процессу столбец матрицы? (в C/C++ массивы хранятся в памяти строка за строкой – row-major order, в Fortran столбец за столбцом – column-major order)  Как реализовать прием сообщений различных размеров (заголовок сообщения содержит его тип, размер)?
  • 3. Пользовательские типы данных (MPI Derived Data Types) typedef struct { double x; double y; double z; double f; int data[8]; } particle_t; int main(int argc, char **argv) { int rank; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); int nparticles = 1000; particle_t *particles = malloc(sizeof(*particles) * nparticles); Как передать массив частиц другому процессу?
  • 4. Пользовательские типы данных (MPI Derived Data Types) /* Create data type for message of type particle_t */ MPI_Datatype types[5] = {MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_INT}; int blocklens[5] = {1, 1, 1, 1, 8}; MPI_Aint displs[0]; displs[0] = offsetof(particle_t, x); displs[1] = offsetof(particle_t, y); displs[2] = offsetof(particle_t, z); displs[3] = offsetof(particle_t, f); displs[4] = offsetof(particle_t, data); MPI_Datatype parttype; MPI_Type_create_struct(5, blocklens, displs, types, &parttype); MPI_Type_commit(&parttype); Компилятор выравнивает структуру // size = 72 struct { double x; // offset 0 double y; // offset 8 double z; // offset 16 int type // offset 24 double f; // offset 32 int data[8]; // offset 40 } // size = 64 struct { double x; // offset 0 double y; // offset 8 double z; // offset 16 double f; // offset 24 int data[8]; // offset 32 }
  • 5. Пользовательские типы данных (MPI Derived Data Types) /* Init particles */ if (rank == 0) { // Random positions in simulation box for (int i = 0; i < nparticles; i++) { particles[i].x = rand() % 10000; particles[i].y = rand() % 10000; particles[i].z = rand() % 10000; particles[i].f = 0.0; } } MPI_Bcast(particles, nparticles, parttype, 0, MPI_COMM_WORLD); // code ... MPI_Type_free(&parttype); free(particles); MPI_Finalize( ); return 0; }
  • 6. MPI_Type_contiguous int MPI_Type_contiguous(int count, MPI_Datatype oldtype, MPI_Datatype *newtype)  Непрерывная последовательность в памяти (массив) элементов типа oldtype  Одномерный массив  Пример  oldtype = {(double, 0), (char, 8)} (1 double и 1 char, 0 и 8 — это смещения)  MPI_Type_contiguous(3, MPI_Datatype oldtype, &newtype)  newtype = {(double, 0), (char, 8), (double, 16), (char, 24), (double, 32), (char, 40)} contig.
  • 7. Пользовательские типы данных (MPI Derived Data Types)  T. Hoefler. Advanced Parallel Programming with MPI // EuroMPI'14 Tutorial http://htor.inf.ethz.ch/teaching/mpi_tutorials/eurompi14/
  • 8. Пользовательские типы данных (MPI Derived Data Types)  int MPI_Type_vector(int count, int blocklength, int stride, MPI_Datatype oldtype, MPI_Datatype *newtype)  int MPI_Type_indexed(int count, const int array_of_blocklengths[], const int array_of_displacements[], MPI_Datatype oldtype, MPI_Datatype *newtype)  int MPI_Type_create_struct(int count, const int array_of_blocklengths[], const MPI_Aint array_of_displacements[], const MPI_Datatype array_of_types[], MPI_Datatype *newtype)  int MPI_Type_create_subarray(int ndims, const int array_of_sizes[], const int array_of_subsizes[], const int array_of_starts[], int order, MPI_Datatype oldtype, MPI_Datatype *newtype)  ...
  • 9. Выбор типа данных 1. Предопределенные типы (MPI_DOUBLE, MPI_INT, MPI_CHAR, ...) 2. contig 3. vector 4. index_block 5. index 6. struct Slower
  • 10. Упаковка данных (MPI_Pack) int main(int argc, char **argv) { int rank, packsize, position; int a; double b; uint8_t packbuf[100]; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank == 0) { a = 15; b = 3.14; Как передать int a и double b одним сообщением ?
  • 11. Упаковка данных (MPI_Pack) packsize = 0; /* Pack data into the buffer */ MPI_Pack(&a, 1, MPI_INT, packbuf, 100, &packsize, MPI_COMM_WORLD); MPI_Pack(&b, 1, MPI_DOUBLE, packbuf, 100, &packsize, MPI_COMM_WORLD); } MPI_Bcast(&packsize, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(packbuf, packsize, MPI_PACKED, 0, MPI_COMM_WORLD); if (rank != 0) { position = 0; /* Unpack data */ MPI_Unpack(packbuf, packsize, &position, &a, 1, MPI_INT, MPI_COMM_WORLD); MPI_Unpack(packbuf, packsize, &position, &b, 1, MPI_DOUBLE, MPI_COMM_WORLD); } printf("Process %d unpacked %d and %lfn", rank, a, b); MPI_Finalize( ); return 0; }
  • 12. Обработка изображения (contrast) width height 1)Вычисляется среднее квадратичное значений всех пикселей (RMS) RMS = sqrt( sum( L[i][j] * L[i][j] ) / (H * W) ) 2) Каждый пиксель L[i,j] преобразуется L[i,j] = 2 * L[i, j] — RMS if (L[i,j] < 0) then L[i,j] = 0 if (L[i,j] > 255) then L[i,j] = 255
  • 13. Обработка изображения (contrast) width height npixels = width * height; npixels_per_process = npixels / commsize; P0 P1 P2 … PN-1 1D decomposition
  • 14. Обработка изображения (contrast) int main(int argc, char *argv[]) { MPI_Init(&argc, &argv); int rank, commsize; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &commsize); int width, height, npixels, npixels_per_process; uint8_t *pixels = NULL; if (rank == 0) { width = 15360; // 15360 x 8640: 16K Digital Cinema (UHDTV) ~ 127 MiB height = 8640; npixels = width * height; pixels = xmalloc(sizeof(*pixels) * npixels); for (int i = 0; i < npixels; i++) pixels[i] = rand() % 255; } MPI_Bcast(&npixels, 1, MPI_INT, 0, MPI_COMM_WORLD); // Send size of image npixels_per_process = npixels / commsize; uint8_t *rbuf = xmalloc(sizeof(*rbuf) * npixels_per_process); // Send a part of image to each process MPI_Scatter(pixels, npixels_per_process, MPI_UINT8_T, rbuf, npixels_per_process, MPI_UINT8_T, 0, MPI_COMM_WORLD);
  • 15. Обработка изображения (contrast) int sum_local = 0; for (int i = 0; i < npixels_per_process; i++) sum_local += rbuf[i] * rbuf[i]; /* Calculate global sum of the squares */ int sum = 0; // MPI_Reduce(&sum_local, &sum, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Allreduce(&sum_local, &sum, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); double rms; // if (rank == 0) rms = sqrt((double)sum / (double)npixels); //MPI_Bcast(&rms, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
  • 16. Обработка изображения (contrast) /* Contrast operation on subimage */ for (int i = 0; i < npixels_per_process; i++) { int pixel = 2 * rbuf[i] - rms; if (pixel < 0) rbuf[i] = 0; else if (pixel > 255) rbuf[i] = 255; else rbuf[i] = pixel; } MPI_Gather(rbuf, npixels_per_process, MPI_UINT8_T, pixels, npixels_per_process, MPI_UINT8_T, 0, MPI_COMM_WORLD); if (rank == 0) // Save image... free(rbuf); if (rank == 0) free(pixels); MPI_Finalize(); }
  • 17. Обработка изображения (contrast)  Равномерно ли пиксели изображения распределяются по процессам? npixels_per_process = npixels / commsize;  Загрузка исходного изображения ✔ Корневой процесс загружает изображение и рассылает части остальным  (изображение может не поместиться в память одного узла) ✔ Каждый процесс загружает часть изображения (MPI I/O, NFS, Lustre)  Обработка изображения ✔ Вычисление RMS: MPI_Reduce + MPI_Bcast или MPI_Allreduce  Сохранение изображения ✔ Сборка Gather — изображение формируется в памяти процесс 0 ✔ Сборка Send/Recv — части изображения последовательно сохраняются в файл
  • 18. Домашнее чтение  Pavan Balaji, William Gropp, Torsten Hoefler, Rajeev Thakur. Advanced MPI Programming  // Tutorial at SC14, November 2014, http://www.mcs.anl.gov/~thakur/sc14-mpi-tutorial/  Torsten Hoefler. Advanced MPI 2.2 and 3.0 Tutorial //  http://htor.inf.ethz.ch/teaching/mpi_tutorials/cscs12/hoefler_tutorial_advanced-mpi-2.2-and-mpi-3.0_cscs .pdf