Interfața de transmitere a mesajelor (MPI, interfața de transmitere a mesajelor) este o interfață de programare ( API ) pentru transferul de informații , care vă permite să faceți schimb de mesaje între procesele care îndeplinesc aceeași sarcină. Proiectat de William Groupe , Evin Lusk și alții.
MPI este cel mai comun standard de interfață de schimb de date în programarea paralelă și există implementări pentru un număr mare de platforme de computer. Folosit în dezvoltarea de programe pentru clustere și supercalculatoare . Principalul mijloc de comunicare între procese în MPI este transmiterea de mesaje unul către celălalt.
MPI este standardizat de Forumul MPI . Standardul MPI descrie o interfață de transmitere a mesajelor care trebuie să fie suportată atât pe platformă, cât și în aplicațiile utilizatorului . În prezent, există un număr mare de implementări gratuite și comerciale ale MPI. Există implementări pentru Fortran 77/90, Java , C și C++ .
MPI este orientat în primul rând către sisteme de memorie distribuită , adică atunci când costurile de transfer de date sunt mari, în timp ce OpenMP este orientat către sisteme de memorie partajată (multi-core cu cache partajat). Ambele tehnologii pot fi utilizate împreună pentru a utiliza în mod optim sistemele multi-core dintr-un cluster.
Prima versiune a MPI a fost dezvoltată în 1993-1994, iar MPI 1 a apărut în 1994.
Cele mai multe implementări MPI moderne acceptă versiunea 1.1. Standardul MPI versiunea 2.0 este acceptat de majoritatea implementărilor moderne, cu toate acestea, este posibil ca unele caracteristici să nu fie pe deplin implementate.
MPI 1.1 (publicat la 12 iunie 1995 , implementat pentru prima dată în 2002) acceptă următoarele caracteristici:
În MPI 2.0 (publicat la 18 iulie 1997 ) sunt acceptate suplimentar următoarele caracteristici:
MPI 2.1 a fost lansat la începutul lunii septembrie 2008.
MPI 2.2 a fost lansat pe 4 septembrie 2009.
MPI 3.0 a fost lansat pe 21 septembrie 2012.
Mecanismul de bază pentru comunicarea între procesele MPI este transmiterea și recepția mesajelor. Mesajul transportă datele și informațiile transmise care permit părții destinatare să le primească selectiv:
Operațiunile de trimitere și primire pot fi blocante sau neblocante. Pentru operațiunile neblocante sunt definite funcțiile de verificare a pregătirii și de așteptare a executării operației.
O altă metodă de comunicare este accesul la memorie la distanță (RMA), care vă permite să citiți și să modificați zona de memorie a unui proces de la distanță. Procesul local poate transfera zona de memorie a procesului de la distanță (în interiorul ferestrei specificate de procese) în memoria sa și înapoi, precum și poate combina datele transferate către procesul de la distanță cu datele disponibile în memoria acestuia (de exemplu , prin însumare). Toate operațiunile de acces la memorie la distanță sunt neblocante, totuși, funcțiile de sincronizare de blocare trebuie apelate înainte și după efectuarea lor.
Următorul este un exemplu de program de calcul al numărului C folosind MPI :
// Includeți anteturile necesare #include <stdio.h> #include <math.h> // Inclusiv fișierul antet MPI #include "mpi.h" // Funcție pentru calcule intermediare double f ( double a ) { întoarcere ( 4,0 / ( 1,0 + a * a )); } // Funcția principală a programului int main ( int argc , char ** argv ) { // Declarația variabilelor int done = 0 , n , myid , numprocs , i ; dublu PI25DT = 3,141592653589793238462643 ; dublu mypi , pi , h , sum , x ; dublu startwtime = 0,0 , endwtime ; int namelen ; char procesor_name [ MPI_MAX_PROCESSOR_NAME ]; // Inițializează subsistemul MPI MPI_Init ( & argc , & argv ); // Obține dimensiunea comunicatorului MPI_COMM_WORLD // (numărul total de procese din cadrul sarcinii) MPI_Comm_size ( MPI_COMM_WORLD , & numprocs ); // Obține numărul procesului curent din // comunicatorul MPI_COMM_WORLD MPI_Comm_rank ( MPI_COMM_WORLD , & myid ); MPI_Get_processor_name ( nume_procesor , & namelen ); // Imprimă numărul firului de execuție în pool-ul partajat fprintf ( stdout , "Procesul %d din %d este pe %s \n " , myid , numprocs , procesor_name ); fflush ( stdout ); în timp ce ( ! terminat ) { // numărul de intervale if ( myid == 0 ) { fprintf ( stdout , „Introduceți numărul de intervale: (0 iese)” ); fflush ( stdout ); if ( scanf ( " %d " , & n ) != 1 ) { fprintf ( stdout , „Niciun număr introdus; renunțarea \n ” ); n = 0 _ } startwtime = MPI_Wtime (); } // Difuzați numărul de intervale către toate procesele (inclusiv noi înșine) MPI_Bcast ( & n , 1 , MPI_INT , 0 , MPI_COMM_WORLD ); dacă ( n == 0 ) gata = 1 ; altfel { h = 1,0 / ( dublu ) n ; suma = 0,0 ; // Calculați punctul alocat procesului pentru ( i = myid + 1 ; ( i <= n ) ; i += numprocs ) { x = h * (( dublu ) i - 0,5 ); suma += f ( x ); } mypi = h * suma ; // Resetați rezultatele din toate procesele și adăugați MPI_Reduce ( & mypi , & pi , 1 , MPI_DOUBLE , MPI_SUM , 0 , MPI_COMM_WORLD ); // Dacă acesta este procesul principal, imprimați rezultatul dacă ( myid == 0 ) { printf ( "PI este de aproximativ %.16lf, Eroare este %.16lf \n " , pi , fabs ( pi - PI25DT )); endwtime = MPI_Wtime (); printf ( "ora ceasului de perete =%lf \n " , ora de terminare - ora de pornire ); fflush ( stdout ); } } } // Eliberează subsistemul MPI MPI_Finalize (); returnează 0 ; }distribuit și paralel | Software pentru calcul|
---|---|
Standarde, biblioteci | |
Software de monitorizare | |
Software de control |