Message Passing Interface

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до: навігація, пошук

MPI (англ. Message Passing Interface, Інтерфейс передачі повідомлень) — це специфікація, що була розроблена в 1993–1994 роках групою MPI Forum[1],і забезпечує реалізацію моделі обміну повідомленнями між процесами. Остання версія даної специфікації: MPI-2. У моделі програмування MPI програма породжує кілька процесів, що взаємодіють між собою за допомогою звертання до підпрограм прийому і передачі повідомлень.

Зазвичай, при ініціалізації MPI-програми створюється фіксований набір процесів, причому (що, утім, необов'язково) кожний з них виконується на своєму процесорі. У цих процесах можуть виконуватися різні програми, тому MPI-модель іноді називають MPMD-моделлю (Multiple Program, Multiple Data), на відміну від SPMD моделі, де на кожному процесорі виконуються тільки однакові задачі. MPI підтримує двохточкові і глобальні, синхронні й асинхронні, блокуючі і неблокуючі типи комунікацій. Спеціальний механізм — комунікатор — ховає від програміста внутрішні комунікаційні структури. Структура комунікацій може змінюватися протягом часу життя процесу, але кількість задач повинна залишатися постійною (MPI-2 уже підтримує динамічну зміну числа задач).

Специфікація MPI забезпечує переносимість програм на рівні вихідних кодів. Підтримується робота на гетерогенних кластерах і симетричних мультипроцесорних системах. Не підтримується, як уже відзначалося, запуск процесів під час виконання MPI-програми. У специфікації відсутні опис паралельного вводу-виводу і зневадження програм — ці можливості можуть бути включені до складу конкретної реалізації MPI у виді додаткових пакетів і утиліт. Сумісність різних реалізацій не гарантується.

Важливою властивістю паралельної програми є детермінізм — програма повинна завжди давати той самий результат для того самого набору вхідних даних. Модель передачі повідомлень, загалом даною властивістю не володіє, оскільки не визначений порядок одержання повідомлень від двох процесів третім. Якщо ж один процес послідовно посилає кілька повідомлень іншому процесу, MPI гарантує, що одержувач одержить їхній саме в тому порядку, у якому вони були відправлені. Відповідальність за забезпечення детермінованого виконання програми лягає на програміста.

MPI-програма[ред.ред. код]

#include <mpi.h> // очевидно;)
#include <stdio.h>

int main(int argc, char* argv[])
{
   int myrank, size;
   MPI_Init(&argc, &argv); // Ініціалізація MPI
   MPI_Comm_size(MPI_COMM_WORLD, &size); // Розмір комунікатора
   MPI_Comm_rank(MPI_COMM_WORLD, &myrank); // Одержуємо наш номер
   printf("Proc %d of %d\n", myrank, size);
   MPI_Finalize(); // Фіналізація MPI
   puts("Done.");
   return 0;
}

Перед викликом будь-якої процедури MPI, потрібно викликати ініціалізацію MPI_Init, перед цим викликом може знаходитися тільки виклик MPI_Initialized. MPI_Init крім усього іншого створює глобальний комунікатор MPI_COMM_WORLD, через котрий буде проходити обмін повідомленнями. Область взаємодії комунікатора MPI_COMM_WORLD — усі процеси даної програми. Якщо є необхідність у розбивці області взаємодії на дрібніші сегменти (частково-широкомовні розсилання), використовуються виклики MPI_Comm_dup/create/split/etc (тут не розглядаються). Розмір комунікатора, одержуваний викликом MPI_Comm_size — число процесів у ньому. Розмір комунікатора MPI_COMM_WORLD — загальне число процесів. Кожен процес має свій унікальний у рамках комунікатора номер — ранг. Ранги процесів у контекстах різних комунікаторів можуть відрізнятися. Після виконання всіх обмінів повідомленнями в програмі повинний розташовуватися виклик MPI_Finalize() — процедура видаляє всі структури даних MPI і робить інші необхідні дії. Програміст повинний сам подбати про те, щоб до моменту виклику MPI_Finalize усі пересилання даних були довершені. Після виконання MPI_Finalize виклик будь-яких, крім MPI_Initialized, процедур (навіть MPI_Init) неможливий. Наша програма виводить повідомлення від усіх породжених нею процесів. Приклад виводу (порядок повідомлень, що надходять від процесів, може буде змінюватися) приведений нижче (np — кількість процесів):

  Proc 1 of 3
  Done.
  Proc 0 of 3
  Done.
  Proc 2 of 3
  Done.

Зверніть увагу, що після виклику MPI_Finalize() парелельна робота не закінчується — «Done» виводиться кожним процесом.

Термінологія і позначення[ред.ред. код]

Номер процесу — ціле невід'ємне число, що є унікальним атрибутом кожного процесу.
Атрибути повідомлення — номер процесу-відправника, номер процесу-одержувача і ідентифікатор повідомлення. Для них заведена структура MPI_Status, що містить три поля: MPI_Source (номер процесу відправника), MPI_Tag (ідентифікатор повідомлення), MPI_Error (код помилки); можуть бути і додаткові поля.
Ідентифікатор повідомлення (msgtag) — атрибут повідомлення, що є цілим невід'ємним числом, лежачим в діапазоні від 0 до 32767. Процеси об'єднуються в групи, можуть бути вкладені групи. Усередині групи всі процеси перенумеровані. З кожною групою асоційований свій комунікатор . Тому при здійсненні пересилання необхідно вказати ідентифікатор групи, всередині якої проводиться ця пересилка. Всі процеси містяться в групі з наперед визначеним ідентифікатором MPI_COMM_WORLD .

Стандарти MPI[ред.ред. код]

Перша версія MPI розроблялася в 1993–1994 році, і MPI 1 вийшла в 1994. Більшість сучасних реалізацій MPI підтримують версію 1.1. Стандарт MPI версії 2.0 підтримується більшістю сучасних реалізацій, але деякі функції можуть бути реалізовані не до кінця. У MPI 1.1 (опублікований 12 червня 1995 , перша реалізація з'явилася в 2002 році) підтримуються наступні функції:

  • передача і отримання повідомлень між окремими процесами;
  • колективні взаємодії процесів;
  • взаємодії в групах процесів;
  • реалізація топологій процесів;

У MPI 2.0 (опублікований 18 липня 1997) додатково підтримуються наступні функції:

  • динамічне породження процесів і управління процесами;
  • односторонні комунікації (Get / Put);
  • паралельний введення і виведення;
  • розширені колективні операції (процеси можуть виконувати колективні операції не тільки всередині одного комунікатора, але й у рамках декількох комунікаторів).

Версія MPI 2.1 вийшла на початку вересня 2008 року. Версія MPI 2.2 вийшла 4 вересня 2009. Версія MPI 3.0 вийшла 21 вересня 2012 року.

Функціонування інтерфейсу[ред.ред. код]

Базовим механізмом зв'язку між MPI процесами є передача і прийом повідомлень. Повідомлення несе в собі передані дані і інформацію, що дозволяє приймаючій стороні здійснювати їх вибірковий прийом:

  • відправник — ранг (номер у групі) відправника повідомлення;
  • одержувач — ранг одержувача;
  • ознака — може використовуватися для розділення різних видів повідомлень;
  • комунікатор — код групи процесів.

Операції прийому і передачі можуть бути блокується і неблокірующій. Для неблокірующій операцій визначені функції перевірки готовності і очікування виконання операції.

Іншим способом зв'язку є віддалений доступ до пам'яті (RMA), що дозволяє читати і змінювати область пам'яті віддаленого процесу. Локальний процес може переносити область пам'яті віддаленого процесу (всередині зазначеного процесами вікна) в свою пам'ять і назад, а також комбінувати дані, передані в віддалений процес з наявними в його пам'яті даними (наприклад, шляхом підсумовування). Всі операції віддаленого доступу до пам'яті не блокуються, однак, до і після їх виконання необхідно викликати блокуються функції синхронізації.

Реалізації MPI[ред.ред. код]

  • MPICH — найпоширеніша безкоштовна реалізація, працює на UNIX -системи і Windows NT
  • LAM / MPI — ще одна безкоштовна реалізація MPI. Підтримує гетерогенні конфігурації, LAM підтримує гетерогенні конфігурації, пакет
  • Globus і задовольняє IMPI (Interoperable MPI).
  • WMPI — реалізація MPI для Windows
  • MPI / PRO For Windows NT — комерційна реалізація для Windows NT
  • Intel MPI — комерційна реалізація для Windows / Linux
  • Microsoft MPI входить до складу Compute Cluster Pack SDK . Заснований на MPICH2, але включає додаткові засоби управління завданнями. Підтримується специфікація MPI-2.
  • HP-MPI — комерційна реалізація від HP
  • SGI MPT — платна бібліотека MPI від SGI
  • Mvapich — безкоштовна реалізація MPI для Infiniband
  • Open MPI — безкоштовна реалізація MPI, спадкоємець LAM / MPI
  • Oracle HPC ClusterTools — безкоштовна реалізація для Solaris SPARC / x86 і Linux на основі Open MPI
  • MPJ — MPI for Java
  • MPJ Express — MPI на Java

Загальні процедури MPI[ред.ред. код]

INT MPI_Init (INT * ARGC, символ *** ARGV)

MPI_Init — ініціалізація паралельної частини програми. Реальна ініціалізація для кожного додатка виконується не більше одного разу, а якщо MPI вже був инициализирован, то ніякі дії не виконуються і відбувається негайне повернення з підпрограми. Всі залишилися MPI-процедури можуть бути викликані тільки після виклику MPI_Init . Повертає: у разі успішного виконання — MPI_SUCCESS, інакше — код помилки. (Те ж саме повертають і всі інші функції, що розглядаються в даному керівництві.)

INT MPI_Finalize (недійсними)

MPI_Finalize — завершення паралельної частини програми. Всі наступні звернення до будь MPI-процедурам, у тому числі до MPI_Init, заборонені. До моменту виклику MPI_Finalize деяким процесом всі дії, що вимагають його участі в обміні повідомленнями, повинні бути завершені.


int MPI_Comm_size(MPI_Comm comm, int* size)

Определение общего числа параллельных процессов в группе comm.

  • comm — идентификатор группы
  • OUT size — размер группы

Прийом / передача повідомлень між окремими процесами[ред.ред. код]

Прийом / передача повідомлень з блокуванням[ред.ред. код]

int MPI_Send(void* buf, int count, MPI_Datatype datatype, int dest, int msgtag, MPI_Comm comm)

  • buf — адреса початку буфера посилки повідомлення
  • count — число переданих елементів у повідомленні
  • datatype — тип переданих елементів
  • dest — номер процесу-одержувача
  • msgtag — ідентифікатор повідомлення
  • comm — ідентифікатор групи

Блокуюча посилка повідомлення з ідентифікатором msgtag, що складається з count елементів типу datatype, процесу з номером dest . Всі елементи повідомлення розташовані поспіль в буфері buf . Значення count може бути нулем. Тип переданих елементів datatype повинен вказуватися за допомогою зумовлених констант типу. Дозволяється передавати повідомлення самому собі.

Блокування гарантує коректність повторного використання всіх параметрів після повернення з підпрограми. Вибір способу здійснення цієї гарантії: копіювання в проміжний буфер або безпосередня передача процесу dest, залишається за MPI. Слід спеціально зазначити, що повернення з підпрограми MPI_Send значить ні того, що повідомлення вже передано процесу dest, ні того, що повідомлення покинуло процесорний елемент, на якому виконується процес, який виконав MPI_Send

Прийом / передача повідомлень без блокування[ред.ред. код]

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

Передача повідомлення, аналогічна MPI_Send, проте повернення з підпрограми відбувається відразу після ініціалізації процесу передачі без очікування обробки всього повідомлення, що у буфері buf . Це означає, що не можна повторно використовувати даний буфер для інших цілей без отримання додаткової інформації про завершення даної посилки. Закінчення процесу передачі (тобто того моменту, коли можна перевикористати буфер buf без побоювання зіпсувати передане повідомлення) можна визначити за допомогою параметра request і процедур MPI_Wait і MPI_Test . Повідомлення, відправлене будь-який з процедур MPI_Send і MPI_Isend, може бути прийняте будь-який з процедур MPI_Recv і MPI_Irecv

Синхронізація процесів[ред.ред. код]

INT MPI_Barrier (MPI_Comm комм)

  • comm — ідентифікатор групи

Блокує роботу процесів, що викликали дану процедуру, до тих пір, поки всі залишилися процеси групи comm також не виконають цю процедуру.

Визначені константи[ред.ред. код]

Константы MPI Тип в C
MPI_CHAR signed char
MPI_SHORT signed int
MPI_INT signed int
MPI_LONG signed long int
MPI_UNSIGNED_CHAR unsigned char
MPI_UNSIGNED_SHORT unsigned int
MPI_UNSIGNED unsigned int
MPI_FLOAT float

Див. також[ред.ред. код]

Примітки[ред.ред. код]

Посилання[ред.ред. код]


Комп'ютер Це незавершена стаття про комп'ютери.
Ви можете допомогти проекту, виправивши або дописавши її.