MPI aansluiten in Visual Studio

Toevallig kreeg ik te maken met de studie van parallel computing en in het bijzonder MPI. Misschien is deze richting vandaag veelbelovend, dus ik wil de habray-gebruiker de basis van dit proces laten zien.

Basisprincipes en voorbeeld
De berekening van exponent (e) wordt als voorbeeld gebruikt. Een van de opties om het te vinden is de Taylor-reeks:
e ^ x = ∑ ((x ^ n) / n!), waarbij de sommatie van n = 0 tot oneindig is.

Deze formule kan gemakkelijk worden geparallelliseerd, aangezien het vereiste aantal de som van individuele termen is, en hierdoor kan elke individuele processor de individuele termen berekenen.

Het aantal termen dat in elke individuele processor zal worden berekend, hangt zowel af van de lengte van het interval n als van het beschikbare aantal processors k dat aan het rekenproces kan deelnemen. Als de lengte van het interval bijvoorbeeld n = 4 is en er zijn vijf processors (k = 5) betrokken bij de berekeningen, dan krijgen de eerste tot de vierde processors elk één term en de vijfde niet betrokken. Als n = 10 en k = 5, krijgt elke processor twee termen om te berekenen.

Aanvankelijk gebruikt de eerste processor de uitzendfunctie MPI_Bcast om de anderen de waarde van de door de gebruiker gespecificeerde variabele n te sturen. Over het algemeen heeft de functie MPI_Bcast het volgende formaat:
int MPI_Bcast (void * buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm), waarbij buffer het adres is van de buffer met het element, count is het aantal elementen, datatype is het corresponderende datatype in MPI, root is de rangorde van de zending van de hoofdverwerker, en comm is de naam van de communicator.
In mijn geval, zoals eerder vermeld, zal de eerste processor met rang 0 fungeren als de hoofdprocessor.

Daarna wordt het nummer n met succes verzonden, elke processor begint zijn voorwaarden te berekenen. Hiervoor wordt bij elke stap van de cyclus het getal i, dat in eerste instantie gelijk is aan de rang van de processor, aangevuld met een getal gelijk aan het aantal processors dat aan de berekeningen deelneemt. Als het getal in de volgende stappen het getal n overschrijdt dat door de gebruiker is opgegeven, stopt de lusuitvoering voor deze processor.

Tijdens de uitvoering van de cyclus worden de termen toegevoegd aan een aparte variabele en na voltooiing wordt het resulterende bedrag naar de hoofdprocessor gestuurd. Hiervoor wordt de functie MPI_Reduce van de cast-bewerking gebruikt. In het algemeen ziet het er als volgt uit:
int MPI_Reduce (void * buf, void * result, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm)

Het voegt de elementen van de invoerbuffer van elk proces in de groep samen met behulp van de bewerking op en retourneert de aaneengeschakelde waarde naar de uitvoerbuffer van de procesgenummerde root. Het resultaat van een dergelijke bewerking is een enkele waarde, daarom heeft de cast-functie zijn naam gekregen.

Nadat het programma op alle processors is uitgevoerd, ontvangt de eerste processor de totale som van de termen, wat de exponentwaarde is die we nodig hebben.

Opgemerkt moet worden dat zowel in parallelle als sequentiële methoden voor het berekenen van de exponent, een recursieve functie wordt gebruikt om de faculteit te vinden. Bij het nemen van een beslissing over de methode om de uitgevoerde taak parallel te laten lopen, overwoog ik de mogelijkheid om de faculteit ook op verschillende processors te vinden, maar uiteindelijk werd deze optie door mij als irrationeel beschouwd.

De primaire taak is nog steeds om de waarde van de exponent te vinden, en als de processors elke faculteit van elke term afzonderlijk beginnen te berekenen, kan dit leiden tot het tegenovergestelde effect, namelijk een aanzienlijk verlies in prestaties en rekensnelheid.
Dit wordt verklaard door het feit dat in dit geval een zeer grote belasting van de communicatieomgeving begint, die al vaak een zwakke schakel is in parallelle computersystemen. Als de berekening van de faculteit op elke processor privé plaatsvindt, zal de belasting van de communicatielijnen minimaal zijn. Dit geval kan een goed voorbeeld worden genoemd van het feit dat het parallellisatieprobleem soms zijn grenzen moet hebben.

Algoritme van code-uitvoering
1. De waarde van het getal n wordt vanuit de visuele shell naar het programma verzonden, dat vervolgens met behulp van de uitzendfunctie naar alle processors wordt verzonden.
2. Wanneer de eerste hoofdprocessor wordt geïnitialiseerd, wordt een timer gestart.
3. Elke processor voert een cyclus uit, waarbij de toename het aantal processors in het systeem is. In elke iteratie van de lus wordt een term berekend en de som van dergelijke termen wordt opgeslagen in de variabele drobSum.
4. Na het einde van de cyclus voegt elke processor zijn drobSum-waarde toe aan de Result-variabele met behulp van de MPI_Reduce cast-functie.
5. Nadat de berekeningen op alle processors zijn voltooid, stopt de eerste hoofdprocessor de timer en stuurt de resulterende waarde van de variabele Resultaat naar de uitvoerstroom.
6. De door onze timer gemeten tijdwaarde in milliseconden wordt ook naar de uitvoerstroom gestuurd.
Codelijst
Het programma is geschreven in C++, we nemen aan dat de argumenten voor uitvoering vanuit de buitenste schil worden doorgegeven. De code ziet er als volgt uit:
#erbij betrekken "mpi.h"
#erbij betrekken
#erbij betrekken
namespace std; gebruiken;

dubbel feit (int n)
{
als (n == 0)
retour 1;
anders
retourneer n * Feit (n-1);
}

int hoofd (int argc, char * argv)
{
SetConsoleOutputCP (1251);
int n;
int myid;
int numproc;
int ik;
int rc;
lange dubbele drob, drobSum = 0, Resultaat, som;
dubbele starttijd = 0.0;
dubbele eindtijd;

N = atoi (argv);

if (rc = MPI_Init (& argc, & argv))
{
cout<< "Opstartfout, uitvoering gestopt" << endl;
MPI_Afbreken (MPI_COMM_WORLD, rc);
}

MPI_Comm_size (MPI_COMM_WORLD, & numprocs);
MPI_Comm_rank (MPI_COMM_WORLD, & mijnid);

als (mijnid == 0)
{

Starttijd = MPI_Wtijd ();
}
MPI_Bcast (& n, 1, MPI_INT, 0, MPI_COMM_WORLD);

voor (i = myid; i<= n; i += numprocs)
{
drob = 1 / Feit (i);
drobSum + = drob;
}

MPI_Reduce (& drobSum, & Resultaat, 1, MPI_LONG_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
cout.precisie (20);
als (mijnid == 0)
{
cout<< Result << endl;
eindtijd = MPI_Wtijd ();
cout<< (endwtime-startwtime)*1000 << endl;
}

MPI_Finalize ();
retourneer 0;
}


* Deze broncode is gemarkeerd met Source Code Highlighter.
Uitgang:
Zo kregen we een eenvoudig programma om de exponent te berekenen met meerdere processors tegelijk. Waarschijnlijk is het knelpunt de opslag van het resultaat zelf, want met een toename van het aantal cijfers zal het niet triviaal zijn om een ​​waarde te bevatten met behulp van standaardtypen, en deze plaats vereist uitwerking. Misschien is een nogal rationele oplossing om het resultaat naar een bestand te schrijven, hoewel je, gezien de puur educatieve functie van dit voorbeeld, je hier niet speciaal op kunt concentreren.

Parallellisatie in C
Voorbeeld 3b... Parallellisatie in Fortran
Voorbeeld 4a... De kenmerken van de systeemtimer in de C-taal bepalen
Voorbeeld 4b... De kenmerken van de systeemtimer in Fortran . definiëren

1.4. Berichten verzenden en ontvangen tussen afzonderlijke processen

1.4.1. Punt-tot-punt bewerkingen

1.4.2. Geblokkeerde berichten verzenden en ontvangen

Voorbeeld 5a... Uitwisseling van berichten van twee processen in C-taal
Voorbeeld 5b... Fortran-berichten tussen twee processen
Voorbeeld 6a... Berichten van oneven en even processen in C-taal
Voorbeeld 6b... Fortran-berichten van oneven en even processen
Voorbeeld 7a... Doorsturen naar een niet-bestaand C-proces
Voorbeeld 7b... Doorsturen naar een niet-bestaand Fortran-proces
Voorbeeld 8a... Gebufferde C-gegevens verzenden
Voorbeeld 8b... Gebufferde gegevensoverdracht in Fortran-taal
Voorbeeld 9a... Informatie krijgen over berichtkenmerken in C-taal
Voorbeeld 9b... Informatie krijgen over berichtkenmerken in de Fortran-taal
Voorbeeld 10a... Bepalen van latentie en bandbreedte in C
Voorbeeld 10b... Latentie en bandbreedte bepalen in Fortran-taal

1.4.3. Berichten verzenden en ontvangen zonder te blokkeren

Voorbeeld 11a... Ringwisseling met niet-blokkerende C-bewerkingen
Voorbeeld 11b... Ringuitwisseling met Fortran niet-blokkerende operaties
Voorbeeld 12a... Communicatieschema "master - werknemers" in C-taal
Voorbeeld 12b... Communicatieschema "meester - arbeiders" in Fortran
Voorbeeld 13a... Matrixtranspositie in C-taal
Voorbeeld 13b... Fortran matrix transponeren

1.4.4. Uitgestelde interactieverzoeken

Voorbeeld 14a... Schema van een iteratieve methode met uitwisseling over een ringtopologie met behulp van uitgestelde zoekopdrachten in C
Voorbeeld 14b... Schema van een iteratieve methode met uitwisseling via een ringtopologie met behulp van uitgestelde zoekopdrachten in Fortran

1.4.5. Impasse

Voorbeeld 15a... Ringtopologie-uitwisseling met behulp van de MPI_Sendrecv C-procedure
Voorbeeld 15b... Ringtopologie-uitwisseling met behulp van de MPI_SENDRECV Fortran-procedure

1.5. Collectieve procesinteracties

1.5.1. Algemene bepalingen

1.5.2. Barrière

Voorbeeld 16a... C Modelleringsbarrière-synchronisatie
Voorbeeld 16b... Fortran Barrière Synchronisatie Modellering

1.5.3. Collectieve gegevensoverdracht

1.5.4. Globale operaties

Voorbeeld 17a... Modellering van globale sommatie met behulp van het verdubbelingsschema en de collectieve bewerking MPI_Reduce in C
Voorbeeld 17b... Modellering van globale sommatie met behulp van het verdubbelingsschema en de collectieve bewerking MPI_Reduce in Fortran

1.5.5. Aangepaste wereldwijde bewerkingen

Voorbeeld 18a... Aangepaste globale C-functie
Voorbeeld 18b... Aangepaste globale Fortran-functie

1.6. Groepen en communicatoren

1.6.1. Algemene bepalingen

1.6.2. Bewerkingen met procesgroepen

Voorbeeld 19a... Werken met C-groepen
Voorbeeld 19b... Werken met groepen in de Fortran-taal

1.6.3. Bewerkingen met communicators

Voorbeeld 20a... Een C-communicator partitioneren
Voorbeeld 20b... Een Fortran-communicator partitioneren
Voorbeeld 21a... C-processen hernummeren
Voorbeeld 21b... Hernummeringsprocessen in Fortran

1.6.4. Intercommunicatoren

Voorbeeld 22a... Schema "master - werkers" met behulp van de intercommunicator in C-taal
Voorbeeld 22b... Master-Worker-schema met behulp van een Fortran-intercommunicator

1.6.5. attributen

1.7. Virtuele topologieën

1.7.1. Algemene bepalingen

1.7.2. Cartesiaanse topologie

1.7.3. Grafiektopologie

Voorbeeld 23a... Schema "master - werkers" met behulp van grafiektopologie in de C-taal
Voorbeeld 23b... Master-Worker-schema met behulp van grafiektopologie in Fortran

1.8. Overdracht van verschillende soorten gegevens

1.8.1. Algemene bepalingen

1.8.2. Afgeleide gegevenstypen

Voorbeeld 24a... Permutatie van matrixkolommen in omgekeerde volgorde in C
Voorbeeld 24b... Herschik matrixkolommen in omgekeerde volgorde in Fortran

1.8.3. Gegevens inpakken:

Voorbeeld 25a... Verpakte gegevens verzenden in C
Voorbeeld 25b... Verpakte gegevens doorsturen in Fortran-taal

1.9. Info-object

1.9.1. Algemene bepalingen

1.9.2. Werken met het info-object

1.10. Dynamische procesbesturing

1.10.1. Algemene bepalingen

1.10.2 paaiprocessen

meester.c
slaaf.c
Voorbeeld 26a. Master-Worker-schema met behulp van C-processpawning
meester.f
slaaf.f
Voorbeeld 26b. Master-Worker-schema met behulp van Fortran Process Spawning

1.10.3. Client-server communicatie

server.c
klant.c
Voorbeeld 27a. Gegevensuitwisseling tussen server en client met een openbare naam in C-taal
server.f
klant.f
Voorbeeld 27b. Uitwisseling van gegevens tussen server en client met een openbare naam in Fortran-taal

1.10.4. Een proceskoppeling verwijderen

1.10.5. Communicatie via stopcontacten

1.11. Eenrichtingscommunicatie

1.11.1. Algemene bepalingen

1.11.2. Werken met een raam

1.11.3. Data overdracht

1.11.4. Synchronisatie

Voorbeeld 28a
Voorbeeld 28b
Voorbeeld 29a... Ringtopologie-uitwisseling met eenrichtings C-communicatie
Voorbeeld 29b... Ringtopologie-uitwisseling met Fortran eenrichtingscommunicatie
Voorbeeld 30a... Ringtopologie-uitwisseling met eenrichtings C-communicatie
Voorbeeld 30b... Ringtopologie-uitwisseling met Fortran eenrichtingscommunicatie

1.12. Externe interfaces

1.12.1. gegeneraliseerde zoekopdrachten

1.12.2. Statusinformatie

1.12.3. Draden

1.13. Parallelle I/O

1.13.1. definities

1.13.2. Werken met bestanden

1.13.3. Toegang tot de gegevens

Voorbeeld 31a... Gebufferd C-bestand lezen
Voorbeeld 31b... Fortran gebufferd bestand lezen
Voorbeeld 32a... Collectief lezen uit bestand in C-taal
Voorbeeld 32b... Collectief lezen uit een bestand in Fortran

1.14. Foutverwerking

1.14.1. Algemene bepalingen

1.14.2. Communicator-gerelateerde foutafhandelaars

1.14.3. Venstergerelateerde foutafhandelingen

1.14.4. Bestandsgerelateerde foutafhandelaars

1.14.5. Aanvullende procedures

1.14.6. Foutcodes en klassen

1.14.7. Foutafhandelaars aanroepen

Voorbeeld 33a... C foutafhandeling
Voorbeeld 33b... Foutafhandeling in Fortran

Hoofdstuk 2 OpenMP parallelle programmeertechnologie

2.1. Invoering

2.2. Basisconcepten

2.2.1. Het programma samenstellen

Voorbeeld 34a... C voorwaardelijke compilatie
Voorbeeld 34b
Voorbeeld 34c... Fortran voorwaardelijke compilatie

2.2.2. Parallel programmamodel

2.2.3. Richtlijnen en procedures

2.2.4. Programma uitvoering

2.2.5. Tijdmeting

Voorbeeld 35a... Werken met systeemtimers in C-taal
Voorbeeld 35b... Werken met systeemtimers in Fortran-taal

2.3. Parallelle en opeenvolgende regio's

2.3.1. Parallelle richtlijn

Voorbeeld 36a... Parallelle regio in C-taal
Voorbeeld 36b... Parallelle regio in Fortran-taal
Voorbeeld 37a... C reductie optie
Voorbeeld 37b... Reductieoptie in Fortran-taal

2.3.2. verkorte notatie

2.3.3. Omgevingsvariabelen en hulpprocedures

Voorbeeld 38a... De routine omp_set_num_threads en de optie num_threads in C
Voorbeeld 38b... Omp_set_num_threads procedure en num_threads optie in Fortran
Voorbeeld 39a... C-routines omp_set_dynamic en omp_get_dynamic
Voorbeeld 39b... Fortran-routines omp_set_dynamic en omp_get_dynamic
Voorbeeld 40a... Geneste parallelle regio's in C
Voorbeeld 40b... Fortran geneste parallelle regio's
Voorbeeld 41a... Comp_in_parallel functie
Voorbeeld 41b... Omp_in_parallel Fortran-functie

2.3.4. Enkele richtlijn

Voorbeeld 42a... C enkele richtlijn en nu optie
Voorbeeld 42b... Fortran enkele richtlijn en nu optie
Voorbeeld 43a... C copyprivate optie
Voorbeeld 43b... Fortran copyprivate optie

2.3.5. Hoofdrichtlijn

Voorbeeld 44a... C hoofdrichtlijn
Voorbeeld 44b... Fortran hoofdrichtlijn

2.4. Gegevensmodel

Voorbeeld 45a... C privé optie
Voorbeeld 45b... Fortran privé optie
Voorbeeld 46a... Gedeelde optie in C-taal
Voorbeeld 46b... Fortran gedeelde optie
Voorbeeld 47a... C eersteprivate optie
Voorbeeld 47b... Fortran eerste privé-optie
Voorbeeld 48a... C threadprivate richtlijn
Voorbeeld 48b... Fortran threadprivate richtlijn
Voorbeeld 49a... C kopieer optie
Voorbeeld 49b... Fortran kopieeroptie

2.5. Verdeling van het werk

2.5.1. Parallellisatie op laag niveau

Voorbeeld 50a... C-routines omp_get_num_threads en omp_get_thread_num
Voorbeeld 50b... Fortran-routines omp_get_num_threads en omp_get_thread_num

2.5.2. Parallelle lussen

Voorbeeld 51a... De for-richtlijn in C
Voorbeeld 51b... Fortran do richtlijn
Voorbeeld 52a... De planningsoptie in C
Voorbeeld 52b... Fortran schema optie
Voorbeeld 53a... De planningsoptie in C

annotatie: De lezing is gewijd aan de beschouwing van MPI-technologie als een parallelle programmeerstandaard voor gedistribueerde geheugensystemen. De belangrijkste wijzen van gegevensoverdracht worden beschouwd. Begrippen als procesgroepen en communicators worden geïntroduceerd. Basisgegevenstypen, point-to-point-bewerkingen, collectieve bewerkingen, synchronisatie- en tijdmetingsbewerkingen komen aan bod.

Het doel van de lezing: De lezing is gericht op het bestuderen van de algemene methodologie voor de ontwikkeling van parallelle algoritmen.

Video-opname van de lezing - (volume - 134 MB).

5.1. MPI: basisconcepten en definities

Laten we eens kijken naar een aantal concepten en definities die fundamenteel zijn voor de MPI-standaard.

5.1.1. Parallel programma concept

Onder parallel programma in het kader van MPI, een reeks gelijktijdig uitgevoerde processen... Processen kunnen op verschillende processors worden uitgevoerd, maar er kunnen ook meerdere processen op één processor worden uitgevoerd (in dit geval wordt de uitvoering uitgevoerd in een timesharing-modus). In het uiterste geval kan één processor worden gebruikt om een ​​parallel programma uit te voeren - in de regel wordt deze methode gebruikt om in eerste instantie de juistheid van een parallel programma te controleren.

Elk proces van een parallel programma wordt gegenereerd op basis van een kopie van dezelfde programmacode ( SPMP-model). Deze programmacode, gepresenteerd in de vorm van een uitvoerbaar programma, moet beschikbaar zijn op het moment dat het parallelle programma wordt gestart op alle gebruikte processors. De bronprogrammacode voor het uitvoerbare programma is ontwikkeld in algoritmische talen C of Fortran met behulp van een of andere implementatie van de MPI-bibliotheek.

Het aantal gebruikte processen en het aantal processors wordt bepaald op het moment dat een parallel programma wordt gestart door middel van de uitvoeringsomgeving van MPI-programma's en kan tijdens de berekeningen niet veranderen (de MPI-2-standaard voorziet in de mogelijkheid om dynamisch te veranderen het aantal processen). Alle processen van het programma worden opeenvolgend hernummerd van 0 tot p-1, waar P er is een totaal aantal processen. Het procesnummer heet rang Verwerken.

5.1.2. Bewerkingen voor gegevensoverdracht

MPI is gebaseerd op bewerkingen voor het doorgeven van berichten. Onder de functies in MPI zijn verschillende gekoppeld (punt naar punt) bewerkingen tussen twee processen en collectief (collectief) communicatieacties voor de gelijktijdige interactie van meerdere processen.

Om gepaarde bewerkingen uit te voeren, kunnen verschillende transmissiemodi worden gebruikt, waaronder synchroon, blokkeren, enz. - een volledige overweging van mogelijke transmissiemodi: wordt uitgevoerd in paragraaf 5.3.

Zoals eerder opgemerkt, voorziet de MPI-standaard in de noodzaak om de meeste basishandelingen voor collectieve gegevensoverdracht te implementeren - zie paragrafen 5.2 en 5.4.

5.1.3. Het concept van communicators

De processen van een parallel programma worden gecombineerd tot: groep... Onder communicator MPI betekent een speciaal gemaakt serviceobject dat een groep processen en een aantal aanvullende parameters combineert ( context) gebruikt bij het uitvoeren van gegevensoverdrachtbewerkingen.

In de regel worden gekoppelde gegevensoverdrachtbewerkingen uitgevoerd voor processen die tot dezelfde communicator behoren. Collectieve operaties worden gelijktijdig toegepast op alle communicatorprocessen. Als gevolg hiervan is de vermelding van de gebruikte communicator verplicht voor gegevensoverdrachtbewerkingen in MPI.

Tijdens berekeningen kunnen nieuwe procesgroepen en communicators worden aangemaakt en bestaande procesgroepen en communicators worden verwijderd. Hetzelfde proces kan tot verschillende groepen en communicatoren behoren. Alle processen die beschikbaar zijn in het parallelle programma maken deel uit van de communicator die standaard is gemaakt met de MPI_COMM_WORLD-identificatie.

Als het nodig is om gegevens tussen processen van verschillende groepen over te dragen, is het noodzakelijk om een ​​globale communicator te maken ( intercommunicator).

Een gedetailleerde beschouwing van de mogelijkheden van MPI voor het werken met groepen en communicatoren zal worden uitgevoerd in paragraaf 5.6.

5.1.4. Gegevenstypen

Bij het uitvoeren van bewerkingen voor het verzenden van berichten, om de verzonden of ontvangen gegevens in de MPI-functies aan te geven, is het noodzakelijk om te specificeren: soort van gegevens verzonden. MPI bevat een grote set basistypen data die grotendeels samenvallen met de datatypes in de algoritmische talen C en Fortran. Bovendien heeft MPI de mogelijkheid om nieuwe afgeleide typen gegevens voor een nauwkeurigere en beknoptere beschrijving van de inhoud van doorgestuurde berichten.

Een gedetailleerde bespreking van de mogelijkheden van MPI voor het werken met afgeleide gegevenstypen zal worden uitgevoerd in paragraaf 5.5.

5.1.5. Virtuele topologieën

Zoals eerder opgemerkt, kunnen gepaarde gegevensoverdrachtbewerkingen worden uitgevoerd tussen alle processen van dezelfde communicator, en alle processen van de communicator nemen deel aan de collectieve bewerking. In dit opzicht heeft de logische topologie van communicatielijnen tussen processen de structuur van een volledige grafiek (ongeacht de aanwezigheid van echte fysieke communicatiekanalen tussen processors).

Daarnaast (en dat werd al opgemerkt in paragraaf 3), is het voor de presentatie en daaropvolgende analyse van een aantal parallelle algoritmen raadzaam om het bestaande communicatienetwerk logisch weer te geven in de vorm van bepaalde topologieën.

MPI heeft de mogelijkheid om een ​​verscheidenheid aan processen in de vorm weer te geven rooster willekeurige dimensie (zie paragraaf 5.7). In dit geval kunnen de grensprocessen van de roosters aangrenzend worden verklaard en dus, op basis van de roosters, structuren van het type torus.

Daarnaast beschikt MPI over faciliteiten voor het vormen van logische (virtuele) topologieën van elk gewenst type. Een gedetailleerde bespreking van de mogelijkheden van MPI voor het werken met topologieën zal worden uitgevoerd in paragraaf 5.7.

En tot slot nog een laatste reeks opmerkingen voordat we MPI gaan overwegen:

  • Beschrijving van functies en alle voorbeelden van programma's die worden gegeven, worden gepresenteerd in de algoritmische taal C; de details van het gebruik van MPI voor de Fortran algoritmische taal worden gegeven in paragraaf 5.8.1,
  • Een korte beschrijving van de beschikbare implementaties van de MPI-bibliotheken en een algemene beschrijving van de uitvoeringsomgeving voor MPI-programma's zal worden beschouwd in clausule 5.8.2,
  • De belangrijkste presentatie van MPI-mogelijkheden zal gericht zijn op de versie 1.2-standaard ( MPI-1); aanvullende eigenschappen van de versie 2.0-standaard worden gepresenteerd in clausule 5.8.3.

Beginnen met het bestuderen van MPI, kan worden opgemerkt dat MPI aan de ene kant behoorlijk gecompliceerd is - de MPI-standaard voorziet in de aanwezigheid van meer dan 125 functies. Aan de andere kant is de MPI-structuur goed doordacht - de ontwikkeling van parallelle programma's kan worden gestart na slechts 6 MPI-functies te hebben overwogen. Alle extra functies van MPI kunnen worden beheerst naarmate de complexiteit van de ontwikkelde algoritmen en programma's toeneemt. Genoemd in deze stijl - van eenvoudig tot complex - en verder zal al het trainingsmateriaal op MPI worden gepresenteerd.

5.2. Inleiding tot parallelle programma-ontwikkeling met behulp van MPI

5.2.1. MPI Basis

Hier is de minimaal vereiste set MPI-functies, voldoende voor de ontwikkeling van vrij eenvoudige parallelle programma's.

5.2.1.1 Initialisatie en beëindiging van MPI-programma's

De eerste functie om aan te roepen MPI zou een functie moeten zijn:

int MPI_Init (int * agrc, char *** argv);

om de looptijd van het MPI-programma te initialiseren. De functieparameters zijn het aantal argumenten op de opdrachtregel en de tekst van de opdrachtregel zelf.

Laatste functie aangeroepen MPI moet een functie zijn:

int MPI_Finalize (ongeldig);

Dientengevolge kan worden opgemerkt dat de structuur van een parallel programma dat is ontwikkeld met behulp van MPI als volgt zou moeten zijn:

#include "mpi.h" int main (int argc, char * argv) (<программный код без использования MPI функций>MPI_Init (& agrc, & argv);<программный код с использованием MPI функций>MPI_Finalize ();<программный код без использования MPI функций>retourneer 0; )

Opgemerkt moet worden:

  1. Bestand mpi.h bevat definities van benoemde constanten, functieprototypes en gegevenstypen van de MPI-bibliotheek,
  2. Functies MPI_Init en MPI_Finalize zijn verplicht en moeten worden uitgevoerd (en slechts één keer) door elk proces van het parallelle programma,
  3. Voordat u belt MPI_Init de functie kan worden gebruikt: MPI_Geïnitialiseerd om te bepalen of er eerder een oproep is gedaan MPI_Init.

De hierboven besproken voorbeelden van functies geven een idee van de syntaxis voor het benoemen van functies in MPI. De functienaam wordt voorafgegaan door het MPI-voorvoegsel, gevolgd door een of meer woorden van de naam, het eerste woord in de functienaam begint met een hoofdletter, de woorden worden gescheiden door een onderstrepingsteken. De namen van MPI-functies verklaren in de regel het doel van de acties die door de functie worden uitgevoerd.

Opgemerkt moet worden:

  • Communicator MPI_COMM_WORLD, zoals eerder opgemerkt, wordt standaard gemaakt en vertegenwoordigt alle processen van het parallelle programma dat wordt uitgevoerd,
  • De rang verkregen door de functie MPI_Comm_rank, is de rangorde van het proces dat deze functie heeft aangeroepen, d.w.z. variabele ProcRank zal verschillende waarden aannemen in verschillende processen.

Deze opmerking laat zien hoe u MPI installeert, verbindt met Visual Studio en het vervolgens gebruikt met de opgegeven parameters (aantal rekenknooppunten). Dit artikel gebruikt Visual Studio 2015, omdat: het was met haar dat mijn studenten problemen hadden (deze notitie is geschreven door studenten voor studenten), maar de instructie zal waarschijnlijk ook werken voor andere versies.

Stap 1:
U moet de HPC Pack 2008 SDK SP2 installeren (in uw geval is er mogelijk een andere versie), beschikbaar op de officiële Microsoft-website. De bitgrootte van het pakket en het systeem moeten overeenkomen.

Stap 2:
U moet de paden configureren, hiervoor gaat u naar het tabblad Debug - Eigenschappen:

"C: \ Program Files \ Microsoft HPC Pack 2008 SDK \ Include"

In het veld Bibliotheekdirectories:

"C: \ Program Files \ Microsoft HPC Pack 2008 SDK \ Lib \ amd64"

In het veld met bibliotheken, als er een 32-bits versie is, in plaats van amd64, moet u i386 registreren.

Msmpi.lib

:

Stap 3:

Om de lancering te configureren, gaat u naar het tabblad Foutopsporing en specificeert u in het veld Opdracht:

"C: \ Program Files \ Microsoft HPC Pack 2008 SDK \ Bin \ mpiexec.exe"

Geef in het veld Opdrachtargumenten bijvoorbeeld

N 4 $ (Doelpad)

Het cijfer 4 geeft het aantal processen aan.

Om het programma uit te voeren, moet u verbinding maken met de bibliotheek

Het pad naar het project mag geen Cyrillisch bevatten. Als er fouten optreden, kunt u de Microsoft MPI gebruiken die beschikbaar is op de Microsoft-website.

Om dit te doen, volstaat het om na de installatie het pad te registreren in het veld Opdracht van het tabblad Foutopsporing:

"C: \ Program Files \ Microsoft MPI \ Bin \ mpiexec.exe"

Vergeet ook niet om de bitdiepte op te geven voordat u het programma start:

Een voorbeeld van het starten van een programma met MPI:

#erbij betrekken #erbij betrekken namespace std; gebruiken; int main (int argc, char ** argv) (int rang, grootte; MPI_Init (& argc, & argv); MPI_Comm_size (MPI_COMM_WORLD, & grootte); MPI_Comm_rank (MPI_COMM_WORLD, & rang); cout<< "The number of processes: " << size << " my number is " << rank << endl; MPI_Finalize(); return 0; }

Werk van het programma op 2 knooppunten: