Loading AI tools
З Вікіпедії, вільної енциклопедії
MPI (англ. Message Passing Interface, Інтерфейс передачі повідомлень) — це специфікація, що була розроблена в 1993–1994 роках групою MPI Forum[1],і забезпечує реалізацію моделі обміну повідомленнями між процесами. Остання версія цієї специфікації: MPI-2. У моделі програмування MPI програма породжує кілька процесів, що взаємодіють між собою за допомогою виклику підпрограм прийому й передачі повідомлень.
Зазвичай, при ініціалізації MPI-програми створюється фіксований набір процесів, причому (що, утім, необов'язково) кожний з них виконується на своєму процесорі. У цих процесах можуть виконуватися різні програми, тому MPI-модель іноді називають MIMD-моделлю (Multiple Instruction, Multiple Data), на відміну від SIMD моделі, де на кожному процесорі виконуються тільки однакові задачі. MPI підтримує двохточкові й глобальні, синхронні й асинхронні, блокуючі й неблокуючі типи комунікацій. Спеціальний механізм — комунікатор — ховає від програміста внутрішні комунікаційні структури. Структура комунікацій може змінюватися протягом часу життя процесу, але кількість задач має залишатися постійною (MPI-2 підтримує динамічну зміну кількості задач).
Специфікація 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_COMM_WORLD .
Перша версія MPI розроблялася в 1993–1994 році, і MPI 1 вийшла в 1994. Більшість сучасних реалізацій MPI підтримують версію 1.1. Стандарт MPI версії 2.0 підтримується більшістю сучасних реалізацій, але деякі функції можуть бути реалізовані не до кінця. У MPI 1.1 (опублікований 12 червня 1995 , перша реалізація з'явилася в 2002 році) підтримуються наступні функції:
У MPI 2.0 (опублікований 18 липня 1997) додатково підтримуються наступні функції:
Версія MPI 2.1 вийшла на початку вересня 2008 року. Версія MPI 2.2 вийшла 4 вересня 2009. Версія MPI 3.0 вийшла 21 вересня 2012 року.
Базовим механізмом зв'язку між MPI процесами є передача і прийом повідомлень. Повідомлення несе в собі передані дані і інформацію, що дозволяє приймаючій стороні здійснювати їх вибірковий прийом:
Операції прийому й передачі можуть бути блокуючі і неблокуючі. Для неблокуючих операцій визначені функції перевірки готовності й очікування виконання операції.
Іншим способом зв'язку є віддалений доступ до пам'яті (RMA), що дозволяє читати і змінювати область пам'яті віддаленого процесу. Локальний процес може переносити область пам'яті віддаленого процесу (всередині зазначеного процесами вікна) в свою пам'ять і назад, а також комбінувати дані, передані у віддалений процес, з наявними в його пам'яті даними (наприклад, шляхом підсумовування). Всі операції віддаленого доступу до пам'яті не блокуються, однак, до і після їх виконання необхідно викликати блокуючі функції синхронізації.
int MPI_Init (INT * ARGC, char *** ARGV)
MPI_Init — ініціалізація паралельної частини програми. Реальна ініціалізація для кожного додатка виконується не більше одного разу, а якщо MPI вже був ініціалізований, то ніякі дії не виконуються і відбувається негайне повернення з підпрограми. Всі інші MPI-процедури можуть бути викликані тільки після виклику MPI_Init .
Повертає: у разі успішного виконання — MPI_SUCCESS, інакше — код помилки. (Те ж саме повертають і всі інші функції MPI_*, вказані нижче)
int MPI_Finalize (void)
MPI_Finalize — завершення паралельної частини програми. Всі наступні звернення до будь-яких MPI-процедур (зокрема — до MPI_Init) заборонено. До моменту виклику якимось процесом MPI_Finalize має бути завершено всі дії, що вимагають його участі в обміні повідомленнями.
int MPI_Comm_size(MPI_Comm comm, int* size)
Показує розмір (кількість паралельних процесів) групи, асоційованої з комунікатором
int MPI_Send(void* buf, int count, MPI_Datatype datatype, int dest, int msgtag, MPI_Comm comm)
Блокуюче надсилання повідомлення з ідентифікатором msgtag, що складається з count елементів типу datatype, процесу з номером dest . Всі елементи повідомлення розташовані поспіль в буфері buf . Значення count може бути нулем. Тип переданих елементів datatype повинен вказуватися за допомогою зумовлених констант типу. Дозволяється передавати повідомлення самому собі.
Блокування гарантує коректність повторного використання всіх параметрів після повернення з підпрограми. Вибір способу здійснення цієї гарантії: копіювання в проміжний буфер або безпосередня передача процесу dest, залишається за MPI. Слід спеціально зазначити, що повернення з підпрограми MPI_Send не значить ні того, що повідомлення вже передано процесу dest, ні навіть того, що повідомлення залишило процесор, з якого його було надіслано.
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 |
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.