Elementele de bază ale programării în standardul mpi

3.2 Bazele programării în cadrul standardului MPI

Fiecare proces paralel al programului este generat pe baza unei copii a aceluiași cod de program (model SPMP - Procese Multiple Multiple). Acest cod de program, reprezentat ca un program executabil, ar trebui să fie disponibil atunci când programul paralel este rulat pe toate procesoarele utilizate. Codul sursă pentru programul executabil este dezvoltat în limbi algoritmice C sau Fortran utilizând una sau o altă implementare a bibliotecii MPI.

Numărul de procese și numărul de procesoare utilizate este definit în timpul rulării prin intermediul mediului de execuție program paralel și MPI-programe în cursul calculelor nu se pot schimba (standard MPI-2 oferă posibilitatea de a modifica dinamic numărul de procese). Toate procesele de program sunt numerotate secvențial de la 0 la p-1, unde p este numărul total de procese. Numărul procesului este menționat ca grad de proces.

În acest caz, pentru a se evita calculele de identitate pe procesoare diferite, este posibil, în primul rând, să înlocuiască date diferite pe procesoare diferite, software-ul, și în al doilea rând, prin mijloace de identificare a procesului care se execută programul și, prin urmare, având în vedere posibilitatea de a Pentru a organiza diferențe în calcule în funcție de procesorul folosit de program.

Acest lucru vă permite să încărcați subtask-ul în funcție de "numărul" procesorului. În acest caz, problema inițială este împărțită în subtascuri (descompunere). O tehnică comună este după cum urmează: fiecare dintre sarcinile secundare este emis sub forma unei unități structurale (modul funcție) separat pe toate procesoarele rula același program de „furcă“, care, în conformitate cu „numerele“ ale procesorului încarcă un anumit subactivitate.

Oferim setul minim necesar de funcții MPI, suficient pentru dezvoltarea unor programe paralele relativ simple.

Cel mai simplu program MPI.

Luați în considerare o versiune paralelă a unui exemplu de program demo "Hello world", utilizat pe scară largă. Pe lângă mesajul obișnuit, fiecare proces va tipări numărul și numărul total de procese.

# includ
# include "mpi.h"
int principal (int argc. char * argv [])
<
int procs_rank. procs_count;
MPI_Init ( argc. argv);
// Inițializați biblioteca MPI
MPI_Comm_size (MPI_COMM_WORLD. procs_count);
// determinați numărul de procese
MPI_Comm_rank (MPI_COMM_WORLD. procs_rank);
// aflați rangul procesului
printf ("\ n Bună ziua. Lumea din procesul% 3 din% 3 d." procs_rank.procs_count);
MPI_Finalizare ();
// închideți biblioteca MPI
retur 0;
>

Să analizăm în detaliu un exemplu:

Mai întâi, fișierul antet pentru biblioteca "mpi.h" este conectat. Acesta conține definiții ale funcțiilor, tipurilor și constantelor MPI. Acest fișier trebuie să fie inclus în toate modulele care utilizează MPI.

Primul din fiecare program MPI ar trebui să fie apelul către MPI_Init. care trebuie să fie prezent în fiecare program MPI și precede toate celelalte apeluri MPI. Se stabilește mediul MPI. Doar un singur acces la MPI_Init este permis în execuția programului. Argumentele sale sunt numărul de argumente ale liniei de comandă de proces și linia de comandă a procesului propriu-zis.

int MPI_Init (int * argc. char *** argv)

  • argc - un indicator pentru numărul de parametri ai liniei de comandă;
  • argv - parametrii liniei de comandă.

Funcția MPI_Comm_size returnează numărul proceselor care rulează pentru acest program în procs_count. Modul în care utilizatorul execută aceste procese depinde de implementare, dar orice program poate determina numărul de procese care rulează utilizând acest apel. Valoarea procs_count este, de fapt, dimensiunea grupului asociat cu comunicatorul MPI_COMM_WORLD. Procesele fiecărui grup sunt numerotate de numere întregi, începând cu 0. Acestea se numesc rang. Fiecare proces determină numărul său în grupul asociat cu acest comunicator, utilizând MPI_Comm_rank. Astfel, fiecare proces primește același număr în procs_count. dar numere diferite în rang. Fiecare proces își imprimă rangul și numărul total de procese care rulează, apoi toate procesele efectuează MPI_Finalize. Această funcție trebuie să fie efectuată de fiecare proces MPI și duce la eliminarea "mediului" MPI. Nici un apel MPI nu poate fi efectuat de proces după ce a sunat MPI_Finalize (nu este, de asemenea, posibilă o repetare MPI_Init).

Funcție pentru a determina numărul de procese din zona de comunicare MPI_Comm_size.

int MPI_Comm_size (dimensiune MPI_Comm comm int *)

unde comm este comunicatorul, mărimea este numărul de procese din aria de comunicație a comunicatorului com.

Funcția de determinare a numărului de proces MPI_Comm_rank.

int MPI_Comm_rank (cod MPI_Comm int *)

unde comm este comunicatorul, rangul este numărul procesului care apelează funcția.

Funcția finalizării MPI MPI_Finalize nu are parametri.

int MPI_Finalizare (void)

Luați în considerare rezultatul acestui program pentru două procese.

Cele două opțiuni sunt obținute deoarece ordinea în care apar mesajele text este determinată de care dintre procesele pe care operatorul de imprimare le va efectua înainte, ceea ce este în general dificil de prevăzut în avans. O posibilă soluție la această problemă, care va fi discutată mai târziu, este de a colecta datele într-unul din procese și apoi de a le transmite.

Determinarea duratei de execuție a programului MPI

Aproape imediat după elaborarea primelor programe paralele este necesar să se determine timpul de execuție al calculelor pentru a evalua accelerația realizată a proceselor de rezolvare a problemelor prin utilizarea paralelismului. De obicei, instrumentele pentru măsurarea duratei de funcționare a programelor depind, de regulă, de platforma hardware, de sistemul de operare, de limbajul algoritmic și așa mai departe. Standardul MPI include definirea funcțiilor speciale pentru măsurarea timpului, utilizarea cărora permite eliminarea dependenței de mediul de execuție a programelor paralele. Primirea timpului curent este asigurată de funcția:

dublu MPI_Wtime (void);

rezultatul numirii este numărul de secunde care au trecut de la un anumit moment în timp în trecut. Acest punct în timp, din care secundele de numărare, poate depinde de punerea în aplicare a mediului de bibliotecă MPI, și, astfel, să scape de o astfel de funcție dependență MPI_Wtime trebuie utilizat numai pentru a determina durata executării unor fragmente de cod programe paralele. Schema posibila pentru aplicarea functiei MPI_Wtime poate fi urmatoarea:

<
timp de pornire dublă. ENDTIME;
starttime = MPI_Wtime ();
// Unele operații
endtime = MPI_Wtime ();
printf ("Timp de lucru% f sec \ n" .endtime - starttime);
>

Precizia măsurării timpului poate, de asemenea, să depindă de mediul de execuție al programului paralel. Pentru a determina valoarea actuală a preciziei, se poate folosi o funcție:

dublu MPI_Wtick (vid);

Permite determinarea timpului în secunde între doi indici de timp consecutivi ai cronometrului hardware al sistemului informatic folosit.