MPI ühendamine Visual Studios. MPI funktsioonid

Juhtus nii, et pidin õppetööga tihedalt kokku põrkama paralleelarvutus ja eriti MPI. Võib-olla on see suund tänapäeval väga paljutõotav, nii et ma tahaksin näidata habrauseritele selle protsessi põhitõdesid.

Põhiprintsiibid ja eeskuju
Näitena kasutatakse eksponendi (e) arvutamist. Üks selle leidmise võimalustest on Taylori seeria:
e^x=∑((x^n)/n!), kus summeerimine toimub vahemikus n=0 kuni lõpmatuseni.

Seda valemit on lihtne paralleelstada, kuna soovitud arv on üksikute terminite ja sellest tulenevalt ka kõigi liikmete summa eraldi protsessor võib võtta ette üksikute tingimuste arvutamise.

Igas üksikus protsessoris arvutatavate terminite arv sõltub nii intervalli n pikkusest kui ka arvutusprotsessis osaleda saavate protsessorite k arvust. Nii et kui näiteks intervalli pikkus on n=4 ja arvutustes osaleb viis protsessorit (k=5), siis esimene kuni neljas protsessor saab igaüks ühe liikme ja viiendat ei kaasata . Kui n=10 ja k=5, saab iga protsessor arvutamiseks kaks liiget.

Esialgu saadab esimene protsessor MPI_Bcast levifunktsiooni kasutades teistele kasutaja määratud muutuja n väärtuse. Üldiselt on funktsioonil MPI_Bcast järgmine vorming:
int MPI_Bcast(void *buffer, int count, MPI_Datatype andmetüüp, int root, MPI_Comm comm), kus puhver on puhvri aadress koos elemendiga, count on elementide arv, andmetüüp on vastav MPI andmetüüp, root on põhiedastuse auaste ja komm on suhtleja nimi.
Minu puhul, nagu juba mainitud, toimib põhiprotsessorina esimene protsessor, mille auaste on 0.

Pärast numbri n edukat saatmist on iga protsessor hõivatud oma tingimuste arvutamisega. Selleks lisatakse tsükli igas etapis arvule i, mis on algselt võrdne protsessori auastmega, arv, mis võrdub arvutustes osalevate protsessorite arvuga. Kui number on pooleli järgmised sammud number ma ületan kasutaja määratud number n, tsükli täitmine jaoks antud protsessor peatub.

Tsükli täitmisel lisatakse terminid eraldi muutujasse ja pärast selle täitmist saadetakse saadud summa põhiprotsessorisse. Selleks kasutatakse vähendamise operatsiooni funktsiooni MPI_Reduce. IN üldine vaade see näeb välja selline:
int MPI_Reduce(void *buf, void *result, int count, MPI_Datatype andmetüüp, MPI_Op op, int root, MPI_Comm comm)

See ühendab rühma iga protsessi sisendpuhvri elemendid, kasutades operatsioonioperatsiooni ja tagastab kombineeritud väärtuse juurprotsessi väljundpuhvrisse. Sellise toimingu tulemuseks on üks väärtus, tänu millele sai valufunktsioon oma nime.

Pärast programmi käivitamist kõigil protsessoritel saab esimene protsessor terminite kogusumma, mis on meile vajalik eksponendi väärtus.

Tuleb märkida, et nii paralleelse kui ka järjestikuse astendaja arvutamise meetodi puhul faktoriaali leidmiseks, rekursiivne funktsioon. Otsuse tegemisel täidetava ülesande paralleelstamise meetodi osas kaalusin võimalust leida faktoriaal ka erinevad protsessorid, kuid lõpuks aktsepteerisin seda varianti kui irratsionaalset.

Esmane ülesanne on ikkagi leida eksponendi väärtus ja kui protsessorid hakkavad iga liikme iga faktoriaali eraldi arvutama, võib see kaasa tuua vastupidise efekti, nimelt jõudluse ja arvutuskiiruse olulise kaotuse.
Seda seletatakse asjaoluga, et antud juhul väga tohutu surve kommunikatsioonikeskkonna kohta, mis on paralleelarvutussüsteemides juba sageli nõrk lüli. Kui faktoriaali arvutamine toimub igal protsessoril eraldi, on sideliinide koormus minimaalne. Sel juhul võib nimetada hea näide et ka paralleliseerimise ülesandel peavad vahel olema piirid.

Koodi täitmise algoritm
1. Arvu n väärtus kantakse visuaalsest kestast programmi, mis seejärel saadetakse levifunktsiooni kasutades kõikidele protsessoritele.
2. Esimese peaprotsessori lähtestamisel käivitatakse taimer.
3. Iga protsessor käivitab tsükli, kus juurdekasvu väärtus on protsessorite arv süsteemis. Igas tsükli iteratsioonis arvutatakse liige ja selliste terminite summa salvestatakse muutujasse drobSum.
4. Pärast tsükli lõppemist liidab iga protsessor oma drobSum väärtuse muutujaks Result, kasutades selleks reduktsioonifunktsiooni MPI_Reduce.
5. Pärast kõigi protsessorite arvutuste lõpetamist peatab esimene põhiprotsessor taimeri ja saadab tulemuse muutuja väärtuse väljundvoogu.
6. Väljundvoogu saadetakse ka meie taimeri poolt mõõdetud ajaväärtus millisekundites.
Koodiloend
Programm on kirjutatud C++ keeles, eeldame, et täitmise argumendid edastatakse väliskestast. Kood näeb välja selline:
#kaasa "mpi.h"
#kaasa
#kaasa
kasutades nimeruumi std;

topeltfakt(int n)
{
kui (n==0)
tagastus 1;
muidu
tagasta n*Fact(n-1);
}

int main(int argc, char *argv)
{
SetConsoleOutputCP(1251);
intn;
int myid;
int numprocs;
int i;
intrc;
pikk double drob,drobSum=0,Tulemus,summa;
topelt algusaeg = 0,0;
topelt lõpuaeg;

N = atoi(argv);

if (rc= MPI_Init(&argc, &argv))
{
cout<< "Start ebaõnnestus, täitmine peatatud" << endl;
MPI_Abort(MPI_COMM_WORLD, rc);
}

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

kui (minuid == 0)
{

algusaeg = MPI_Wtime();
}
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

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

MPI_Reduce(&drobSum, &Result, 1, MPI_LONG_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
lõikamistäpsus(20);
kui (minuid == 0)
{
cout<< Result << endl;
lõpuaeg = MPI_Wtime();
cout<< (endwtime-startwtime)*1000 << endl;
}

MPI_Finalize();
tagasi 0;
}


* See lähtekood tõsteti esile Source Code Highlighteriga.
Järeldus
Nii saime lihtsa programmi eksponendi arvutamiseks, kasutades korraga mitut protsessorit. Tõenäoliselt on kitsaskohaks tulemuse enda salvestamine, sest numbrite arvu suurenemisega ei ole standardtüüpide abil väärtuse sisaldamine triviaalne ja see koht tuleb välja töötada. Võib-olla on üsna ratsionaalne lahendus kirjutada tulemus faili, kuigi selle näite puhtalt harivat funktsiooni silmas pidades ei saa me sellele keskenduda.

Märkus: Loeng on pühendatud MPI-tehnoloogia kui hajusmälusüsteemide pkäsitlemisele. Vaadeldakse peamisi andmeedastusviise. Tutvustatakse selliseid mõisteid nagu protsessirühmad ja kommunikaatorid. Käsitletakse põhiandmetüüpe, punktist punkti toiminguid, kollektiivoperatsioone, sünkroonimistoiminguid ja ajastustoiminguid.

Loengu eesmärk: Loeng on suunatud paralleelalgoritmide väljatöötamise üldise metoodika uurimisele.

Loengu videosalvestus - (maht - 134 MB).

5.1. MPI: põhimõisted ja määratlused

Mõelge mitmetele mõistetele ja määratlustele, mis on MPI standardi jaoks olulised.

5.1.1. Paralleelprogrammi kontseptsioon

Under paralleelprogramm MPI raames mõistame samaaegse täitmise komplekti protsessid. Protsessid võivad töötada erinevatel protsessoritel, kuid samal protsessoril võib asuda mitu protsessi (sel juhul toimub nende täitmine ajajagamise režiimis). Piiraval juhul saab paralleelprogrammi täitmiseks kasutada ühte protsessorit – reeglina kasutatakse seda meetodit paralleelprogrammi õigsuse esmaseks kontrollimiseks.

Iga paralleelprogrammi protsess genereeritakse sama programmikoodi koopia põhjal ( SPMP mudel). See käivitatava programmina esitatud programmikood peab olema paralleelprogrammi käivitamise ajal saadaval kõigil kasutatud protsessoritel. Käivitatava programmi lähtekood töötatakse välja C või Fortrani algoritmilistes keeltes, kasutades MPI teegi üht või teist teostust.

Protsesside arv ja kasutatavate protsessorite arv määratakse paralleelprogrammi käivitamise hetkel MPI programmi täitmiskeskkonna abil ja ei saa arvutuste käigus muutuda (standard MPI-2 annab võimaluse protsesside arvu dünaamiliselt muuta ). Kõik programmiprotsessid nummerdatakse järjestikku ümber 0-st p-1, Kus lk on protsesside koguarv. Kutsutakse protsessi numbrit koht protsessi.

5.1.2. Andmeedastustoimingud

MPI aluseks on sõnumi edastamise toimingud. MPI-s pakutavate funktsioonide hulgas on paaris (punktist punktini) toimingud kahe protsessi vahel ja kollektiivne (kollektiivne) suhtlustoimingud mitme protsessi samaaegseks koostoimeks.

Paaritud toimingute tegemiseks saab kasutada erinevaid edastusrežiime, sh sünkroonset, blokeerimist jne – võimalike täielik kaalumine edastusrežiimid tehakse punktis 5.3.

Nagu varem märgitud, näeb MPI standard ette vajaduse rakendada enamik põhilisi kollektiivseid andmeedastustoiminguid – vt alajaotisi 5.2 ja 5.4.

5.1.3. Suhtlejate mõiste

Paralleelprogrammi protsessid on kombineeritud rühmad. Under suhtleja MPI viitab spetsiaalselt loodud teenindusobjektile, mis ühendab protsesside rühma ja mitmeid lisaparameetreid ( Sisu), mida kasutatakse andmeedastustoimingutes.

Reeglina tehakse paarisandmeedastusoperatsioone samasse kommunikaatorisse kuuluvate protsesside jaoks. Kollektiivseid operatsioone rakendatakse samaaegselt kõikidele suhtlemisprotsessidele. Sellest tulenevalt on kasutatava kommunikaatori määramine MPI-s andmeedastustoimingute jaoks kohustuslik.

Arvutuste käigus saab luua uusi protsesside ja kommunikaatorite rühmi ning kustutada olemasolevaid. Sama protsess võib kuuluda erinevatele rühmadele ja suhtlejatele. Kõik paralleelprogrammis saadaolevad protsessid kaasatakse vaikimisi loodud kommunikaatorisse identifikaatoriga MPI_COMM_WORLD.

Kui on vaja andmeid erinevate rühmade protsesside vahel üle kanda, on vaja luua globaalne kommunikaator ( suhtleja).

Üksikasjalik arutelu MPI võimalustest rühmade ja suhtlejatega töötamiseks viiakse läbi alajaotises 5.6.

5.1.4. Andmetüübid

Sõnumi edastamise toimingute tegemisel tuleb MPI funktsioonides edastatavate või vastuvõetavate andmete määramiseks määrata tüüp saadetud andmed. MPI sisaldab suurt komplekti baastüübid andmed, mis langevad suures osas kokku andmetüüpidega algoritmilistes keeltes C ja Fortran. Lisaks on MPI-l võimalus luua uut tuletatud tüübid andmed edastatud sõnumite sisu täpsemaks ja ülevaatlikumaks kirjeldamiseks.

Üksikasjalik arutelu MPI võimalustest tuletatud andmetüüpidega töötamiseks viiakse läbi alajaotises 5.5.

5.1.5. Virtuaalsed topoloogiad

Nagu varem märgitud, saab seotud andmeedastusoperatsioone sooritada sama kommunikaatori mis tahes protsesside vahel ja kõik kommunikaatori protsessid osalevad kollektiivses toimingus. Sellega seoses on protsessidevaheliste sideliinide loogiline topoloogia tervikliku graafiku struktuur (olenemata tegelike füüsiliste sidekanalite olemasolust protsessorite vahel).

Koos sellega (ja seda märgiti juba jaotises 3) on mitme paralleelse algoritmi esitamiseks ja järgnevaks analüüsiks soovitatav olemasolevat sidevõrku loogiliselt esitada teatud topoloogiate kujul.

MPI-l on võime esitada vormil protsesside komplekti restid suvaline mõõde (vt alajaotis 5.7). Sel juhul saab võre piirprotsessid kuulutada naaberteks ja seega võrkude põhjal sellist tüüpi struktuurid torus.

Lisaks on MPI-l ka võimalused mis tahes nõutavat tüüpi loogiliste (virtuaalsete) topoloogiate genereerimiseks. Üksikasjalik arutelu MPI võimalustest topoloogiatega töötamiseks tehakse alajaotises 5.7.

Ja lõpuks viimane märkuste seeria enne MPI arutelu alustamist:

  • Funktsioonide kirjeldus ja kõik antud programmide näited esitatakse algoritmilises keeles C; MPI kasutamise eripära Fortrani algoritmilise keele jaoks on toodud jaotises 5.8.1,
  • MPI teekide saadaolevate rakenduste lühikirjeldust ja MPI programmide täitmiskeskkonna üldist kirjeldust käsitletakse jaotises 5.8.2,
  • MPI võimaluste põhiesitlus keskendub versiooni 1.2 standardile ( MPI-1); versiooni 2.0 standardi lisafunktsioone tutvustatakse 5.8.3.

MPI uurimist alustades võib tõdeda, et ühest küljest on MPI üsna keeruline – MPI standard näeb ette enam kui 125 funktsiooni. Teisest küljest on MPI ülesehitus hästi läbimõeldud - paralleelsete programmide väljatöötamist saab alustada vaid 6 MPI funktsiooni arvestamisel. Kõiki MPI lisafunktsioone saab omandada arendatud algoritmide ja programmide keerukuse kasvades. Selles stiilis nominaal - lihtsast keerukani - ja kogu MPI-teemalist koolitusmaterjali tutvustatakse veelgi.

5.2. Sissejuhatus paralleelprogrammide arendamisse MPI abil

5.2.1. MPI põhitõed

Esitame minimaalselt nõutava MPI funktsioonide komplekti, millest piisab üsna lihtsate paralleelprogrammide arendamiseks.

5.2.1.1 MPI-programmide lähtestamine ja lõpetamine

Esimene funktsioon kutsutud MPI peaks olema funktsioon:

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

MPI-programmi käituskeskkonna lähtestamiseks. Funktsiooni parameetrid on argumentide arv käsureal ja käsurea tekst ise.

Viimane kutsutud funktsioon MPI peab olema funktsioon:

int MPI_Finalize(void);

Selle tulemusena võib märkida, et MPI abil välja töötatud paralleelprogrammi struktuur peaks olema järgmisel kujul:

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

Tuleb märkida:

  1. Fail mpi.h sisaldab nimega konstantide, funktsioonide prototüüpide ja MPI teegi andmetüüpide määratlusi,
  2. Funktsioonid MPI_Init Ja MPI_Lõpeta on kohustuslikud ja neid peab käivitama (ja ainult üks kord) iga paralleelprogrammi protsess,
  3. Enne kõnet MPI_Init funktsiooni saab kasutada MPI_Initsialiseeritud et teha kindlaks, kas kõne on juba tehtud MPI_Init.

Ülaltoodud funktsioonide näited annavad aimu funktsioonide nimetamise süntaksist MPI-s. Funktsiooni nimele eelneb MPI eesliide, millele järgneb üks või mitu nimesõna, funktsiooni nime esimene sõna algab suure tähega, sõnad on eraldatud alakriipsuga. MPI funktsioonide nimetused selgitavad reeglina funktsiooni poolt sooritatavate toimingute eesmärki.

Tuleb märkida:

  • Suhtleja MPI_COMM_WORLD, nagu varem märgitud, luuakse vaikimisi ja esindab kõiki töötava paralleelprogrammi protsesse,
  • Funktsiooni abil saadud järjestus MPI_Comm_rank, on selle funktsiooni väljakutse teinud protsessi auaste, st. muutuv ProcRank omandab erinevates protsessides erinevaid väärtusi.

Paralleliseerimine C-s
Näide 3b. Paralleelsus Fortranis
Näide 4a. Süsteemitaimeri omaduste määramine C-keeles
Näide 4b. Süsteemi taimeri omaduste määramine Fortranis

1.4. Sõnumite saatmine ja vastuvõtmine eraldi protsesside vahel

1.4.1. Punkt-punkti toimingud

1.4.2. Blokeerivate sõnumite saatmine ja vastuvõtmine

Näide 5a. Sõnumite vahetamine kahe protsessi vahel C-keeles
Näide 5b. Sõnumite vahetamine kahe protsessi vahel Fortranis
Näide 6a. Paaris- ja paarituprotsesside sõnumivahetus C-keeles
Näide 6b. Paaris- ja paarituprotsesside sõnumivahetus Fortrani keeles
Näide 7a. Edastamine olematule C protsessile
Näide 7b. Fortrani keeles edastamine olematule protsessile
Näide 8a. Puhverdatud andmete saatmine C-vormingus
Näide 8b. Puhverdatud Fortrani andmete saatmine
Näide 9a. Teabe hankimine sõnumi atribuutide kohta C-keeles
Näide 9b. Teabe hankimine Fortranis sõnumi atribuutide kohta
Näide 10a. Latentsuse ja läbilaskevõime määratlus C-keeles
Näide 10b. Latentsuse ja läbilaskevõime määratlus Fortrani keeles

1.4.3. Sõnumite saatmine ja vastuvõtmine ilma blokeerimata

Näide 11a. Helina topoloogia vahetus, kasutades mitteblokeerivaid C-operatsioone
Näide 11b. Ringi topoloogia vahetus, kasutades Fortrani mitteblokeerivaid toiminguid
Näide 12a. Suhtlusskeem "meister - töölised" C-keeles
Näide 12b. Suhtlusskeem "meister - töötajad" Fortranis
Näide 13a. Maatriksi transpositsioon C-keeles
Näide 13b. Maatriksi transpositsioon Fortranis

1.4.4. Hilinenud interaktsioonitaotlused

Näide 14a. Iteratiivse meetodi skeem rõnga topoloogia vahetamisega, kasutades C-keeles edasilükatud päringuid
Näide 14b. Iteratiivse meetodi skeem rõnga topoloogia vahetamisega, kasutades edasilükatud päringuid Fortrani keeles

1.4.5. Ummikseisud (tupik)

Näide 15a. Helina topoloogia vahetus, kasutades C-keeles protseduuri MPI_Sendrecv
Näide 15b. Helina topoloogia vahetus, kasutades Fortranis MPI_SENDECV protseduuri

1.5. Kollektiivsete protsesside interaktsioonid

1.5.1. Üldsätted

1.5.2. Barjäär

Näide 16a. Barjääri sünkroonimise modelleerimine C-s
Näide 16b. Barjääride sünkroniseerimise modelleerimine Fortranis

1.5.3. Kollektiivsed andmeedastustoimingud

1.5.4. Globaalsed operatsioonid

Näide 17a. Globaalse summeerimise modelleerimine kahekordistusskeemi ja MPI_Reduce kollektiivoperatsiooni abil C-s
Näide 17b. Globaalse summeerimise modelleerimine kahekordistamisskeemi ja MPI_Reduce kollektiivoperatsiooni abil Fortranis

1.5.5. Kohandatud globaalsed toimingud

Näide 18a. Kohandatud globaalne funktsioon C-keeles
Näide 18b. Kohandatud globaalne funktsioon Fortrani keeles

1.6. Rühmad ja suhtlejad

1.6.1. Üldsätted

1.6.2. Protsessi rühmatoimingud

Näide 19a. Töötamine rühmadega C-s
Näide 19b. Töötamine Fortran Groupidega

1.6.3. Toimingud suhtlejatega

Näide 20a. Communicatori jagamine C-s
Näide 20b. Communicatori eraldamine Fortranis
Näide 21a. Protsessi nummerdamist C-keeles
Näide 21b. Protsessi ümber nummerdamist Fortranis

1.6.4. Suhtlejad

Näide 22a. Meister-töölise skeem C interkommunikaatori abil
Näide 22b. Skeem "meister - töötajad", kasutades Fortrani interkommunikaatorit

1.6.5. Atribuudid

1.7. Virtuaalsed topoloogiad

1.7.1. Üldsätted

1.7.2. Descartes'i topoloogia

1.7.3. Graafi topoloogia

Näide 23a. Master-worker skeem kasutades graafi topoloogiat C-keeles
Näide 23b. Master-worker skeem, kasutades Fortrani graafi topoloogiat

1.8. Segaandmete saatmine

1.8.1. Üldsätted

1.8.2. Tuletatud andmetüübid

Näide 24a. Maatriksi veergude ümberkorraldamine C-s
Näide 24b. Maatriksi veergude ümberkorraldamine Fortranis

1.8.3. Andmete pakendamine

Näide 25a. Pakitud andmete saatmine C-vormingus
Näide 25b. Pakitud Fortrani andmete saatmine

1.9. infoobjekt

1.9.1. Üldsätted

1.9.2. Infoobjektiga töötamine

1.10. Dünaamiline protsessi juhtimine

1.10.1. Üldsätted

1.10.2 Protsesside genereerimine

meister.c
ori.c
Näide 26a. Master-worker skeem kasutades C protsessi kudemist
meister.f
ori.f
Näide 26b. Master-worker skeem, kasutades Fortrani protsessi genereerimist

1.10.3. Kliendi-serveri suhtlus

server.c
klient.c
Näide 27a. Side serveri ja kliendi vahel, kasutades C-keeles avalikku nime
server.f
klient.f
Näide 27b. Andmevahetus serveri ja kliendi vahel avaliku nimega Fortrani keeles

1.10.4. Protsessi seose kustutamine

1.10.5. Side pistikupesade kaudu

1.11. Ühesuunaline side

1.11.1. Üldsätted

1.11.2. Aknaga töötamine

1.11.3. Andmete ülekanne

1.11.4. Sünkroonimine

Näide 28a
Näide 28b
Näide 29a. Helina topoloogia vahetus, kasutades C-s ühesuunalist sidet
Näide 29b. Helina topoloogia vahetus, kasutades Fortrani ühesuunalist sidet
Näide 30a. Helina topoloogia vahetus, kasutades C-s ühesuunalist sidet
Näide 30b. Helina topoloogia vahetus, kasutades Fortrani ühesuunalist sidet

1.12. Välised liidesed

1.12.1. Üldised päringud

1.12.2. Teave staatusest

1.12.3. Niidid

1.13. Paralleelne I/O

1.13.1. Definitsioonid

1.13.2. Töötamine failidega

1.13.3. Juurdepääs andmetele

Näide 31a. Puhverdatud lugemine failist C-keeles
Näide 31b. Puhverdatud lugemine failist Fortranis
Näide 32a. Kollektiivne lugemine failist C-keeles
Näide 32b. Kollektiivne lugemine failist Fortranis

1.14. Viga töötlemisel

1.14.1. Üldsätted

1.14.2. Kommunikaatoritega seotud veakäsitlejad

1.14.3. Akendega seotud veakäsitlejad

1.14.4. Failidega seotud veakäsitlejad

1.14.5. Täiendavad protseduurid

1.14.6. Vigade koodid ja klassid

1.14.7. Helistamine veakäsitlejatele

Näide 33a. Vigade käsitlemine C-s
Näide 33b. Vigade käsitlemine Fortranis

2. peatükk OpenMP paralleelprogrammeerimise tehnoloogia

2.1. Sissejuhatus

2.2. Põhimõisted

2.2.1. Programmi koostamine

Näide 34a. Tingimuslik kompileerimine keeles C
Näide 34b
Näide 34c. Tingimuslik koostamine Fortranis

2.2.2. Paralleelprogrammi mudel

2.2.3. direktiivid ja menetlused

2.2.4. Programmi täitmine

2.2.5. Aja mõõtmine

Näide 35a. Süsteemi taimeritega töötamine C-keeles
Näide 35b. Süsteemi taimeritega töötamine Fortranis

2.3. Paralleelsed ja jadapiirkonnad

2.3.1. paralleeldirektiiv

Näide 36a. Rööppiirkond C-keeles
Näide 36b. Paralleelpiirkond Fortrani keeles
Näide 37a. vähendamise võimalus C-keeles
Näide 37b. Fortrani vähendamise võimalus

2.3.2. Lühendatud märge

2.3.3. Keskkonnamuutujad ja abistamisprotseduurid

Näide 38a. omp_set_num_threads protseduur ja num_threads valik C-keeles
Näide 38b. omp_set_num_threads protseduur ja num_threads valik Fortranis
Näide 39a. omp_set_dynamic ja omp_get_dynamic protseduurid C-keeles
Näide 39b. Protseduurid omp_set_dynamic ja omp_get_dynamic Fortranis
Näide 40a. Pesastatud paralleelsed piirkonnad C-s
Näide 40b. Pesastatud paralleelsed piirkonnad Fortranis
Näide 41a. omp_in_parallel funktsioon C-keeles
Näide 41b. Funktsioon omp_in_parallel Fortranis

2.3.4. ühtne direktiiv

Näide 42a. Üksikdirektiiv ja nowait-valik C-s
Näide 42b. Üksikdirektiiv ja nowait-valik Fortranis
Näide 43a. copyprivate võimalus C-keeles
Näide 43b. Fortran copyprivate valik

2.3.5. põhidirektiiv

Näide 44a. Põhidirektiiv C-s
Näide 44b. Fortrani põhidirektiiv

2.4. Andmemudel

Näide 45a. C privaatne valik
Näide 45b. Fortrani privaatne valik
Näide 46a. C jagatud valik
Näide 46b. Fortrani jagatud valik
Näide 47a. esimene privaatne valik C-keeles
Näide 47b. esimene privaatne võimalus Fortranis
Näide 48a. Keerme eradirektiiv C-s
Näide 48b. Fortrani lõime eradirektiiv
Näide 49a. C kopeerimise valik
Näide 49b. Fortrani kopeerimise võimalus

2.5. Tööde jaotus

2.5.1. Madala taseme paralleelsus

Näide 50a. Protseduurid omp_get_num_threads ja omp_get_thread_num C-keeles
Näide 50b. Protseduurid omp_get_num_threads ja omp_get_thread_num Fortranis

2.5.2. Paralleelsed silmused

Näide 51a. Direktiivi jaoks C
Näide 51b. Fortran tee direktiiv
Näide 52a. ajakava valik C-keeles
Näide 52b. Fortrani ajakava valik
Näide 53a. ajakava valik C-keeles

MPI funktsioonid

Tuletatud tüüp, operatsioonid, andmetüübid

Bsend Buffer_attach Get_count ANY_SOURCE Sendrecv_replace ANY_TAG Probe

Allgetherv Alltoall Alltoallv Vähenda Rduce_scatter Scan

Tuletatud tüüp koostatakse eelmääratletud MPI tüüpidest ja eelnevalt määratletud tuletatud tüüpidest, kasutades spetsiaalseid konstruktorifunktsioone

MPI_tüüp külgnev, MPI_tüüp_vektor, MPI_tüüp_hvektor, MPI_tüüp_indekseeritud, MPI_tüüp_hindexed, MPI_tüüp_struktuur.

Uus tuletatud tüüp registreeritakse funktsiooni MPI_Type_commit kutsumisega. Alles pärast registreerimist saab uut tuletatud tüüpi kasutada suhtlusrutiinides ja muude tüüpide konstrueerimisel. Eelmääratletud MPI tüübid loetakse registreerituks.

Kui tuletatud tüüpi pole enam vaja, hävitab selle funktsioon MPI_Type_free.

1) MPI_Init - lähtestamisfunktsioon. Selle funktsiooni täitmise tulemusel luuakse protsessirühm, kuhu paigutatakse kõik rakendusprotsessid, ja luuakse sideala, mida kirjeldab eelmääratletud kommunikaator MPI_COMM_WORLD.

MPI_Type_commit - tüübi registreerimine, MPI_Type_free - tüübi hävitamine

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

2) MPI_Finalize – funktsioon MPI programmide lõpetamiseks. Funktsioon sulgeb kõik MPI protsessid ja kõrvaldab kõik ühenduse alad.

int MPI_Finalize(void);

3) Suhtluspiirkonna protsesside arvu määramise funktsioon MPI_Comm_size . Funktsioon tagastab protsesside arvu kommunikaatori kommi suhtlusalal.

int MPI_Comm_size(MPI_Comm comm, int *suurus);

4) Protsessi numbri tuvastamise funktsioon MPI_Comm_rank . Funktsioon tagastab selle funktsiooni kutsunud protsessi numbri. Protsessi numbrid jäävad vahemikku 0..suurus-1.

int MPI_Comm_rank(MPI_Comm comm, int *rank);

5) Sõnumi edastamise funktsioon MPI_Saada . Funktsioon saadab identifikaatori sildiga sõnumi andmetüüpi tüüpi loenduselemendid sihtprotsessile kommunikaatori komm sidepiirkonnas.

int MPI_Saada(void* buf, int count, MPI_Datatype andmetüüp, int dest, int silt, MPI_Comm comm);

6) Sõnumi vastuvõtu funktsioon MPI_Recv . Funktsioon võtab kommunikaatori kommi sidealal allikaprotsessist vastu identifikaatorimärgisega sõnumi andmetüübi tüüpi loenduselemendid.

int MPI_Recv(void* buf, int count, MPI_Datatype andmetüüp, int allikas, int silt, MPI_Comm comm, MPI_Status *olek)

7) Ajastusfunktsioon (taimer) MPI_Wtime . Funktsioon tagastab astronoomilise aja sekundites, mis on möödunud mingist hetkest minevikus (võrdluspunkt).

double MPI_Wtime(tühine)

Funktsioonid sõnumite edastamiseks protsesside vahel jagunevad:

S (sünkroonne) eesliide

tähendab sünkroonset andmeedastusrežiimi. Andmeedastustoiming lõpeb alles siis, kui andmete vastuvõtt on lõppenud. Funktsioon ei ole kohalik.

B eesliide (puhverdatud)

tähendab puhverdatud andmeedastusrežiimi. Edastamisprotsessi aadressiruumis luuakse spetsiaalse funktsiooni abil lõikelaud, mida kasutatakse vahetusoperatsioonides. Saatmistoiming lõpeb, kui andmed on sellesse puhvrisse paigutatud. Funktsioonil on kohalik iseloom.

R-eesliide (valmis)

kokkulepitud või ettevalmistatud andmeedastusviis. Andmeedastusoperatsioon algab alles siis, kui vastuvõttev protsessor on seadnud andmete vastuvõtmiseks valmis lipu, alustades vastuvõtmist. Funktsioon ei ole kohalik.

Prefiks I (kohe)

viitab mitteblokeerivatele toimingutele.

MPI_Status Structure

Pärast sõnumi lugemist ei pruugi mõned parameetrid olla teada, nimelt: loetud elementide arv, sõnumi identifikaator ja saatja aadress. Seda teavet saab hankida olekuparameetri abil. Olekumuutujad peavad olema MPI-programmis selgesõnaliselt deklareeritud. C-keeles on olek MPI_Status tüüpi struktuur kolme väljaga MPI_SOURCE, MPI_TAG, MPI_ERROR.

8) Tegelikult saabunud sõnumielementide arvu määramiseks peate kasutama spetsiaalset funktsiooni MPI_Get_count .

int MPI_Get_count (MPI_Status *status, MPI_Datatype andmetüüp, int *count);

9) Saate määrata vastuvõetud sõnumi parameetrid ilma seda lugemata, kasutades funktsiooni MPI_Probe. int MPI_Probe(int allikas, int silt, MPI_Comm komm, MPI_olek *olek);

10) Olukordades, kus soovitakse protsesside vahel andmeid vahetada, on kindlam kasutada kombineeritud operatsiooni MPI_Sendrecv. Selles toimingus asendatakse buf-massiivist saadetud andmed vastuvõetud andmetega.

int MPI_Sendrecv(void *sendbuf, int sendcount, MPI_Datatype sendtype, int dest, int sendtag, void *recvbuf, int recvcount, MPI_Datatype recvtype, int source, MPI_Datatype recvtag, MPI_Comm comm, MPI_Status);

11) Mitteblokeeruva toimingu lõpuleviimise kontrollimise funktsioon MPI_Test .

int MPI_Test(MPI_Request *päring, int *lipp, MPI_Olek *olek);

See on kohalik mitteblokeeriv toiming. Kui päringuga seotud toiming on lõpule viidud, tagastatakse lipp = true ja olek sisaldab teavet lõpetatud toimingu kohta. Kui testitav toiming ei ole lõpule viidud, tagastatakse lipp = false ja oleku väärtus on sel juhul määramata.

12) Päringu eemaldamise funktsioon, ootamata mitteblokeeriva toimingu MPI_Request_free lõpuleviimist.

int MPI_taotlus_vaba(MPI_taotlus *päring);

Taotluse parameeter on seatud väärtusele MPI_REQUEST_NULL.

13) Andmete ühest protsessist kõikidesse programmi protsessidesse (andmete edastamine) ülekandmise toimingu tõhusa teostamise saab tagada MPI funktsiooni abil:

int MPI_Bcast(kehtetu *buf, int count, MPI_andmetüüp, int juur, MPI_Comm)

Funktsioon MPI_Bcast edastab andmeid puhverpuhvrist, mis sisaldab tüüpi loenduselemente juurprotsessist kõikidesse sidekommunikatsioonis sisalduvatesse protsessidesse.

14) Kui on vaja mõnelt sõnumit saada Lähteprotsessi lähteparameetriks saab määrata MPI_ANY_SOURCE

15) Kui on vaja saada sõnum mis tahes sildiga, saab märgendi parameetri seadistada MPI_ANY_TAG

16) Staatuse parameeter võimaldab teil määratleda mitmeid vastuvõetud sõnumi omadusi:

- staatus.MPI_SOURCE – auaste vastuvõetud sõnumi saatmisprotsess,

- status.MPI_TAG – vastu võetud sõnumimärgend.

17) Funktsioon

MPI_Get_count t(MPI_status *olek, MPI_andmetüübi tüüp, int *count)

tagastab muutujas count tüüpi tüüpi elementide arvu vastuvõetud sõnumis.

18) Andmeedastustoimingud kõikidest protsessidest ühte protsessi. Selles operatsioonis kogutud

väärtused teostavad üht või teist andmetöötlust (viimase punkti rõhutamiseks nimetatakse seda toimingut ka andmete vähendamise toiminguks)

int MPI_Reduce (void *sendbuf, void *recvbuf,int count, MPI_Datatype type, MPI_Op op,int root,MPI_Comm comm)

19) Protsesside sünkroniseerimine, s.o. Arvutusprotsessi teatud punktide protsesside samaaegne saavutamine tagatakse MPI funktsiooni abil: int MPI_barrier(MPI_Comm komm); Funktsioon MPI_Barrier määratleb kollektiivse operatsiooni ja seega peavad selle kasutamisel välja kutsuma kõik kasutatava kommunikaatori protsessid. Funktsiooni MPI_Barrier kutsumisel

protsessi täitmine on blokeeritud, protsessi arvutused jätkuvad alles pärast seda, kui kõik kommunikaatori protsessid kutsuvad välja funktsiooni MPI_Barrier.

20) Puhverdatud edastusrežiimi kasutamiseks tuleb luua ja üle kanda MPI-mälupuhver.

sõnumite puhverdamiseks – selleks kasutatav funktsioon on: int MPI_Buffer_attach (void *buf, int size),

- buf on mälupuhver sõnumite puhverdamiseks,

- suurus - puhvri suurus.

21) Pärast puhvri lõppu tuleb see MPI-st lahti ühendada, kasutades funktsiooni:

int MPI_Buffer_detach (tühi *buf, int *suurus).

22) Andmeedastus- ja vastuvõtutoimingute tõhus ja garanteeritud samaaegne teostamine on saavutatav MPI funktsiooni abil:

int MPI_Sendrecv (void *sbuf,int scount,MPI_Datatype stype,int dest, int stag, void *rbuf,int rcount,MPI_Datatype

rtype,int allikas,int rtag, MPI_Comm comm, MPI_Status *olek)

23) Kui sõnumid on sama tüüpi, on MPI-l võimalus kasutada ühte puhvrit: intMPI_Sendrecv_replace (void *buf, int count, MPI_Datatype type, int dest,

int stag, int allikas, int rtag, MPI_Comm comm, MPI_Status* olek)

24) Andmete ühest protsessist kõikidesse protsessidesse ülekandmise üldistatud toimimine (andmete jaotamine) erineb leviedastusest selle poolest, et protsess kannab protsessidesse erinevaid andmeid (vt joonis 4.4). Seda toimingut saab teha funktsiooni abil:

int MPI_Scatter(void *sbuf,int arv,MPI_andmetüübi tüüp,

25) Üldine andmeedastus kõigilt töötlejatelt ühte protsessi (andmete kogumine) on vastupidine andmete levitamise protseduurile (vt joonis 4.5). Selle toimingu tegemiseks on MPI-l funktsioon:

int MPI_Gather(void *sbuf,int scount,MPI_Datatype tüüp,

void *rbuf,int rcount,MPI_Datatype rtype, int root, MPI_Comm comm)

26) Tuleb märkida, et funktsiooni MPI_Gather kasutamisel kogutakse andmeid ainult

ühel protsessil. Et saada kõik kogutud andmed iga kommunikaatori protsessi kohta

peate kasutama kogumise ja levitamise funktsiooni:

int MPI_Allgather(void *sbuf, int scount, MPI_Datatype tüüp, void *rbuf, int rcount, MPI_Datatype rtype, MPI_Comm comm)

27) Andmete saatmine kõikidest protsessidest kõikidesse protsessidesse on kõige levinum andmeedastusoperatsioon (vt joonis 4.6). Seda toimingut saab teha funktsiooni abil:

int MPI_Alltoall (void *sbuf,int scount,MPI_Datatype stype, void *rbuf,int rcount,MPI_Datatype rtype,MPI_Comm comm)

28) Funktsioon MPI_Reduce pakub andmete vähendamise tulemusi

ainult ühel protsessil. Kõigi kommunikaatoriprotsesside andmete vähendamise tulemuste saamiseks peate kasutama vähendamise ja levitamise funktsiooni:

int MPI_Allreduce(void *sendbuf, void *recvbuf,int count, MPI_Datatype type, MPI_Op op,MPI_Comm comm).

29) Ja veel ühe andmete kogumise ja töötlemise toimingu variandi, mis tagab kõigi vähendamise osatulemuste saamise, saab funktsiooni abil:

int MPI_Scan (void *sendbuf, void *recvbuf,int count, MPI_Datatype type, MPI_Op op,MPI_Comm comm).

Funktsiooni MPI_Scan täitmise üldine skeem on näidatud joonisel fig. 4.7. Vastuvõetud sõnumite elemendid on protsesside poolt edastatud sõnumite vastavate elementide töötlemise tulemused, samas kui protsessi tulemuste saamiseks auastmega i, 0≤i

30) Bufpos muutuja algväärtus tuleb moodustada enne pakkimist ja seejärel määrata funktsiooniga MPI_Pack . Funktsiooni MPI_Pack kutsutakse järjestikku, et pakkida kõik vajalikud andmed.

int MPI_Pack_size (int count, MPI_Datatype type, MPI_Comm comm, int *size)

31) Pärast kõigi vajalike andmete pakkimist saab ettevalmistatud puhvrit kasutada andmeedastusfunktsioonides, mille tüüp on määratud MPI_PACKED.

Pärast MPI_PACKED tüüpi sõnumi saamist saab andmed lahti pakkida, kasutades funktsiooni:

int MPI_Unpack(void *buf, int bufsize, int *bufpos, void *data, int count, MPI_Datatype type, MPI_Comm comm)

Komplekssete juhiste komplekti arvuti

CISC (inglise keel Complex instruction set computing või inglise keele kompleksne käsukomplekti arvuti -

täieliku juhiste komplektiga arvuti) on protsessorite kujundamise kontseptsioon, mida iseloomustavad järgmised omadused:

suhteliselt väike arv üldotstarbelisi registreid;

· suur hulk masinakäske, millest mõned laaditakse semantiliselt sarnaselt kõrgetasemeliste programmeerimiskeelte operaatoritega ja täidetakse paljude tsüklitena;

· suur hulk adresseerimismeetodeid;

· suur hulk erineva bitisügavusega käsuvorminguid;

· kahe aadressiga käsuvormingu domineerimine;

· tüüpi töötlemiskäskude olemasolu register-mälu.

Puudused:

riistvara kõrge hind; raskused arvutuste paralleelseerimisel.

CISC käsustiku koostamise metoodika on vastupidine teisele metoodikale – RISC-le. Nende mõistete erinevus seisneb programmeerimismeetodites, mitte protsessori tegelikus arhitektuuris. Peaaegu kõik kaasaegsed protsessorid emuleerivad nii RISC kui ka CISC käsukomplekte.

Vähendatud juhiskomplektiga arvuti

See põhineb RISC arhitektuuri põhimõtetel: fikseeritud käsuformaat, registritoimingud, käskude ühetsükliline täitmine, lihtsad adresseerimismeetodid, suur registrifail. Samal ajal on mitmeid olulisi omadusi, mis eristavad seda arhitektuuri teiste RISC-protsessorite arhitektuuridest. Nende hulka kuuluvad: sõltumatu registrikomplekt iga täitevseadme jaoks; eraldi CISC-laadsete käskude lisamine süsteemi; hilinenud üleminekute mehhanismi puudumine; originaalne viis tingimuslike hüpete rakendamiseks. Arhitektuuriga mikroprotsessorite peamiseks rakendusalaks on suure jõudlusega serverid ja superarvutid.

Sellised arvutid põhinevad arhitektuuril, mis eraldab töötlemisjuhised mälukäskudest ja rõhutab tõhusat konveiertöötlust. Käsusüsteem oli konstrueeritud nii, et mis tahes käsu täitmine võttis vähe masinatsükleid (soovitavalt üks masinatsükkel). Käskude täitmise loogika oli jõudluse parandamiseks orienteeritud pigem riistvarale kui püsivara juurutamisele. Käskude dekodeerimise loogika lihtsustamiseks kasutati fikseeritud pikkusega käske.

Ja fikseeritud formaat.

IN kui hop sihtpuhvri tehnoloogia tähendus

IN Protsessor pakub mehhanismi üleminekute suuna dünaamiliseks ennustamiseks. Sellega

Kiibi eesmärk on väike vahemälu, mida nimetatakse haru sihtpuhvriks (BTB) ja kaks sõltumatut käskude eellaadimispuhvrite paari (kaks 32-bitist puhvrit konveieri kohta). Haru-sihtpuhver salvestab eellaadimispuhvrites olevate juhiste aadressid. Eellaadimispuhvrite töö on korraldatud nii, et igal ajahetkel tõmmatakse vaid üks vastava paari puhvritest. Kui käsuvoost leitakse haruoperatsioon, võrreldakse arvutatud haru aadressi BTB puhvris salvestatud aadressidega. Sobivuse korral eeldatakse, et haru võetakse ja lastakse käitada veel üks eellaadimispuhver, mis hakkab väljastama vastavas konveieris täidetavaid käske. Kui esineb ebakõla, ei võeta arvesse ühtegi haru ja eellaadimispuhvrit ei lülitata sisse, jätkates käsu andmise tavapärast järjekorda. See väldib konveieri seisakuid.

Struktuursed konfliktid ja viisid nende minimeerimiseks

Käskude täitmise kombineeritud režiim nõuab üldiselt konveierfunktsionaalseid üksusi ja ressursside dubleerimist, et võimaldada konveieril kõiki võimalikke käskude kombinatsioone. Kui suvaline käskude kombinatsioon ei saa

ressursikonflikti tõttu aktsepteeritakse, on masinal väidetavalt struktuurne konflikt. Kõige tüüpilisem näide masinatest, milles võivad tekkida struktuursed konfliktid, on masinad, mille funktsionaalüksused on mittetäielikult ühendatud.

Minimeeri: konveier peatab ühe käsu täitmise, kuni vajalik seade muutub kättesaadavaks.

Andmekonfliktid, torujuhtme peatused ja läbimise rakendamine

Üks tegureid, mis torujuhtmesüsteemide jõudlust oluliselt mõjutab, on käskudevahelised loogilised sõltuvused. Andmekonfliktid tekivad siis, kui konveieri kasutamine võib muuta operandide juurdepääsu järjekorda nii, et see järjekord erineb järjekorrast, mida täheldatakse käskude järjestikuse täitmisel konveierita masinas. Selles näites püstitatud probleemi saab lahendada üsna lihtsa riistvaralise tehnikaga, mida nimetatakse andmete edastamiseks, andmete möödaviimiseks ja mõnikord ka lühiseks.

Andmekonfliktid põhjustavad torujuhtme peatamise

Selle asemel vajame näite korrektse töötamise tagamiseks täiendavat riistvara, mida nimetatakse konveieri interlooki riistvaraks. Üldiselt tuvastab selline riistvara konfliktid ja peatab konveieri nii kauaks, kuni konflikt esineb. Sel juhul peatab see riistvara konveieri, mis algab käsuga, mis soovib andmeid kasutada ajal, mil eelmine käsk, mille tulemus on meie operandiks, annab selle tulemuse. See aparaat paneb konveieri seisma või "mullima" samamoodi nagu struktuursete konfliktide korral.

Tingimuslikud haru ennustamise puhvrid

Tingimuslik haru ennustamise puhver on väike mälu, mida adresseerivad hüppekäsu aadressi kõige vähem olulised bitid. Iga selle mälu lahter sisaldab ühte bitti, mis näitab, kas eelmine üleminek viidi läbi või mitte. See on seda tüüpi puhvri kõige lihtsam tüüp. Sellel pole silte ja see on kasulik ainult haru viivituse vähendamiseks, kui viivitus on suurem kui haru sihtaadressi väärtuse arvutamiseks kuluv aeg. Haru ennustuspuhvrit saab rakendada väikese spetsiaalse vahemäluna, millele pääseb ligi käsuaadressi kaudu konveieri käskude toomise (IF) etapis, või bitipaarina, mis on seotud iga käskude vahemäluplokiga ja tuuakse koos iga käsuga.