ARHITECTURI PARALELE DE CALCUL

Size: px
Start display at page:

Download "ARHITECTURI PARALELE DE CALCUL"

Transcription

1 ARHITECTURI PARALELE DE CALCUL O compilaţie de Gheorghe M.Panaitescu Universitatea Petrol-Gaze Ploiesti Catedra Automaticǎ si calculatoare

2 2

3 INTRODUCERE În editia din anul universitar , cursul de Arhitecturi paralele de calcul s-a bazat în cea mai mare parte pe câteva tutoriale publicate pe Internet de Lawrence Livermore National Laboratory, California, Statele Unite ale Americii, sub semnǎtura lui Blaise Barney. Toate aceste lectii dense si concise cititorul le poate gǎsi în versiunea lor originalǎ la adresa Au fost traduse si pe alocuri completate cu informatii din alte surse trei tutoriale: Introduction to Parallel Computing (ultima actualizare: iulie 2006) OpenMP (ultima actualizare: august 2006) Message Passing Interface (MPI) (ultima actualizare: iulie 2006) Figurile din text sunt, toate, reproduse de acolo. Au fost atasate acestor informatii câteva din lectiile tinute de Kathy Yelik ( la Universitatea din Berkeley, California, Statele Unite ale Americii, si anume acele lectii care se referǎ la structurile hardware si la modelele principale de programare. Din loc în loc, si continutul acestor lectii a fost prelucrat, uneori prescurtat, alteori adǎugat, pe baza altor lecturi din surse similare. Asadar, cititorul nu trebuie sǎ se astepte la vreo urmǎ de originalitate din partea autorului acestei juxtapuneri de texte si de material grafic. Ar fi si absurd a cere aşa ceva într-un domeniu cu o dinamicǎ extraordinarǎ, care în România, în particular la Ploieşti cunoaşte abia pasii de început. Alcǎtuirea acestui suport pentru cursul Arhitecturi paralele de calcul nu a fost lipsitǎ de dificultǎti. Prima dificultate si poate cea mai importantǎ a constat în selectarea temelor care urmau a fi incluse în cadrul dat de programa analiticǎ a cursului prevǎzut a se derula pe durata a 42 de ore. Pentru aceasta, autorul a citit (aproape de necrezut) câteva mii de pagini apǎrute pe parcursul a circa 10 ani. Unele dintre ele, câteva sute au fost si traduse în limba românǎ. În aceste conditii nu se poate afirma cu certitudine cǎ aceastǎ versiune a cursului, a treia, este cea optimǎ. Ar putea fi cel mult un punct de plecare în realizarea versiunilor urmǎtoare prin procedeul de-acum familiar copy-and-paste. A doua dificultate a constituit-o traducerea însǎsi. Sunt termeni care nu au încǎ echivalenţe stabile în româneste si, în plus, textele de specialitate în limba englezǎ abundǎ în acronime a cǎror semnificatie nu poate fi descoperitǎ 3

4 totdeauna contextual. Termenii greu traductibili au fost lǎsati în forma lor originalǎ, nu de putine ori acompaniati de explicatii detaliate, sau au fost lǎsati sǎ dubleze traducerile lor în limba românǎ, uneori aproximative. Pentru prescurtǎri si acronime s-au folosit dictionare on-line de tipul celor accesibile la adresa de Internet primarǎ Rǎmâne de discutat dacǎ din multiplele semnificatii ale unui acelasi acronim a fost retinutǎ de fiecare datǎ cea potrivitǎ. Subiectele tratate de reuniunea celor trei tutoriale mentionate mai devreme si de adaosul amitit sunt de naturǎ a familiariza studentii cu principiile generale ale calculului paralel si cu structurile hardware care le suportǎ. Sunt date, de asemenea, elemente destul de cuprinzǎtoare privind producerea de software, realizarea de aplicatii pentru cele douǎ arhitecturi paralele majore, cea cu memorie partajatǎ si cea cu memorie distribuitǎ. Standardele OpenMP, respectiv MPI asociate celor douǎ arhitecturi fundamentale sunt cuprinse în liniile lor directoare majore. Cu elementele explicate în cele douǎ tutoriale dedicate, studentii pot elabora propriile lor programe destinate executǎrii în paralel într-una sau alta dintre conjuncturile hardware mentionate. Structurile hardware acoperite prin acest suport de curs dau o idee destul de cuprinzǎtoare asupra stadiului curent si asupra tendintelor dezvoltǎrii calculului paralel în lume. Pentru detalii încǎ mai actuale, cititorul interesat în domeniu poate accesa site-ul CUPRINSUL INTRODUCERE ÎN CALCULUL PARALEL OpenMP 5 54 MPI - MESSAGE PASSING INTERFACE 102 MASINI PARALELE SI MODELE DE PROGRAMARE MASINI PARALELE CU MEMORIE PARTAJATǍ CALCULATOARE CU MEMORIE DISTRIBUITǍ SURSE DE PARALELISM

5 INTRODUCERE ÎN CALCULUL PARALEL Ce este calculul paralel? Traditional, programele de calcul s-au scris îndeobste în perspectiva unei executǎri secventiale sau seriale. S-au scris pentru a fi rulate pe un calculator care are o singurǎ unitate centralǎ de procesare. În aceste împrejurǎri, problemele sunt rezolvate printr-o secventǎ de instructiuni executate de unitatea centralǎ una câte una. O singurǎ instructiune poate fi în executie la un moment dat. În întelesul cel mai simplu, calculul paralel constǎ în utilizarea concomitentǎ a unor resurse multiple pentru a rezolva o problemǎ de calcul. Resursele acestea pot fi: Un singur calculator cu mai multe procesoare Un numǎr arbitrar de calculatoare conectate de o retea de comunicatie O combinatie a acestora. Problema de calcul trebuie sǎ exhibe uzual caracteristici de genul: Posibilitatea de a fi divizatǎ în pǎrti care pot fi rezolvate concomitent Posibilitatea de a fi executate în oricare moment instructiuni multiple Perspectiva de a fi rezolvatǎ în timp mai scurt pe resurse de calcul multiple decât pe o resursǎ standard unicǎ. Calculul paralel este o versiune extinsǎ a calculului secvential, versiune care încearcǎ sǎ imite ceea ce se întâlneste frecvent în naturǎ: multe întâmplǎri complexe si corelate se produc în acelasi timp desi sunt în sine secventiale. Câteva exemple: Orbitele planetare si galactice, parcurgerea lor de corpurile ceresti Formele de manifestare ale oceanului planetar si evolutia vremii Deplasarea plǎcilor tectonice Traficul într-un oras mare la ore de vârf Linia de asamblare a unui tip de automobil Operatiile zilnice în cadrul organizatoric al unei afaceri Construirea unui centru comercial Comandarea unui hamburger la un local quick-food Traditional, calculul paralel a fost considerat nivelul de sus al calculului si a fost motivat prin simulǎrile numerice ale unor sisteme complexe si prin mari provocǎri în domeniul calculului cum sunt: 5

6 Prezicerea vremii si a climei Modelarea reactiilor chimice si nucleare Transformarea genomului uman si al altor specii Activitatea geologicǎ si seismicǎ Proiectarea dispozitivelor mecanice de la proteze la nave spatiale Modelarea/proiectarea circuitelor electronice Conducerea proceselor de productie În zilele noastre, aplicatiile comerciale dau o fortǎ motoare cel putin egalǎ pentru dezvoltarea calculatoarelor din ce în ce mai rapide. Aceste aplicatii cer procesarea unor volume mari de date în moduri foarte rafinate. Exemple: Bazele de date paralel, data-mining Explorǎrile geologice Motoarele de cǎutare, serviciile comerciale bazate pe Internet Diagnosticarea medicalǎ ajutatǎ de calculator Managementul corporatiilor nationale si multinationale Graficǎ avansatǎ si realitatea virtualǎ, în particular în industria de entertainment Tehnologiile video si multimedia în retele Medii de lucru în cooperare În ultimǎ instantǎ, calculul paralel este o încercare de a face timpul elastic: el pare a fi infinit dar niciodatǎ nu pare a fi suficient. De ce se utilizeazǎ calculul paralel? Sunt douǎ motive principale pentru care se utilizeazǎ calculul paralel: Economia de timp timpul indicat de ceasul din perete Rezolvarea unor problema de mare amploare Alte ratiuni pot fi: A profita de resurse altele decât cele locale (când acestea sunt limitate) prin utilizarea unor resurse dintr-o retea mai largǎ, situate poate chiar pe Internet Economii la costul calculelor prin utilizarea unor resurse multiple ieftine în loc de a plǎti timpul consumat pe un supercalculator Depǎsirea restrictiilor de memorie: calculatoarele singure au posibilitǎti de memorare fatalmente limitate; pentru probleme de amploare, pentru a depǎsi acest obstacol paralizant se poate apela la memoriile mai multor calculatoare. În limitarea posibilitǎtilor de calcul secvential, în calea aparent simplǎ a construirii de calculatoare din ce în ce mai rapide apar restrictii atât de naturǎ fizicǎ cât si de naturǎ practicǎ: 6

7 Viteza de transmitere depinde direct de cât de repede se pot deplasa datele prin structura hardware. Limite absolute sunt viteza luminii (30 cm/ns) si limita de transmitere prin fire de cupru (9 cm/ns). Vitezele mai mari necesitǎ cresterea apropierii dintre elementelele procesoare. Limitele miniaturizǎrii: tehnologia procesoarelor permite un numǎr în crestere de tranzistoare pe un acelasi cip. Cu toate acestea, chiar cu componente la nivelul dimensiunilor moleculare sau atomice se atinge o limitǎ a miniaturizǎrii de nedepǎsit. Limite economice: este din ce în ce mai costisitor sǎ se producǎ procesoare unice încǎ si încǎ mai rapide. Prin utilizarea unui numǎr mare de procesoare ieftine si moderat de rapide, se pot obtine acelesi performante (sau poate mai bune) la un cost mai redus. Despre viitor: trendul ultimilor zece ani caracterizat de retele mai rapide decât înainte, de sisteme distribuite si de arhitecturile cu multe procesoare (chiar la nivelul calculatoarelor mici) sugereazǎ cǎ paralelismul este viitorul calculului. Concepte si terminologie Arhitectura von Neumann De peste 40 de ani, aproape toate calculatoarele au urmat un model comun de masinǎ cunoscut sub numele matematicianului maghiar John von Neumann. Un calculator von Neumann utilizeazǎ conceptul de program memorat. Unitatea centralǎ executǎ un program depus în memorie care indicǎ secventa de operatii, de lecturǎ si de scriere din/în memorie. Schema de bazǎ: Memoria este utilizatǎ pentru a stoca atât instructiunile programului cât si datele Instructiunile sunt un gen de date codate care spun calculatorului sǎ execute ceva anume 7

8 Datele sunt informatii pe care le utilizeazǎ programul O unitate centralǎ de procesare (CPU) preia instructiuni si/sau date din memorie, decodeazǎ instructiunile si apoi le executǎ secvential. Clasificarea clasicǎ dupǎ Flynn Existǎ modalitǎti diferite de a clasifica calculatoarele paralel. Una din cele mai utilizate, în uz din 1966, este clasificarea lui Flynn. Clasificarea Flynn face distinctie între arhitecturile calculatoarelor cu mai multe procesoare în raport cu douǎ caracteristici independente, instructiunile si datele. Fiecare din aceste caracteristici poate avea una din douǎ stǎri: unice sau multiple. Tabelul de mai jos defineste cele patru clase posibile potrivit criteriilor lui Flynn. SISD Single instruction, single data (instructiune unicǎ, date unice) MISD Mutiple instruction, single data (instructiune multiplǎ, date unice) SIMD Single instruction, multiple data (instructiune unicǎ, date multiple) MIMD Multiple instruction, multiple data (instructiune multiplǎ, date multiple) SISD: Un calculator secvential (neparalel) Instructiune unicǎ: un flux de numai o instructiune este executat de unitatea centralǎ în fiecare moment, în fiecare ciclu al ceasului Date unice: un flux de numai un articol-datǎ este utilizat ca intrare pe durata unui ciclu al ceasului Executia este deterministǎ Aceasta este cea mai veche formǎ de calculator si pânǎ de curând cea mai frecvent întâlnitǎ Exemple: cele mai multe PC-uri, statiile de lucru cu un singur CPU si calculatoarele mainframe 8

9 SIMD: Un tip de calculator paralel Instructiune unicǎ: toate unitǎtile procesoare executǎ aceeasi instructiune în fiecare ciclu al ceasului Date multiple: fiecare unitate procesoare poate opera pe un articol-datǎ diferit Acest tip de masinǎ are de obicei un dispecer de instructiuni, o retea internǎ de bandǎ foarte largǎ si un masiv cuprinzǎtor de unitǎti de instructiuni de foarte micǎ capacitate Foarte potrivit pentru probleme speciale caracterizate prin grad înalt de regularitate, cum ar fi procesarea de imagini Executie deterministǎ si sincronǎ (pasi cu bariere) Douǎ varietǎti: masive de procesoare si pipeline vectorial Exemple (unele depǎsite sau dispǎrute): Masive de procesoare (Processor Arrays): Connection Machine CM-2, Maspar MP-1, MP-2 Pipeline vectorial (Vector Pipelines): IBM 9000, Cray C90, Fujitsu VP, NEC SX-2, Hitachi S820 9

10 MISD: Putine exemple reale din aceastǎ clasǎ de calculatoare paralel au existat vreodatǎ Câteva exemple de conceput ar putea fi: Filtre de frecevente multiple care ar opera pe un singur flux de semnal Algoritmi de criptografie multiplǎ care ar încerca sǎ spargǎ un mesaj codat unic MIMD: În mod curent, cel mai obisnuit tip de calculator paralel Instructiuni multiple: procesoarele pot executa fluxuri diferite de instructiuni Date multiple: fiecare procesor poate lucra pe un flux de date diferit de al altor procesoare Executia poate fi sincronǎ sau asincronǎ, deterministǎ sau nedeterministǎ Exemple: cele mai multe din supercalculatoarele curente, grilele de calculatoare paralele în retea si calculatoarele SMP (Symmetric MultiProcessing) multiprocesoare inclusiv unele tipuri de PC-uri. 10

11 Terminologie generalǎ pentru calculul paralel Ca orice sector de activitate, calculul paralel are propriul jargon. În continuare sunt dati câtiva termeni de uz obisnuit în calculul paralel. Task o sectiune logic discretǎ a efortului de calcul. Tipic, un task este un program sau un set de instructiuni asemǎnǎtoare unui program care este executat de un procesor. Task parlel un task care poate fi executat de procesoare multiple în conditii de sigurantǎ (care genereazǎ rezultate corecte). Executie serialǎ executarea secventialǎ a unui program, declaratie cu declaratie. În sensul cel mai simplu, este ceea ce se întâmplǎ într-o masinǎ cu un singur procesor. Virtual, si când toate task-urile sunt paralel existǎ sectiuni ale unui program paralel care trebuie executate serial. Executie paralelǎ executie a unui program prin mai mult decât un task, cu fiecare task capabil sǎ execute concomitent aceeasi declaratie sau declaratii diferite. Memorie partajatǎ (în indiviziune) din punct de vedere strict hardware este o arhitecturǎ în care toate procesoarele au acces direct (si de obicei bazat pe bus) la memoria fizicǎ comunǎ. În sensul programǎrii, formula descrie un model în care task-urile paralele au toate aceeasi imagine a memoriei si se pot adresa si pot accesa direct aceleasi locatii logice de memorie indiferent unde existǎ memoria fizicǎ în realitate. Memorie distribuitǎ în sensul hardware se referǎ la accesul la o memorie, care fizic nu este comunǎ, printr-o retea. Ca model de programare, task-urile pot vedea logic numai memoria localǎ a masinii si trebuie sǎ apeleze la comunicare pentru a avea acces la memoria altor masini unde alte task-uri sunt în curs de executie. 11

12 Comunicare obisnuit, task-urile paralele trebuie sǎ schimbe date. Existǎ mai multe moduri în care se poate comunica: printr-un bus al memoriilor utilizat în indiviziune (partajat) sau printr-o retea. Indiferent de modalitatea utilizatǎ, schimbul real de date este denumit uzual comunicare. Sincronizare coordonarea task-urilor paralel în timp real, foarte frecvent asociatǎ cu comunicarea. Implementatǎ adesea prin stabilirea unui punct de sincronizare în aplicatie unde un task nu poate continua pânǎ când alt(e) task(uri) nu ating(e) acelasi punct sau acelasi punct echivalent logic. Sincronizarea implicǎ uzual asteptǎri cel putin pentru un task si poate cauza prin aceasta o crestere a timpului de executie (timp universal ceasul din perete) a aplicatiei paralel. Granularitate în calculul paralel, granularitatea este o mǎsurǎ calitativǎ a raportului calcul/comunicare. Granularitatea poate fi: Grosierǎ: relativ mult calcul între fazele (evenimentele) de comunicare Finǎ: relativ putin calcul între fazele (evenimentele) de comunicare Accelerarea observatǎ a unui cod care a fost paralelizat se defineste ca raportul: (timpul dupǎ ceasul din perete la executia serialǎ)/(timpul dupǎ ceasul din perete la executia paralelǎ) Este unul din cei mai simpli si mai larg utilizati indicatori ai performantelor unui program paralel. Overhead-ul paralel durata necesarǎ pentru a coordona task-urile paralel, în opozitie cu executarea de lucru util. Overhead-ul paralel poate include elemente de genul: Timpul de pornire a task-ului Sincronizǎrile Comunicarea de date Overhead-ul software impus de compilatoarele paralel, biblioteci, instrumente (tools), sistemul de operare etc. Timpul de încheiere a task-ului Masiv paralel se referǎ la un sistem hardware care constituie un sistem paralel dat, care are multe procesoare. Semnificatia lui multe este în crestere dar în prezent multe înseamnǎ de la 1000 în sus. Scalabilitate se referǎ la capacitatea unui sistem paralel (hardware si/sau software) de a demonstra în accelerarea (speedup) paralelǎ o crestere proportionalǎ odatǎ cu atasarea mai multor procesoare. Factori care contribuie la scalabilitate: Hardware în particular lǎrgimea de bandǎ memorie-cpu si reteaua de comunicare Algoritmul aplicatiei Overhead-ul paralel asociat Caracteristicile specifice ale aplicatiei si programului 12

13 Arhitecturi ale memoriei în calculul paralel Memorie partajatǎ (în indiviziune) Caracteristici generale: Calculatoarele paralel cu memorie partajatǎ variazǎ larg ca structurǎ dar în general au comunǎ posibilitatea datǎ tuturor procesoarelor de a accesa toatǎ memoria ca spatiu de adresare global. Procesoarele multiple pot opera independent dar folosesc în indiviziune (partajat) aceleasi resurse de memorie Schimbǎrile într-o locatie de memorie efectuate de un procesor sunt vizibile tuturor celorlalte procesoare Masinile cu memorie partajatǎ pot fi împǎrtite în douǎ clase majore pe baza duratelor de acces la memorie: UMA si NUMA. Uniform Memory Access (UMA): Reprezentate azi obisnuit prin multiprocesoarele simetrice (SMP Symmetric MultiProcessor) Procesoarele sunt identice Acees egal si durate de acces egale la memorie Denumite uneori CC-UMA Cache Coherent UMA. Coerenta cache înseamnǎ cǎ o actualizare fǎcutǎ de un procesor într-o locatie din memoria partajatǎ este cunoscutǎ de toate celelalte procesoare. Coerenta cache este realizatǎ la nivelul hardware. 13

14 Non-Uniform Memory Access (NUMA): Alcǎtuitǎ deseori prin legarea fizicǎ a doua sau mai multe SMP-uri Un SMP poate accesa direct memoria altui SMP Nu toate procesoarele au durate de acces egale la toate memoriile Accesul la memorie prin legǎturǎ este mai lent Dacǎ coerenta cache este mentinutǎ atunci se vorbeste de CC-NUMA, NUMA cu coerentǎ de cache Avantaje: Spatiul de adresare global dǎ programatorului o perspectivǎ prietenoasǎ asupra memoriei Partajarea datelor între task-uri este si rapidǎ si uniformǎ datoritǎ proximitǎtii memorie-cpu-uri Dezavantaje: Dezavantajul prim este lipsa scalabilitǎtii între memorie si CPU-uri. Atasarea mai multor CPU poate face sǎ creascǎ geometric traficul asociat cu administrarea cache/memorie Responsabilitate crescutǎ a programatorului pentru constructe de sincronizare care sǎ asigure accesul corect la memoria globalǎ Cheltuieli: devine din ce în ce mai dificil si costisitor a proiecta si a produce masini cu memorie partajatǎ cu numǎr de procesoare permanent crescǎtor. Memorie distributǎ Caracteristici generale: Ca si sistemele cu memorie partajatǎ, sistemele cu memorie distribuitǎ cunosc o varietate largǎ dar au caracteristici comune. Sistemele cu memorie distribuitǎ necesitǎ o retea de comunicatie pentru a conecta memoria procesoarelor. 14

15 Procesoarele au memoria lor localǎ. Adresele de memorie ale unui procesor nu se asociazǎ cu un alt procesor asa încât nu existǎ conceptul de spatiu de adresare global care sǎ cuprindǎ toate procesoarele Deoarece fiecare procesor are memoria sa proprie localǎ, el opereazǎ independent. Schimbǎrile pe care el le face în memoria lui proprie, localǎ nu are nici un efect asupra memoriilor celorlalte procesoare. Prin urmare conceptul de coerentǎ cache nu se aplicǎ. Dacǎ un procesor necesitǎ acces la datele detinute de un alt procesor, este uzual sarcina programatorului de a defini explicit cum si când datele respective sunt comunicate. Sincronizarea între task-uri este tot asa, în responsabilitatea programatorului. Tesǎtura retelei utilizate pentru transferul de date variazǎ mult desi ea poate fi la fel de simplǎ ca metoda Ethernet. Avantaje: Memoria este scalabilǎ cu numǎrul de procesoare. Cresterea numǎrului de procesoare are ca urmare cresterea proportionalǎ a memoriei. Fiecare procesor poate avea acces rapid la memoria proprie fǎrǎ interferentǎ si fǎrǎ overhead-ul legat de încercarea de a mentine o coerentǎ de cache. Eficientǎ sub aspectul costului: se pot utiliza procesoare ieftine si retele ieftine (commodity, off-the-shelf). Dezavantaje: Programatorul este responsabil pentru multe detalii asociate cu comunicarea între procesoare. Poate fi dificil a asocia (to map) structuri de date existente, bazate pe o memorie globalǎ, pe o astfel de organizare a memoriei. Comparatie între arhitecturile cu memorie partajatǎ si distribuitǎ Arhitectura CC-UMA CC-NUMA Distribuitǎ Smp-uri SGI Origin Cray T3E Sun Vexx Sequent Maspar Exemple DEC/Compaq HP Exemplar IBM SP2 SGI Challenge DEC/Compaq IBM POWER3 IBM POWER4 MPI MPI Threads Threads Comunicatie MPI OpenMP OpenMP shmem shmem La zeci de La sute de La mii de Scalabilitate procesoare proesoare procesoare Neajunsuri Lǎrgimea de Lǎrgimea de Administrarea bandǎ memorie- bandǎ memorie- sistemului CPU CPU Programare dificil 15

16 Timp de acces de dezvoltat si de neuniform întretinut Accesibiltatea la Multe mii de ISV Multe mii de ISV Sute de ISV software ISV = Independent Software Vendor (producǎtori independenti de softvare) Memorii hibride, distribuite si partajate O recapitulare a caracteristicilor cheie ale masinilor cu memorie partajatǎ si cu memorie distribuitǎ este datǎ în tabelul de mai sus. Calculatoarele cele mai mari si cele mai rapide din lumea contemporanǎ utilizeazǎ arhitecturi atât cu memorie partajatǎ cât si cu memorie distribuitǎ. Componentele cu memorie partajatǎ sunt de obicei masini SMP cache-coerente. Procesoarele unui SMP dat pot adresa memoria acelei masini ca fiind globalǎ. Componenta cu memorie distribuitǎ este o retea de mai multe SMP-uri. SMPurile sunt constiente numai de memoria proprie, nu si de memoriile celorlalte SMP-uri. Prin urmare comunicarea prin retea este necesarǎ pentru a deplasa date de la un SMP la altul. Tendinta curentǎ pare a indica faptul cǎ acest tip de arhitecturǎ a memoriei va continua sǎ prevaleze si sǎ creascǎ cǎtre nivelul cel mai de sus al calculului în viitorul previzibil. Avantajele si dezavantajele celor douǎ tipuri pure de arhitecturǎ a memoriei sunt cumva împǎrtite de arhitectura aceasta hibridǎ. Modele de programare parlel Generalitǎti În uzul comun sunt mai multe modele de programare paralel: Memorie partajatǎ 16

17 Fire (threads) Transfer de mesaje Paralel pe date Hibrid Modelele de programare paralel existente fac abstractie de arhitecturile hardware si de arhitecturile memoriei. Desi poate cǎ nu sunt percepute astfel, aceste modele nu sunt specifice vreunui tip particular de masinǎ sau vreunei arhitecturi de memorie. În realitate, oricare dintre aceste modele poate fi (teoretic) implementat pe orice structurǎ hardware. Douǎ exemple: 1. Modelul cu memorie partajatǎ pe o masinǎ cu memorie distribuitǎ: Kendall Square Research (KSR) varianta ALLCACHE. Memoria masinii este fizic distribuitǎ dar apare utilizatorului ca o memorie unitarǎ partajatǎ (spatiu de adresare global). La modul generic, aceastǎ tratare este denumitǎ memorie partajatǎ virtualǎ. Notǎ: desi KSR nu mai existǎ pe piatǎ, nu existǎ vreun motiv sǎ se creadǎ cǎ o implementare similarǎ este exclusǎ în viitor. 2. Modelul cu transfer de mesaje pe o masinǎ cu memorie partajatǎ: MPI pe SGI Origin. SGI Origin utilizeazǎ arhitectura de memorie partajatǎ de tipul CC_NUMA, unde fiecare task are acces direct la memoria globalǎ. Capabilitatea de a trimite si receptiona mesaje cu MPI, cum se face obisnuit într-o retea de masini cu memorie distribuitǎ nu este numai implementatǎ ci este si utilizatǎ uzual. Alegerea unui model este adesea o combinatie de ceea ce este la îndemânǎ si de optiune personalǎ. Nu existǎ un model perfect, desi existǎ cu certitudine implementǎri mai bune, mai reusite ale unui model fatǎ de altele. Sectiunile urmǎtoare descriu fiecare din modelele enumerate mai devreme si aduc în discutie unele din implemetǎrile lor reale. Modelul cu memorie partajatǎ În modelul de programare cu memorie partajatǎ task-urile împart un spatiu de adresare comun pe care îl folosesc pentru scriere si lecturǎ în mod asincron. Pentru controlul accesului la memoria partajatǎ se pot folosi mecanisme variate cum sunt blocajele (locks) si semafoarele. Din punctul de vedere al programatorului, un avantaj al acestui model este acela cǎ notiunea de proprietate asupra datelor lipseste, asa încât nu este necesar a specifica explicit comunicarea de date între task-uri. Dezvoltarea unui program poate fi adesea simplificatǎ. Un dezavantaj major în materie de performante este faptul cǎ întelegerea si managementul localizǎrii datelor devine mai dificilǎ. Implementǎri: 17

18 Pe platformele cu memoria partajatǎ, compilatoarele dedicate traduc variabilele programului definite de utilizator în adrese de memorie reale, care sunt globale. Nu existǎ la acest moment nici o implementare pe platforme cu memorie distribuitǎ. Totusi, cum s-a mentionat mai sus, realizarea KSR ALLCACHE a dat o vedere a datelor ca într-o memorie partajatǎ chiar dacǎ fizic memoria masinii era distribuitǎ. Modelul cu fire (threads) În modelul de programare paralel cu fire, un singur proces poate avea cǎi de executie multiple, concurente în sensul cǎ concurǎ la îndeplinirea sarcinii de calcul. Probabil cǎ analogia cea mai simplǎ care poate fi utilizatǎ pentru a descrie firele o reprezintǎ conceptul programului unic care include un numǎr de subrutine: Programul principal a.out este planificat la executie de sistemul de operare nativ. a.out încarcǎ si angajeazǎ toate resursele de sistem si de utilizator pentru a fi executat. a.out executǎ ceva lucru serial si apoi creazǎ un numǎr de task-uri (fire) care pot fi planificate la executie si executate de sistemul de operare în modul concurent. Fiecare fir are date locale, dar totodatǎ foloseste în indiviziune toate resursele lui a.out. Aceasta salveazǎ din overhead-ul asociat cu replicarea resurselor programului pentru fiecare fir. Fiecare fir beneficiazǎ totodatǎ de vedere spre memoria globalǎ deoarece el utilizeazǎ partajat spatiul de memorare al programului a.out. 18

19 Lucrul unui fir poate fi descris cel mai bine ca o subrutinǎ în programul principal. Orice fir poate executa orice subrutinǎ în acelasi timp cu alte fire. Firele comunicǎ între ele prin intermediul memoriei globale (prin actualizarea locatiilor adresate). Aceasta reclamǎ constructe de sincronizare pentru a fi datǎ siguranta cǎ niciodatǎ nu se întâmplǎ ca mai mult de un fir sǎ actualizeze aceeasi adresǎ globalǎ. Firele pot deveni active si se pot încheia dar a.out rǎmâne prezent pentru a asigura resursele partajate necesare pânǎ la încheierea aplicatiei. Firele sunt asociate uzual cu arhitecturile cu memorie partajatǎ si sistemele de operare partajate. Implementǎri: Obisnuit, din perspectiva programǎrii, implementarea firelor cuprinde: O bibliotecǎ de subrutine care sunt apelate din codul sursǎ paralel Un set de directive de compilare încorporate fie în codul sursǎ serial, fie în cel paralel. În ambele cazuri programatorul este responsabil cu determinarea întregului paralelism. Implementarea firelor nu este nouǎ în tehnicile de calcul. Istoric, producǎtorii de hardware au implementat propria lor versiune de fire proprietate de firmǎ. Aceste implementǎri au diferit una de alta, ceea ce a fǎcut dificil pentru programatori sǎ dezvolte aplicatii portabile bazate pe fire. Prin eforturi de standardizare independente au rezultat douǎ implementǎri de fire, foarte diferite: POSIX Threads si OpenMP. Implementarea POSIX Threads Bazatǎ pe biblioteci; cere coduri paralel. Specificatǎ de standardul IEEE POSIX c (1995). Numai în limbajul C. Cunoscutǎ uzual ca Pthreads. Cei mai multi producǎtori de hardware oferǎ acum Pthreads, aditional la implementarea de proprietar a firelor. Paralelism foarte explicit; cere din partea programatorului o atentie la detalii semnificativǎ. Implementarea OpenMP Bazatǎ pe directive de compilare; poate utiliza cod serial. Definit si aprobat colectiv de un grup de producǎtori majori de hardware si software. Varianta OpenMP Fortran API a fost lansatǎ în 1997; varianta C/C++ API a fost lansatǎ în anul urmǎtor. Portabilǎ pe multe platforme, inclusiv pe platforme Unix si Windows NT. 19

20 Foarte usor si simplu de utilizat datǎ fiind capacitatea de a oferi paralelism incremental. Microsoft are propria sa implementare pentru fire, care nu este înruditǎ nici cu standardul UNIX POSIX, nici cu OpenMP. Modelul cu transfer de mesaje Modelul cu transfer de mesaje posedǎ urmǎtoarele caracteristici: Un set de task-uri care utilizeazǎ în timpul calculului propria lor memorie localǎ. Task-urile multiple pot fi rezidente pe aceeasi masinǎ fizicǎ la fel de bine ca si pe un numǎr arbitrar de masini. Task-urile schimbǎ date prin comunicare, prin expedierea si primirea de mesaje. Transferul de date implicǎ de obicei operatii în cooperare executate de fiecare proces. De pildǎ, o operatie de trimitere trebuie sǎ aibǎ ca pereche o operatie de primire. Implementǎri: Din perspectiva programǎrii, implemetǎrile transferului de mesaje cuprinde uzual o bibliotecǎ de subrutine care sunt încorporate în codul sursǎ. Programatorul este rǎspunzǎtor de determinarea întregului paralelism. Istoric, o varietate apreciabilǎ de biblioteci pentru tranferul de mesaje a fost accesibilǎ încǎ din anii Aceste implementǎri difereau substantial între ele, ceea ce fǎcea dificilǎ pentru programatori dezvoltarea de aplicatii portabile. În 1992 s-a format Forum-ul MPI cu scopul principal de a stabili o interfatǎ standard pentru implementǎrile transferului de mesaje. Partea I-a a Message Passing Interface (MPI) a fost lansatǎ în Partea a II-a (MPI-2) a fost lansatǎ în Ambele variante MPI cu specificatiile continute sunt accesibile la MPI este acum standardul industrial de facto pentru transferul de mesaje, înlocuind practic toate celelalte implementǎri. Cele mai multe, 20

21 dacǎ nu toate platformele populare de calcul paralel oferǎ cel putin o implementare MPI. Câteva din ele au implementarea completǎ a MPI-2. Pentru arhitecturile cu memorie partajatǎ, implementǎrile MPI nu utilizeazǎ retele pentru comunicarea între task-uri. În loc de asta ele folosesc din motive de performantǎ memoria partajatǎ (cópii ale memoriei). Modelul paralel pe date Modelul paralel pe date are caracteristicile urmǎtoare: Cea mai mare parte a lucrului paralel se concentreazǎ pe executarea operatiilor pe un set de date. Setul de date este organizat uzual ca o structurǎ comunǎ, ca un masiv (array) sau ca un cub. Un set de task-uri lucreazǎ colectiv pe o aceeasi structurǎ de date, dar fiecare task lucreazǎ pe o parte distinctǎ dintr-o partitie a aceleiasi structuri de date. Task-urile executǎ aceeasi operatie pe bucata lor de actiune, de pildǎ adunǎ numǎrul 5 la fiecare element al masivului. Pe arhitecturile cu memorie partajatǎ, toate task-urile au acces la structura de date din memoria globalǎ. La arhitecturile cu memorie distribuitǎ structura de date este divizatǎ si devine rezidentǎ pe zone ale memoriei locale a fiecǎrui task. Implementǎri: 21

22 Programarea cu modelul paralel pe date se face uzual prin scrierea unui program cu constructe de date paralel. Constructele pot fi apeluri la o bibliotecǎ de subrutine paralel pe date sau directive ale compilatorului recunoscute de un compilator paralel pe date. Fortran 90 (F90): extensii standard ISO/ANSI ale Fortranului 77. Contine tot ce cuprinde Fortranul 77 Un nou format al codului; adǎugǎri la setul de caractere Adǎugǎri la structura programului si comenzilor Adǎugǎri de variabile metode si argumente Pointeri si alocǎri de memorie în supliment Procesarea masivelor (tratate ca obiecte) ca adaos Adaos de functii intrinseci noi si recursive Implementǎrile sunt accesibile pentru cele mai multe platforme paralel obisnuite. High Perfomance Fortran (HPF): extensii de Fortran 90 care admit/suportǎ programarea paralel pe date. Contine tot ceea ce contine si Fortranul 90 Aditional, directive care spun compilatorului cum sǎ distribuie datele Adǎugat, asertiuni care pot îmbunǎtǎti/optimiza codul generat Suplimentar, constructe de date paralel (acum parte din Fortranul 95) Implementǎrile sunt accesibile pentru cele mai multe platforme paralel obisnuite. Directive de compilare: permit programatorului specificarea distribuirii si alinierii datelor. Implementǎrile Fortran sunt accesibile pentru cele mai multe platforme paralel obisnuite. Implementǎrile cu memorie distribuitǎ ale acestui model au compilatorul capabil a converti programul într-un cod standard cu apeluri la o bibliotecǎ de transfer de mesaje (uzual MPI) pentru a distribui datele tuturor proceselor. Toate transferurile de mesaje sunt executate invizibil pentru program. Alte modele Existǎ si alte modele de programare paralel peste acelea mentionate mai sus. Acestea vor continua sǎ evolueze odatǎ cu lumea calculatoarelor în permanentǎ schimbare si sofware si hardware. Sunt date mai jos trei din cele mai frecvente. Un model hibrid: Acest model combinǎ douǎ sau mai multe dintre modelele de programare paralel prezentate pânǎ acum. Un exemplu la îndemânǎ este modelul care combinǎ modelul cu transfer de mesaje (MPI) fie cu modelul cu fire (POSIX threads), fie cu modelul cu 22

23 memorie paralelǎ (OpenMP). Acest model hibrid se potriveste bine sistemelor din ce în ce mai prezente alcǎtuite din retele de SMP-uri. Un alt exemplu comun de model hibrid este cel care combinǎ modelul paralel pe date cu transferul de mesaje. Cum s-a semnalat mai devreme, în sectiunea dedicatǎ modelului paralel pe date, implementǎrile paralel (F90, HPF) pe arhitecturi cu memorie distribuitǎ folosesc de fapt transferul de mesaje pentru a transmite date între task-uri în modul transparent pentru programator. Program unic, date multiple (SPMD Single Program Multiple Data) SPMD este de fapt un model de programare de nivel înalt care poate fi construit pe orice combinatie de modele de programare paralel descrise mai devreme. Un singur program este executat de toate task-urile simultan. La un moment oarecare task-urile pot executa instructiuni identice sau diferite, dar din acelasi program. Programele SPMD au de obicei logica necesarǎ programatǎ în ele pentru a permite diferitelor task-uri sǎ se ramifice sau sǎ execute conditionat numai acele pǎrti din programul pentru care sunt desemnate sǎ le execute. Asta înseamnǎ cǎ task-urile nu trebuie obligatoriu sǎ execute întregul program, ci foarte probabil numai pǎrti din el. Task-urile pot utiliza date diferite. Programe multiple, date multiple (MPMD Multiple Program Multiple Data) Ca si SPMD, MPMD este în realitate un model de programare de nivel înalt care poate fi construit pe baza oricǎrei combinatii de modele de programare paralel mentionate mai devreme. 23

24 Aplicatiile MPMD au tipic fisiere obiect executabile multiple (programe). În timp ce aplicatia este rulatǎ în paralel, fiecare task poate excuta un acelasi program sau un program diferit de alte task-uri. Task-urile pot utiliza date diferite. Proiectarea de programe paralele Paralelizarea automatǎ sau manualǎ Proiectarea si dezvoltarea programelor paralel au fost în esentǎ procese manuale. Programatorul este de obicei responsabil atât pentru identificarea cât si pentru implementarea realǎ a paralelismului. Foarte frecvent, dezvoltarea manualǎ a codurilor paralele este consumatoare de timp, complexǎ, susceptibilǎ de erori si iterativǎ. De un numǎr de ani deja, au devenit accesibile instrumente variate de asistare a programatorului în conversia programelor secventiale în programe paralele. Tipul cel mai comun de instrument utilizat pentru a paraleliza automat un program serial este un compilator paralelizator sau un pre-procesor. Un compilator de paralelizare lucreazǎ în general în douǎ moduri diferite: Deplin automatizat Compilatorul analizeazǎ codul sursǎ si identificǎ paralelismele posibile. Analiza include identificarea de inhibitori de paralelism si face o posibilǎ ponderare prin costuri a situatiilor diferite când paralelismul sporeste performanta sau o diminuǎ. Buclele (do, for) sunt tinta cea mai frecventǎ a paralelizǎrii automate. Regizatǎ de programator Utilizând directive de compilare sau posibile flag-uri de compilare, programatorul spune explicit compilatorului cum sǎ paralelizeze codul. Operatia poate fi folositǎ si în combinatie cu o dozǎ anumitǎ de paralelizare automatǎ. 24

25 Dacǎ se începe cu un cod secvential existent si sunt restrictii de timp sau de buget, atunci paralelizarea automatǎ poate fi un rǎspuns. Sunt însǎ câteva capcane importante referitoare la paralelizarea automatǎ: Pot apǎrea rezultate gresite Performatele se pot degrada în realitate Este mai putin flexibilǎ decât paralelizarea manualǎ Limitatǎ la un subset al codului, de regulǎ buclele Poate realmente sǎ nu se obtinǎ o paralelizare a codului dacǎ analiza sugereazǎ existenta unor inhibitori de paralelizare sau codul este prea complex Cele mai multe instrumente de paralelizare automatǎ sunt pentru Fortran. În continuarea acestei sectiuni sunt discutate metodele manuale de a dezvolta coduri paralele. Întelegerea problemei si a programului Fǎrǎ îndoialǎ, primul pas în dezvoltarea de software paralel este a întelege problema de rezolvat în paralel. Dacǎ începutul este cu un program secvential, si acesta trebuie înteles. Înainte de a consuma timp cu o încercare de a dezvolta o solutie paralel pentru o problemǎ, se determinǎ dacǎ acea problemǎ este sau nu una care poate fi paralelizatǎ practic. Exemplu de problemǎ paralelizabilǎ: Sǎ se calculeze energia potentialǎ pentru fiecare din mai multe mii de conformatii independente ale unei molecule. Când calculul acesta este fǎcut, sǎ se afle conformatia de energie minimǎ. Aceastǎ problemǎ poate fi rezolvatǎ în paralel. Fiecare conformatie molecularǎ este determinabilǎ independent. Calculul conformatiei de energie minimǎ este de asemenea paralelizabilǎ. Exemplu de problemǎ neparalelizabilǎ: Calculul seriei Fibonacci (1, 1, 2, 3, 5, 8, 13, 21, ) cu utilizarea formulei F(k + 2) = F(k + 1) + F(k). Aceasta nu este o problemǎ care sǎ poatǎ fi paralelizatǎ deoarece calculul secventei Fibonacci, asa cum se vede, implicǎ evaluǎri dependente, nu independente. Calcularea valorii pentru k + 2 utilizeazǎ valorile pentru k + 1 si pentru k. Acesti trei termeni nu pot fi calculati independent si prin urmare nu pot fi calculati în paralel. Identificarea punctelor fierbinti ale programului: Este important a sti unde se consumǎ partea principalǎ a efortului de calcul. Majoritatea programelor stiintifice si tehnice au concentrat uzual acest efort în câteva locuri. 25

26 Instrumentele de analizǎ a performantelor si a profilului pot fi de ajutor în aceastǎ etapǎ. Concentrare pe paralelizarea acestor puncte fierbinti (hotspot) si ignorarea acelor sectiuni de program care consumǎ putin timp CPU. Identificarea strangulǎrilor din program: Existǎ zone care sunt disproportionat de lente sau care produc opriri sau întârzieri ale lucrului paralel? De pildǎ, operatiile I/O sunt evenimente care încetinesc calculul. Programul poate fi restructurat sau algoritmul poate fi schimbat pentru a elimina sau a reduce episoadele lente. Identificarea de inhibitori ai paralelismului. O clasǎ comunǎ de inhibitori o constituie dependenta datelor cum s-a exemplificat în exemplul cu secventa Fibonacci. Investigarea unor algoritmi diferiti dacǎ este posibil. Aceasta poate fi unica reconsiderare foarte importantǎ la proiectarea aplicatiilor paralel. Partitionarea Unul din primii pasi în proiectarea unui program paralel este spargerea problemei în fragmente discrete de actiune care pot fi distribuite task-urilor multiple. Aceastǎ operatie este cunoscutǎ ca descompunere sau partitionare. Sunt douǎ cǎi fundamentale de a partitiona efortul de calcul între task-uri paralel: descompunerea domeniului si descompunerea functionalǎ. Descompunerea de domeniu: În acest tip de partitionare, datele asociate unei probleme sunt cele care sunt descompuse. Fiecare task paralel lucreazǎ atunci pe o portiune din date. Modalitǎtile de descompunere si repartizare a datelor sunt diferite: 26

27 Descompunerea functionalǎ: În acest caz, atentia este focalizatǎ pe calculele care trebuie executate si nu pe datele manipulate în cursul calculelor. Problema este descompusǎ potrivit cu efortul de calcul care trebuie fǎcut. Fiecare task se dedicǎ atunci unei fractiuni din efortul general. Descompunerea functionalǎ se impune si se aplicǎ în cazul problemelor care pot fi separate în task-uri diferite. De exemplu: 27

28 Modelarea ecosistemelor diagrama de mai jos aratǎ cinci procese si fiecare executǎ un program diferit. Fiecare program calculeazǎ populatia unui grup dat, iar cresterea fiecǎrui grup depinde de aceea a grupurilor vecine. Cu trecerea timpului, fiecare proces calculeazǎ starea sa curentǎ, apoi schimbǎ informatii cu populatiile vecine. Toate task-urile trec apoi la a calcula starea la momentul urmǎtor, dupǎ încǎ un pas de timp. Procesarea semnalelor un set de date despre un semnal audio este trecut prin trei filtre numerice (etape de calcul) distincte. Fiecare filtru este un proces de calcul separat. Primul segment de date trebuie sǎ treacǎ prin primul filtru înainte de a avansa la al doilea. Când etapa aceasta s-a încheiat, al doilea segment de date trece prin primul filtru. La timpul la care al treilea segment este în primul filtru, toate task-urile sunt ocupate. 28

29 Modelele climatice fiecare model component poate fi gândit ca un task separat. Sǎgetile aratǎ schimburile de date între componente pe durata calculului: modelul atmosferei genereazǎ vitezele vântului care sunt utilizate în modelul oceanic, apoi modelul oceanului genereazǎ temperaturile la suprafata apei care sunt utilizate de modelul atmosferic s.a.m.d. Combinarea acestor douǎ tipuri de descompunere a unei probleme este uzualǎ si fireascǎ. Comunicarea Cine are nevoie de comunicare? Necesarul de comunicare depinde de problema care trebuie rezolvatǎ. Comunicarea nu este necesarǎ în cazul unor probleme care pot fi descompuse si executate în paralel virtual fǎrǎ necesitatea ca task-urile sǎ împartǎ datele, de pildǎ o operatie de procesare a unei imagini în care fiecǎrui pixel alb sau negru trebuie sǎ i se inverseze culoarea. Datele de imagine pot fi usor repartizate pe task-uri multiple care vor actiona apoi independent unul de altul pentru a-si face treaba proprie. Problemele de acest tip sunt denumite adesea jenant de paralele (embarrassingly parallel) deoarece ele sunt atât de directe. Este necesarǎ foarte putinǎ comunicare între task-uri. Comunicarea este necesarǎ pentru multe aplicatii paralel care nu sunt tocmai simple si necesitǎ utilizarea partajatǎ a datelor de cǎtre task-uri diferite. De pildǎ, o problemǎ de transfer de cǎldurǎ în 3 dimensiuni (3D) cere ca un task sǎ cunoascǎ temperaturile calculate de task-urile care detin datele învecinate unei zone. Schimbǎrile datelor învecinate au efect direct asupra datelor acelui task. Factori de luat în considerare Sunt câtiva factori importanti care trebuie luati în considerare la proiectarea comunicǎrii dintre task-uri: Costul comunicǎrii Comunicarea între task-uri implicǎ virtual totdeauna un overhead. Cicluri ale masinii si resurse care ar putea fi utilizate pentru calcul sunt deturnate pentru a împacheta si a transmite date. Comunicarea cere frecvent un anumit tip de sincronizare între task-uri, care se poate traduce în timp de asteptare în loc de timp de lucru util. Traficul comunicational competitiv poate satura lǎrgimea de bandǎ disponibilǎ a retelei, ceea ce ar putea agrava si mai mult problemele legate de performantǎ. Latenta si lǎrgimea de bandǎ Latenta este timpul consumat pentru a trimite un mesaj minimal (0 bytes) de la punctul A la punctul B. Se exprimǎ uzual în microsecunde. 29

30 Lǎrgimea de bandǎ este cantitatea de date care pot fi comunicate în unitatea de timp. Se exprimǎ uzual în megabytes/secundǎ. Expedierea multor mesaje scurte poate face latenţa dominantǎ în overhead-urile de comunicare. Adesea este mai eficient a împacheta mesajele mǎrunte într-unul mai mare: prin aceasta se poate mǎri lǎrgimea de bandǎ de comunicare efectivǎ. Vizibilitatea comunicǎrii În cazul modelului cu transfer de mesaje, comunicarea este explicitǎ si în general este destul de la vedere si sub controlul programatorului. În cazul modelului paralel pe date, comunicarea apare rareori transparent programatorului, în particular pe arhitecturile cu memorii distribuite. Programatorul poate chiar sǎ nu fie capabil a sti exact cum este efectuatǎ comunicarea între task-uri. Comunicare sincronǎ sau asincronǎ Comunicarea asincronǎ cere un tip anume de strângere de mânǎ între task-uri care folosesc date în indiviziune. Aceasta poate fi structuratǎ explicit în cod de programator sau se poate produce la un nivel mai jos necunoscut programatorului. Comunicarea sincronǎ este adesea denumitǎ comunicare cu blocare deoarece altǎ lucrare trebuie sǎ astepte pânǎ ce comunicarea s-a isprǎvit. Comunicarea asincronǎ permite task-urilor sǎ transfere date independent unul de altul. De pildǎ, task-ul 1 poate pregǎti si trimite un mesaj taskului 2 si apoi sǎ treacǎ imediat la executarea altei lucrǎri. Nu are importantǎ când task-ul 2 primeste în realitate datele. Comunicarea asincronǎ este denumitǎ uneori comunicare fǎrǎ blocare deoarece în timp ce comunicarea are loc se pot derula alte lucrǎri. Intercalarea calculului cu comunicarea este singurul mare beneficiu al utilizǎrii comunicǎrii asincrone. 30

31 Domeniul acoperit prin comunicare Cunoasterea task-urilor care comunicǎ între ele este criticǎ în timpul etapei de proiectare a unui cod paralel. Ambele delimitǎri de domeniu de comunicare descrise mai jos pot fi implementate sincron sau asincron. Punct-la-punct implicǎ douǎ task-uri, unul expeditor/producǎtor de date, celǎlalt receptor/consumator. Colectivǎ implicǎ diviziunea datelor între mai mult de douǎ task-uri care sunt specificate adesea ca fiind numere dintr-un gup comun sau colectiv. Câteva variatiuni obisnuite (existǎ si altele) în figura de mai sus. Eficienta comunicǎrii Foarte frecvent, programatorul are de ales în privinta unor factori care pot afecta performanta în comunicare. Aici sunt mentionate numai câteva. Care implementare ar trebui utilizatǎ pentru un model dat? Luând modelul cu transfer de mesaje ca exemplu, o implementare MPI poate fi mai rapidǎ pe o platformǎ hardware datǎ decât pe alta. Ce tip de operatii de comunicare ar trebui folosite? Cum s-a spus mai devreme, operatiile de comunicare asincronǎ pot îmbunǎtǎti performanta generalǎ a programului. Mijlocirea retelelor unele platforme pot oferi mai mult decât o retea de comunicare. Care este cea mai bunǎ? 31

32 Overhead si complexitate Imediat mai jos este (de)scrisǎ urmǎtoarea secventǎ de program: void main(int argc, char *argv[]) { int myrank, size; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &myrank); MPI_Comm_size(MPI_COMM_WORLD, &size); Printf( Processor %d of %d: Hello World!, myrank, size); MPI_Finalize(); } Este un exemplu de overhead de comunicare paralel si de complexitate: graful real al apelurilor pentru programul paralel simplu Hello world. Cele mai multe dintre rutine sunt preluate din biblioteca de comunicare. În urma acestei scurte prezentǎri, este de retinut cǎ aceasta este numai o listǎ partialǎ de luat în considerare. Sincronizare Tipuri de sincronizare: Bariere Spun uzual cǎ toate task-urile sunt implicate. 32

33 Fiecare task executǎ lucrarea sa pânǎ ajunge la barierǎ. Aici se opreste sau se blocheazǎ. Când cel din urmǎ task ajunge la barierǎ, toate task-urile sunt sincronizate. Ce se întâmplǎ de aici încolo variazǎ de la caz la caz. Uneori trebuie executatǎ o lucrare secventialǎ. Alteori task-urile sunt automat relansate pentru a continua lucrul lor. Lacǎte/semafoare Pot actiona pe orice numǎr de task-uri Tipic, sunt utilizate pentru a serializa (a proteja) accesul la date globale sau la o sectiune din cod. La un moment dat, numai un task poate utiliza (detine) un lacǎt/semafor/flag. Primul task care accede lacǎtul îl si seteazǎ. Acel task poate atunci sǎ acceadǎ în sigurantǎ (serial) la datele protejate sau la codul protejat. Alte task-uri pot încerca a accede lacǎtul dar trebuie sǎ astepte pânǎ ce task-ul detinǎtor al lacǎtului îl descuie. Pot fi cu blocare sau fǎrǎ blocare. Operatii de comunicare sincronǎ Cuprind numai acele task-uri care executǎ o operatie de comunicare. Când un task executǎ o operatie de comunicare, este necesar un gen de coordonare cu alt(e) task(-uri) care participǎ la comunicare. De pildǎ, înainte ca un task sǎ poatǎ executa o operatie de trimitere el trebuie sǎ primeascǎ mai întâi o înstiintare de la task-ul receptor cǎ a trimite este OK. S-a discutat mai devreme în sectiunea comunicare. Dependentele datelor Definitie: Existǎ o dependentǎ între declaratiile de program atunci când ordinea executǎrii declaratiilor afecteazǎ rezultatele calculului. O dependentǎ de date rezultǎ din utilizarea multiplǎ a aceleiasi/acelorasi locatii de memorie de cǎtre task-uri diferite. Dependentele sunt importante în programarea paralel deoarece sunt unul din inhibitorii principali ai paralelismului. Exemple: Dependentǎ a datelor purtatǎ de o buclǎ 500 DO 500 J = MYSTART,MYEND A(J) = A(J 1)*2.0 CONTINUE 33

34 Valoarea lui A(J 1) trebuie calculatǎ înainte de valoarea lui A(J), prin urmare A(J) are o dependentǎ de date de A(J 1). Paralelismul este inhibat. Dacǎ task-ul 2 îl are pe A(J) si task-ul 1 îl are pe A(J 1), calculul corect al valorii lui A(J) necesitǎ: Arhitectura cu memorie distribuitǎ task-ul 2 trebuie sǎ obtinǎ valoarea lui A(J 1) de la task-ul 1 dupǎ ce task-ul 1 terminǎ calculul sǎu. Arhitectura cu memorie partajatǎ task-ul 2 trebuie sǎ citeascǎ valoarea A(J 1) dupǎ ce task-ul 1 o actualizeazǎ. Dependentǎ a datelor independentǎ de buclǎ task X = 2... Y = X**2 task X = 4... Y = X**3 Ca si în exemplul precedent, paralelismul este inhibat. Valoarea lui Y este dependentǎ de: Arhitectura cu memorie distribuitǎ dacǎ sau când valoarea lui X este comunicatǎ între task-uri Arhitectura cu memorie partajatǎ care task depune ultimul valoarea lui X. Desi toate dependentele de date sunt important a fi identificate în cursul proiectǎrii programelor paralel, dependentele purtate de bucle sunt mai importante deoarece buclele sunt posibil cele mai uzuale tinte pentru eforturile de paralelizare. Cum se trateazǎ dependentele de date: Arhitecturile cu memorie distribuitǎ se comunicǎ datele necesare la puncte de sincronizare. Arhitecturile cu memorie partajatǎ se sincronizeazǎ operatiile de citire/scriere între task-uri. Echilibrarea încǎrcǎrii Echilibrarea încǎrcǎrii se referǎ la practica de a distribui lucrul între task-uri astfel încât toate task-urile sunt mentinute ocupate tot timpul. Poate fi consideratǎ o minimizare a timpului neocupat al task-urilor. Echilibrarea încǎrcǎrii este importantǎ pentru programele paralel din ratiuni de performantǎ. De pildǎ, dacǎ toate task-urile sunt subiectul unui punct barierǎ de sincronizare, task-ul cel mai lent determinǎ performanta generalǎ. 34

35 Cum se obtine echilibrarea încǎrcǎrii? Se partitioneazǎ egal lucrul pe care fiecare task îl primeste. Pentru operatii pe matrici si pe masive de date în care fiecare task executǎ lucru similar, se distribuie multimea datelor egal între task-uri. Pentru iteratii într-o buclǎ în care lucrul executat este similar la fiecare iteratie, se distribuie egal iteratiile pe task-uri. Pentru cazul utilizǎrii unui amestec eterogen de masini cu caracteristici de performatǎ variate, trebuie sǎ se execute o analizǎ de performantǎ prin intermediul unui instrument adecvat pentru a detecta orice dezechilibru al încǎrcǎrii. Se ajusteazǎ repartizarea lucrului în consecintǎ. Utilizarea atribuirii dinamice a lucrului Unele clase de probleme produc debalansǎri ale încǎrcǎrii chiar dacǎ datele sunt distribuite egal între task-uri: Masivele rare unele task-uri au date adevǎrate pe care sǎ lucreze, altele au mai ales zerouri. Metode de grilǎ adaptive unele task-uri pot necesita rafinarea retelei lor de discretizare, pe când altele nu. Simularea problemei celor n corpuri unele particule pot migra la/de la domeniul task-ului initial la domeniul altui task; particulele detinute de un task cer mai mult calcul/lucru decât cele detinute de alte task-uri. Când doza de lucru pentru fiecare task este vǎdit variabilǎ si nu poate fi prezisǎ, poate fi de ajutor tratarea prin utilizarea unui sistem planificator task pool. Când un task isprǎveste lucrul, el se înscrie de îndatǎ într-o coadǎ pentru a obtine o lucrare nouǎ. Poate apǎrea necesar a proiecta un algoritm care sǎ detecteze si sǎ manipuleze dezechilibrele de încǎrcare pe mǎsurǎ ce apar, dinamic, în cod. Granularitate 35

36 Raportul calcul/comunicare: În calculul paralel, granularitatea este o mǎsurǎ calitativǎ a raportului dintre calcul si comunicare. Perioadele dedicate calculului sunt uzual separate de perioadele de comunicare prin evenimente de sincronizare. Paralelismul de granulatie finǎ: Între evenimentele sincronizatoare, sunt executate cantitǎti relativ scǎzute de calcul. Raportul calcul/comunicare este redus. Echilibrarea încǎrcǎrii este facilitatǎ. Implicǎ overhead mare cu comunicarea si prezintǎ putine surse/sanse de îmbunǎtǎtire a performantei. Dacǎ granularitatea este prea finǎ este posibil ca overhead-ul cerut de comunicare si de sincronizarea între task-uri sǎ depǎseascǎ timpul dedicat calculului. Paralelism de granulatie grosierǎ: Între evenimentele de comunicare/sincronizare se executǎ relativ mult calcul. Raport calcul/comunicare ridicat. Implicǎ sanse mai mari de a face performanta sǎ creascǎ. Este mai dificil a face o echilibrarea a încǎrcǎrii eficientǎ. 36

37 Care din cele douǎ granulatii este mai bunǎ? Granularitatea cea mai eficace depinde de algoritm si de conjunctura hardware în care este rulat. În multe cazuri, overhead-ul asociat cu comunicarea si sincronizarea este mare fatǎ de viteza de executie astfel cǎ este avantajos a avea o granularitate de tip grosier. Paralelismul fin granulat poate fi util în reducerea ovehead-ului datorat încǎrcǎrii debalansate. I/O Vestile rele: Operatiile I/O sunt privite în general ca inhibitori de paralelism. Sistemele I/O paralele sunt necoapte încǎ si nu sunt disponibile pentru toate platformele. Într-o conjucturǎ în care toate task-urile vǎd acelasi spatiu de fisiere, operatiile de scriere produc suprapuneri de scriere în fisiere. Operatiile de citire sunt afectate de capacitatea serverului de fisiere de a manipula concomitent cereri de scriere multiple. I/O care trebuie fǎcute prin retele (NFS Network File System, nonlocale) pot provoca strangulǎri severe. Vestile bune: Sunt disponibile/accesibile unele sisteme de fisiere paralel. De pildǎ: GPFS General Parallel File System pentru AIX (IBM) Lustre: pentru clustere Linux (Cluster File Systems, Inc.) 37

38 PVFS/PVFS2: Parallel Virtual File System pentru clustere Linux (Clemson/Argonne/Ohio Sate/altele) PanFS: Panasas ActiveScale File System pentru clustere Linux (Panasas, Inc.) HP SFS: HP Storage Works Scalable File Share. Lustre bazat pe un sistem de fisiere paralel (Global File System pentru Linux) un produs de la HP. Specificatia interfetei de programare paralel I/O pentru MPI este disponibilǎ din 1996 ca parte din MPI-2. Implementǎri de proprietar si gratuite sunt acum disponibile uzual. Unele optiuni: Accesul la sistemele paralel de fisiere trebuie acompaniat de lecturi intense deoarece domeniul este în plinǎ dezvoltare. Experientele vǎzând-si-fǎcând sunt de asemenea utile. Asta în cazul cǎ existǎ o implementare în operare. Regula #1: reducerea pe cât posibil a operatiilor I/O în general. Operatiile I/O se ataseazǎ unor portiuni speciale seriale ale jobului si apoi se utilizeazǎ comunicarea paralel pentru a distribui datele cǎtre task-uri paralele. De exemplu, task-ul 1 ar putea citi un fisier de intrare si apoi ar putea comunica datele cerute altor task-uri. Asemǎnǎtor, task-ul 1 ar putea executa operatia de scriere dupǎ colectarea datelor necesar a fi scrise de la toate celelalte task-uri. Pentru sistemele cu memorie distribuitǎ cu spatiu de fisiere partajat, se executǎ operatii I/O în spatiul de fisiere local, nepartajat. De exemplu, fiecare procesor poate avea un spatiu /tmp (temporar) pe care-l poate utiliza. Aceastǎ schemǎ este uzual mult mai eficientǎ decât executarea de I/O pe retea pe un director al unuia din task-uri. Se creazǎ nume de fisiere unice pentru fiecare I/O fisier de task. Limitele si costurile programǎrii paralel Legea lui Amdahl: afirmǎ cǎ accelerarea potentialǎ a unui program este definitǎ de fractia din cod (p) care poate fi paralelizatǎ: speedup = 1/(1 p) Dacǎ nimic din cod nu se poate paraleliza, p = 0 si accelerarea este speedup = 1 (nici un fel de accelerare). Dacǎ codul poate fi paralelizat în totalitate, p = 1 si accelerarea este infinitǎ (teoretic). Dacǎ codul poate fi paralelizat în proportie de 50%, accelerarea maximǎ este speedup = 2, ceea ce înseamnǎ cǎ acel cod poate fi executat de douǎ ori mai repede. 38

39 Dacǎ se introduce numǎrul de procesoare care executǎ fractia paralel din lucrul total, relatia de mai sus se poate scrie speedup = 1/[(p/n) + s] cu p fractia paralel, n numǎrul procesoarelor si s fractia serialǎ. Devine imediat evident cǎ existǎ limite pentru scalabilitatea paralelismului. De pildǎ, la p = 0,50, 0,90, 0,99 (ceea ce este totuna cu 50%, 90%, 99% din cod paralelizabil): n speedup la: p = 0,90 5,26 9,17 9,91 9,91 p = 0,50 1,82 1,98 1,99 1,99 p = 0,99 9,17 50,25 90,99 99,02 Cu toate acestea, anumite probleme exhibǎ performante crescute la cresterea dimensiunii problemei. De exemplu: Calculul pe grila 2D Fractia paralel 85 secunde 15 secunde 39 85% 15%

40 Dimensiunea problemei poate fi crescutǎ prin dublarea dimensiunilor grilei si înjumǎtǎtirea pasului de timp. Asta face grila sǎ aibǎ un numǎr cvadruplu de puncte si un numǎr dublu de pasi de timp. Duratele aratǎ atunci astfel: Calculul pe grila 2D Fractia paralel 680 secunde 15 secunde 97,84% 2,16% Problemele care îsi cresc procentajul de lucru paralel prin cresterea dimensiunii lor sunt mai scalabile decât problemele cu un procentaj fix de timp paralel. Complexitate În general, aplicatiile paralel sunt mult mai complexe decât aplicatiile seriale corespunzǎtoare, probabil cu un ordin de mǎrime. Nu numai cǎ sunt de executat concomitent un flux multiplu de instructiuni, dar mai sunt si datele care curg între ele. Costurile complexitǎtii sunt mǎsurate în timp al programatorului, în practicǎ toate aspectele ciclului de dezvoltare de software: proiectare, codare, depanare, reglare (tuning), întretinere. Adoptarea bunelor practici ale dezvoltǎrii de software este esentialǎ când se lucreazǎ la aplicatii paralel în special când cineva dincolo de persoana programatorului urmeazǎ sǎ lucreze cu acel software. Portabilitate Multumitǎ standardizǎrii multor interfete de programare a aplicatiilor (API Application Programming Interface), cum sunt MPI, POSIX threads, HPF si OpenMP, problema portabilitǎtii programelor paralel nu este atât de serioasǎ ca în anii trecuti. Totusi Toate problemele uzuale de portabilitate asociate programelor seriale se regǎsesc si la programele paralel. De pildǎ, dacǎ se folosesc unele ameliorǎri de producǎtor aduse la Fortran, C sau C++, portabilitatea poate deveni o problemǎ. Chiar dacǎ existǎ standarde pentru mai multe API, implementǎrile diferǎ în unele detalii, uneori pânǎ la punctul în care sunt cerute modificǎri de cod pentru a avea portabilitate. Sistemele de operare pot juca un rol cheie în problema portabilitǎtii. Caracteristic, arhitecturile hardware sunt foarte variabile si de aceea pot afecta portabilitatea. Necesitǎti de resurse 40

41 Intentia primǎ a programǎrii paralel este diminuarea timpului de executie indicat de ceasornicul din perete. Dar pentru a atinge acest obiectiv, timpul CPU necesar este mai mare. De pildǎ, un cod paralel care lucreazǎ 1 orǎ pe 8 procesoare utilizeazǎ în realitate 8 ore de timp unitate centralǎ (CPU). Necesarul de memorie poate fi mai mare pentru codurile paralel decât pentru cele seriale datoritǎ necesitǎtii de a replica datele si din cauza overhead-urilor asociate cu bibliotecile si subsistemele de suport paralel. Pentru programe paralel de duratǎ micǎ, se constatǎ de fapt o descrestere în performante comparativ cu implementǎrile similare seriale. Costurile cu overhead-ul asociate cu instalarea ambiantei paralele, cu crearea task-urilor, cu comunicarea si cu încheierea task-ului pot cuprinde o portiune semnificativǎ din timpul total de executie în cazul rulǎrilor scurte. Scalabilitate Capacitatea performantei unui program paralel de a se scala este un rezultat al unui numǎr de factori si al interactivitǎtii lor. Adǎugarea simplǎ a mai multor masini este rareori rǎspunsul la problema scalabilitǎtii. Algoritmul poate avea limite inerente de scalabilitate. La un anumit punct, adǎugarea de mai multe resurse produce scǎderi în performante. Cele mai multe solutii paralel demonstreazǎ la un anumit punct aceastǎ caracteristicǎ. Factorii hardware joacǎ un rol semnificativ în scalabilitate. Exemple: Lǎrgimea de bandǎ a bus-ului Memorie-CPU la o masinǎ SMP. Lǎrgimea de bandǎ a retelei de comunicatie. Volumul memoriei disponibile pe orice masinǎ datǎ sau pe un set de masini. Viteza ceasului procesorului. Bibliotecile si subsistemele suport pentru lucrul paralel pot limita scalabilitatea independent de aplicatie. Exemple de lucru paralel Procesarea masivelor de date Exemplul acesta este o demonstratie relativ la calculele pe un masiv 2D de elemente, cu calculul pe fiecare element al masivului independent de elementele celelalte ale acelui masiv. Programul serial calculeazǎ element cu element în ordine secventialǎ. Programul poate avea forma: do j = 1,n do i = 1,n a(i,j) = fcn(i,j) 41

42 end do end do Calculul elementelor este independent unul de altul, ceea ce duce la o stuatie deranjant de paralelǎ (embarrassingly parallel). Problema trebuie sǎ fie intensivǎ sub aspectul calculelor. O solutie posibilǎ Se implementeazǎ un model SPMD. Procesul conducǎtor initializeazǎ masivul, trimite informatii proceselorlucrǎtoare si receptioneazǎ/colecteazǎ rezultatele. Procesorul-lucrǎtor primeste informatii, executǎ partea sa de calcul si trimite rezulatele procesului conducǎtor. Folosind schema de memorare Fortran, se executǎ distributia în blocuri a masivului. Solutia în pseudocod: schimbǎrile datorate paralelismului evidentiate cu caractere diferite. find out if I am MASTER or WORKER if I am MASTER initialize the array send each WORKER info on part of array it owns send each WORKER its portion of initial array 42

43 receive from each WORKER results else if I am WORKER receive from MASTER info on part of array I own receive from MASTER my portion of initial array # calculate my portion of array do j = my first column,my last column do i = 1,n a(i,j) = fcn(i,j) end do end do send MASTER results endif O solutie diferitǎ: rezervorul de task-uri Solutia anterioarǎ a folosit echilibrarea încǎrcǎrii staticǎ: Fiecare task are o cantitate de lucru fixǎ de executat Pot rezulta timpi de inactivitate semnificativi pentru procesoarele mai rapide sau mai putin încǎrcate task-ul cel mai lent determinǎ performanta generalǎ. Echilibrarea staticǎ nu este uzual o grijǎ majorǎ dacǎ toate task-urile executǎ acelasi volum de muncǎ pe masini identice. Dacǎ apare o problemǎ de echilibru unele task-uri lucreazǎ mai repede decât altele se poate adopta schema cu rezervorul de task-uri. Schema cu rezervorul de task-uri: Sunt utilizate douǎ tipuri de procese. Procesul conducǎtor (master): Detine rezervorul de task-uri pe care procesele-lucrǎtoare le executǎ Trimite procesului lucrǎtor un task la cerere Colecteazǎ rezultate de la procesele lucrǎtoare Procesul lucrǎtor executǎ repetat urmǎtoarele: Preia task-ul de la procesul conducǎtor (master) Executǎ calculele Trimite rezultatele procesului master Procesele-lucrǎtoare nu stiu înainte de vremea rulǎrii care portie din masiv îi va reveni spre manipulare si câte task-uri vor executa. Echilibrarea încǎrcǎrii se petrece dinamic la vremea rulǎrii: task-urile mai rapide vor primi mai mult de lucru. Solutia în pseudocod cu caractere diferite pentru schimbǎrile impuse de paralelism: 43

44 find out if I am MASTER or WORKER if I am MASTER do until no more jobs send to WORKER next job receive results from WORKER end do tell WORKER no more jobs else if I am WORKER do until no more jobs receive from MASTER next job calculate array element: a(i,j) = fcn(i,j) send results to MASTER end do endif Discutie: În exemplul cu rezervor de task-uri prezentat mai sus, fiecare task calculeazǎ un element de masiv ca un job. Raportul calcul/comunicare este fin granulat. Solutiile fine granular impun overhead mai mare de comunicare pentru a reduce timpii de inactivitate ai task-urilor. O solutie mai bunǎ ar putea fi a distribui mai mult de lucru fiecǎrui job. Volumul corect de lucru depinde de problemǎ. Alt exemplu: calculul numǎrului π Valoarea numǎrului π poate fi calculatǎ în mai multe moduri. Se considerǎ aici urmǎtoarea metodǎ de aproximare a lui π: 1. Se înscrie un cerc într-un pǎtrat 2. Se genereazǎ aleator puncte în acel pǎtrat 3. Se determinǎ numǎrul de puncte dintre acestea, care sunt comune atât pǎtratului cât si cercului 4. Fie r raportul numǎrului de puncte din cerc la numǎrul de puncte din pǎtrat 5. π 4r 6. De observat cǎ generarea mai multor puncte conduce la aproximǎri mai bune Pseudocodul serial pentru aceastǎ procedurǎ: 44

45 npoints = circle_count = 0 do j = 1,npoints generate 2 random numbers between 0 and 1 xcoordinate = random1 ; ycoordinate = random2 if (xcoordinate, ycoordinate) inside circle then circle_count = circle_count + 1 end do PI = 4.0*circle_count/npoints De notat cǎ în cea mai mare parte din timp acest program executǎ bucla do. Duce la o solutie deranjant de paralelǎ, intensivǎ sub aspectul calculului, cu comunicare minimǎ, cu operatii I/O minime. Calculul lui π: Solutia paralel: Strategia paralelǎ: se sparge bucla în portiuni care pot fi executate de task-uri multiple. Pentru task-ul de aproximare a lui π: Fiecare task executǎ portiunea sa din buclǎ de un numǎr de ori. Fiecare task poate face lucrul sǎu fǎrǎ a cere informatii de la alte taskuri (nu sunt, asadar, dependente). Se utilizeazǎ modelul SPMD. Un task actioneazǎ ca master si colecteazǎ rezultatele. Solutia în pseudocod cu schimbǎrile impuse de paralelism în caractere distincte: 45

46 npoints = circle_count = 0 p = number of tasks num = npoints/p find out if I am MASTER or WORKER do j = 1,num generate 2 random numbers between 0 and 1 xcoordinate = random1 ; ycoordinate = random2 if (xcoordinate, ycoordinate) inside circle then circle_count = circle_count + 1 end do if I am MASTER receive from WORKERS their circle_counts compute PI (use MASTER and WORKER calculations) else if I am WORKER 46

47 send to MASTER circle_count endif Ecuatia simplǎ a cǎldurii: Multe probleme din calculul paralel necesitǎ comunicare între task-uri. Un numǎr de probleme comune cer comunicare cu task-urile vecine. Ecuatia cǎldurii descrie schimbarea temperaturii în timp fiind datǎ distributia initialǎ de temperaturi si conditiile periferice (la limitǎ). Pentru rezolvarea numericǎ a ecuatiei cǎldurii pe o regiune rectangularǎ (pǎtratǎ) se foloseste o schemǎ cu diferente finite. Temperatura initialǎ este zero pe periferie si mare în centru. Conditiile periferice sunt mentinute la zero. Pentru problema complet explicitǎ se foloseste un algoritm de discretizare în timp. Elementele unui masiv bidimensional reprezintǎ temperatura în punctele pǎtratului. Calculul pentru un element este dependent de valorile asociate elementelor vecine. Ux,y = Ux,y + Cx(Ux + 1,y + Ux 1,y 2Ux,y) + Cy(Ux,y Ux,y 1 2Ux,y) Un program serial aratǎ astfel: do iy = 2, ny - 1 do ix = 2, nx - 1 u2(ix, iy) = u1(ix, iy) + cx * (u1(ix+1,iy) + u1(ix-1,iy) - 2.*u1(ix,iy)) + cy * (u1(ix,iy+1) + u1(ix,iy-1) - 2.*u1(ix,iy)) end do end do 47

48 Ecuatia simplǎ a cǎldurii: solutia paralel Se implementeazǎ ca un model SPMD. Întregul masiv este partitionat si distribuit task-urilor ca submasive. Fiecare task detine astfel o parte din masivul întreg. Se determinǎ dependenta datelor. Elementele interioare, care apartin unui task sunt independente de alte task-uri. Elementele de frontierǎ sunt dependente de task-urile vecine, de datele lor si de aceea necesitǎ comunicare. 48

49 Procesul master trimite informatia initialǎ task-urilor lucrǎtoare, verificǎ convergenta si colecteazǎ rezultatele. Procesele-lucrǎtoare calculeazǎ solutia, comunicǎ atât cât este necesar cu procesele vecine. Solutia în pseudocod, cu scriere specialǎ pentru schimbǎrile dictate de paralelism: find out if I am MASTER or WORKER if I am MASTER initialize array send each WORKER starting info and subarray do until all WORKERS converge gather from all WORKERS convergence data broadcast to all WORKERS convergence signal end do receive results from each WORKER else if I am WORKER receive from MASTER starting info and subarray do until solution converged update time send neighbors my border info receive from neighbors their border info update my portion of solution array determine if my solution has converged send MASTER convergence data receive from MASTER convergence signal end do send MASTER results endif Ecuatia simplǎ a cǎldurii: a doua solutie paralel cu suprapunerea comunicǎrii si calculului: 49

50 Solutia precedentǎ a admis cǎ task-urile lucrǎtoare folosesc comunicatii cu blocare. Comunicarea cu blocare face ca înainte de a continua cu instructiunea urmǎtoare programatǎ task-ul sǎ astepte ca procesul de comunicare sǎ se încheie. În solutia precedentǎ, task-urile vecine comunicǎ datele de frontierǎ, apoi fiecare proces actualizeazǎ portiunea lui din masiv. Timpul de calcul poate fi adesea redus prin utilizarea comunicǎrii fǎrǎ blocare. Comunicarea fǎrǎ blocare permite ca lucrul sǎ fie continuat/executat în timp ce comunicarea este în derulare. Fiecare task ar putea actualiza interiorul pǎrtii sale de masiv-solutie, în timp ce se petrece comunicarea datelor de la frontierǎ si ar putea actualiza frontiera sa dupǎ ce comunicarea este încheiatǎ. Este dat în continuare pseudocodul solutiei paralel numǎrul 2, cu scrierea cu caractere distincte a pǎrtii de comunicare fǎrǎ blocare: find out if I am MASTER or WORKER if I am MASTER initialize array send each WORKER starting info and subarray do until all WORKERS converge gather from all WORKERS convergence data broadcast to all WORKERS convergence signal end do receive results from each WORKER else if I am WORKER receive from MASTER starting info and subarray do until solution converged update time non-blocking send neighbors my border info non-blocking receive neighbors border info update interior of my portion of solution array wait for non-blocking communication complete update border of my portion of solution array determine if my solution has converged send MASTER convergence data receive from MASTER convergence signal end do 50

51 send MASTER results endif Un alt exemplu: ecuatia undelor 1D: În acest exemplu, se calculeazǎ amplitudinea de-a lungul unei coarde vibrante uniforme dupǎ trecerea unui timp anumit. Calculul implicǎ: Amplitudinea pe directia axei y Un indice i de pozitie pe axa x Puncte-nod impuse de-a lungul coardei Actualizarea amplitudinii la pasi discreti de timp. Ecuatia de rezolvat este ecuatia undelor unidimensionalǎ: A(i,t+1) = (2.0 * A(i,t)) - A(i,t-1) + (c * (A(i-1,t) - (2.0 * A(i,t)) + A(i+1,t))) cu c o constantǎ. De observat cǎ amplitudinea depinde de pasii de timp anteriori (t, t 1) si de punctele vecine (i 1, i + 1). Dependenta datelor înseamnǎ cǎ orice solutie paralelǎ necesitǎ comunicare. Solutia paralel: Se implementeazǎ ca un model SPMD. Masivul depozitar al tuturor amplitudinilor este partitionat si distribuit taskurilor ca submasive. Fiecare task obtine o portiune din masivul total. Echilibrarea încǎrcǎrii: toate punctele reclamǎ lucru egal astfel cǎ punctele trebuie repartizate egal. O descompunere în blocuri ar avea lucrul partitionat într-un numǎr de task-uri ca fragmente care permit fiecǎrui task sǎ detinǎ cât mai multe date contigue. 51

52 Comunicarea este necesarǎ si are loc numai în punctele de frontierǎ. Cu cât este mai mare dimensiunea blocurilor cu atât este mai redusǎ comunicarea. Solutia în pseudocod: find out number of tasks and task identities #Identify left and right neighbors left_neighbor = mytaskid - 1 right_neighbor = mytaskid +1 if mytaskid = first then left_neigbor = last if mytaskid = last then right_neighbor = first find out if I am MASTER or WORKER if I am MASTER initialize array send each WORKER starting info and subarray else if I am WORKER receive starting info and subarray from MASTER endif #Update values for each point along string #In this example the master participates in calculations do t = 1, nsteps send left endpoint to left neighbor receive left endpoint from right neighbor send right endpoint to right neighbor receive right endpoint from left neighbor #Update points along line do i = 1, npoints newval(i) = (2.0 * values(i)) - oldval(i) + (sqtau * (values(i-1) - (2.0 * values(i)) + values(i+1))) 52

53 end do end do #Collect results and write to file if I am MASTER receive results from each WORKER write results to file else if I am WORKER send results to MASTER endif 53

54 OpenMP Ce este OpenMP? OpenMP este o interfatǎ de programare a aplicatiilor (API Application Program Interface) care poate fi utilizatǎ în paralelismul multifir cu memorie partajatǎ (în indiviziune). Contine trei componente API primare: directive de compilare, rutine de bibliotecǎ la executie, variabile de mediu (environment). Portabilitate: Aceastǎ API este realizatǎ în C/C++ si Fortran. S-a implementat pe platforme variate, inclusiv pe cele mai multe platforme Unix si Windows NT. Standardizare: Este definitǎ si aprobatǎ în comun de un grup de producǎtori majori de hardware si software. Este de asteptat a deveni în viitor un standard ANSI (American National Standards Institute). Ce înseamnǎ OpenMP? Înseamnǎ Open specifications for Multi Processing prin lucrǎri în colaborare care întrunesc interese din industria de software si de hardware, guvernamentale si academice. Ce nu este OpenMP? Interfata OpenMP nu este prin ea însǎsi destinatǎ sistemelor paralel cu memorie distribuitǎ. Nu este implementatǎ în mod necesar identic de cǎtre toti producǎtorii. Nu este garantatǎ cǎ ar asigura utilizarea cea mai eficientǎ a memoriei partajate (nu existǎ pentru moment constructe legate de localismul datelor). Istoric Istoria mai veche În anii 90 timpurii, producǎtorii de masini cu memorie partajatǎ furnizau extensii de programare Fortran similare, bazate pe directive: Utilizatorul adǎuga programelor Fortran secventiale directive care specificau care bucle trebuia sǎ fie paralelizate. Compilatorul era responsabil de paralelizarea automatǎ a buclelor de acest gen pe procesoarele SMP (Symmetric MultiProcessing). Implementǎrile erau toate similare functional dar erau, ca de obicei, diferite în unele detalii. 54

55 Prima încercare de a realiza un standard a fost proiectul pentru ANSI X3H5 din Nu a fost adoptat niciodatǎ, în principal din cauza interesului în scǎdere pe mǎsurǎ ce masinile cu memorie distribuitǎ au devenit din ce în ce mai populare. Istoria recentǎ Specificatia de standard OpenMP a fost începutǎ în primǎvara anului 1997, preluând ceea ce a rǎmas din încercarea ANSI X3H5, odatǎ ce arhitecturile mai noi de masini cu memorie partajatǎ au devenit demne de luat în seamǎ. Pertenerii implicati în specificarea standardului OpenMP sunt: OpenMP Architecture Review Board (deschis pentru membri noi) Compaq / Digital Hewlett-Packard Company Intel Corporation International Business Machines (IBM) Kuck & Associates, Inc. (KAI) Silicon Graphics, Inc. Sun Microsystems, Inc. U.S. Department of Energy ASCI program Producǎtori de software cu rol de avizare: Absoft Corporation Edinburgh Portable Compilers GENIAS Software GmBH Myrias Computer Technologies, Inc. The Portland Group, Inc. (PGI) Societǎti de dezvoltare de aplicatii cu rol de avizare: ADINA R&D, Inc. ANSYS, Inc. Dash Associates Fluent, Inc. ILOG CPLEX Division Livermore Software Technology Corporation (LSTC) MECALOG SARL Oxford Molecular Group PLC The Numerical Algorithms Group Ltd.(NAG) Istoria lansǎrilor Octombrie 1997: Fortran versiunea 1.0 Sfârsitul anului 1998: C/C++ versiunea 1.0 Iunie 2000: Fortran versiunea 2.0 Aprilie 2002: C/C++ versiunea

56 Pentru detalii se recomandǎ vizitarea site-ului Scopurile urmǎrite prin OpenMP Standardizare: A furniza un standard pentru varietatea de arhitecturi/platforme cu memorie partajatǎ. Sprijin si mijloc: Stabilirea unui set simplu si limitat de directive pentru programarea masinilor cu memorie partajatǎ. O dozǎ însemnatǎ de paralelism se poate implementa utilizând doar 3-4 directive. Usurinta utilizǎrii: A oferi posibilitatea de a paraleliza incremental, treptat un program secvential, spre deosebire de bibliotecile cu transfer de mesaje care reclamǎ o tratare de genul totul sau nimic. Portabilitate: Permite Fortran-ul (77, 90 si 95), C si C++. For public pentru API si calitatea de membru. Modelul de programare OpenMP Paralelism pe bazǎ de fire: Un proces cu memorie partajatǎ poate consta în fire multiple. OpenMP se bazeazǎ pe existenta firelor multiple în paradigma programǎrii cu partajarea memoriei. Peralelism explicit: OpenMP este un model de programare explicit (nu automat), care oferǎ programatorului deplinul control asupra paralelizǎrii. Modelul ramificatie-jonctiune: OpenMP uzeazǎ de un model al executiei paralel alcǎtuit din ramificatii si jonctiuni (v.figura). Toate programele OpenMP încep ca un proces unic, firul master. Firul master se executǎ secvential pânǎ când ajunge la primul construct numit zonǎ/regiune paralel. Ramificatie: firul master creazǎ un mǎnunchi de fire paralele. Declaratiile din program care alcǎtuiesc o zonǎ paralel sunt executate apoi paralel de firele variate din mǎnunchi. 56

57 Jonctiune: când firele din mǎnunchi terminǎ de executat declaratiile din constructul zonǎ/regiune paralel, ele se sincronizeazǎ si se încheie lǎsând din nou numai firul master. Bazat pe directive de compilare: Virtual, tot paralelismul OpenMP este specificat prin directive de compilare care sunt încorporate în codul sursǎ Fortran sau C/C++. Suportul pentru paralelismul stratificat: Aceastǎ interfatǎ API asigurǎ plasarea unui construct paralel în interiorul altor constructe paralel. Implementǎrile existente pot sǎ includǎ sau nu aceastǎ particularitate. Fire dinamice: Aceastǎ interfatǎ API asigurǎ modificarea dinamicǎ a numǎrului de fire care pot fi utilizate pentru executarea unor zone paralel diferite. Implementǎrile existente pot sǎ includǎ sau nu aceastǎ particularitate. Exemple de structurǎ a codurilor OpenMP. Fortran structura generalǎ a codului: PROGRAM HELLO INTEGER VAR1, VAR2, VAR3 Cod secvential... Începutul sectiunii paralel. Ramificarea mǎnunchiului de fire. Specificarea domeniului variabilelor!$omp PARALLEL PRIVATE(VAR1, VAR2) SHARED(VAR3) Sectiunea paralel executatǎ de toate firele... Toate firele se reunesc în firul master!$omp END PARALLEL Se reia codul secvential... END C / C++ structura generalǎ a codului: #include <omp.h> main() { int var1, var2, var3; 57

58 Codul secvential... Începutul sectiunii paralel. Ramificarea mǎnunchiului de fire. Specificarea domeniului variabilelor #pragma omp parallel private(var1, var2) shared(var3) { Sectiunea paralel executatǎ de toate firele... Toate firele se reunesc în firul master } Se reia codul secvential... } Directive OpenMP Formatul directivelor Fortran: Prefix-gardǎ nume de directivǎ [clauze ]. Toate directivele OpenMP în Fortran trebuie sǎ înceapǎ cu un prefix-gardǎ. Prefixele acceptate depind de tipul sursei Fortran. Prefixe posibile:!$omp sau C#OMP sau *$OMP. O directivǎ OpenMP validǎ trebuie sǎ aparǎ dupǎ un prefix-gardǎ si înaintea oricǎrei clauze. Clauzele sunt optionale, pot fi în orice ordine si pot fi repetate în functie de necesitǎti (dacǎ nu sunt cumva restrictionate). Exemplu:!$OMP PARALLEL DEFAULT(SHARED) PRIVATE(BETA, PI) Pentru sursele în formǎ fixǎ sunt acceptate ca prefix-gardǎ!$omp, C#OMP sau *$OMP, care trebuie sǎ înceapǎ din coloana 1. Toate regulile de formǎ fixǎ ale Fortran-ului pentru lungimea liniei, spatii, coloane de continuare si comentarii se aplicǎ pentru întrega linie de directivǎ. Liniile cu directive initiale trebuie sǎ aibǎ un spatiu/zero în coloana 6. Liniile de continuare trebuie sǎ aibǎ un caracter diferit de spatiu/zero în coloana 6. Pentru sursele în formǎ liberǎ, singura gardǎ acceptatǎ este!$omp. Poate apǎrea în orice coloanǎ dar trebuie sǎ fie precedatǎ de un spatiu (exclusiv). Toate regulile pentru forma liberǎ Fortran, pentru lungimea liniei, spatiu, coloane de continuare si comentarii se aplicǎ pentru întreaga linie de directivǎ. Liniile de directivǎ initiale trebuie sǎ aibǎ un spatiu dupǎ prefixul-gardǎ. 58

59 Liniile de continuare trebuie sǎ aibǎ un caracter & ca ultim caracter al liniei diferit de blank. Linia urmǎtoare trebuie sǎ înceapǎ cu un prefix-gardǎ si apoi continuarea directivelor. Reguli generale: Comentariile nu pot apǎrea pe aceeasi linie cu o directivǎ. Compilatoarele Fortran care sunt abilitate OpenMP includ în general o optiune pentru liniile de comandǎ care spun compilatorului sǎ activeze si sǎ interpreteze toate directivele OpenMP. Mai multe directive Fortran OpenMP apar în perechi si au forma!$omp directivǎ /bloc de cod structurat/!$omp end directivǎ Formatul directivelor C/C++: #pragma omp nume de directivǎ [clauze ] linie-nouǎ. Prefixul #pragma omp este obligatoriu pentru orice directivǎ OpenMP în C/C++. O directivǎ OpenMP validǎ trebuie sǎ aparǎ dupǎ pragma si înainte de orice clauzǎ. Clauzele sunt optionale, pot fi în orice ordine, pot fi repetate (dacǎ nu sunt restrictionǎri). Caracterul linie-nouǎ este necesar pentru a trece la blocul structurat care este inclus în acea directivǎ. Exemplu: #pragma omp parallel default(shared) private(beta,pi) Reguli generale: Directivele respectǎ conventiile din standardele C/C++ pentru directivele de compilare. Sensibilǎ la upper/lower case. Pentru o directivǎ, numai un nume de directivǎ poate fi specificat (ceea ce se practicǎ si la Fortran). Fiecare directivǎ se aplicǎ la cel mult o declaratie urmǎtoare, care poate fi un bloc structurat. Liniile-directivǎ lungi pot fi continuate pe linii urmǎtoare prin combinarea caracterelor newline (linie-nouǎ) cu un caracter \ la finalul liniei-directivǎ. Domeniul directivelor 59

60 Domeniu static (lexical): Codul inclus textual între începutul si finalul unui bloc structurat care urmeazǎ directiva. Domeniul static al unei directive nu acoperǎ rutine multiple sau fisiere de cod. Directive orfane: Despre o directivǎ OpenMP care apare independent de o altǎ directivǎ care o include se spune cǎ este o directivǎ orfanǎ. Ea existǎ în afara domeniului static (lexical) al altei directive. Acoperǎ rutine si posibile fisiere de cod. Domeniu dinamic: Domeniul dinamic al unei directive include atât domeniul ei static (lexical) cât si domeniile orfanelor ei. Exemplu: PROGRAM TEST...!$OMP PARALLEL...!$OMP DO DO I= CALL SUB1... ENDDO... CALL SUB2...!$OMP END PARALLEL SUBROUTINE SUB1...!$OMP CRITICAL...!$OMP END CRITICAL END SUBROUTINE SUB2...!$OMP SECTIONS...!$OMP END SECTIONS... END DOMENIUL STATIC DIRECTIVE ORFANE Directiva DO apare într-o regiune Directivele CRITICAL si paralel care o include SECTIONS apar înafara unei regiuni paralel care sǎ o includǎ DOMENIUL DINAMIC De ce aste importantǎ aceastǎ precizare? OpenMP specificǎ un numǎr de reguli privind domeniul peste care directivele se pot asocia (lega) si se pot include una în alta. Dacǎ acele reguli ale OpenMP sunt ignorate, pot rezulta programe incorecte sau neinteligibile. Regulile sunt prezentate într-o sectiune urmǎtoare. 60

61 Constructul de regiuni PARALLEL. Scopul acestuia: o regiune paralel este un bloc de cod care va fi executat de mai multe fire. Este constructul paralel OpenMP fundamental. Formatul în Fortran:!$OMP PARALLEL [clause...] IF (scalar_logical_expression) PRIVATE (lista) SHARED (lista) DEFAULT (PRIVATE SHARED NONE) FIRSTPRIVATE (lista) REDUCTION (operator: lista) COPYIN (lista) block!$omp END PARALLEL Formatul în C/C++: #pragma omp parallel [clause...] newline if (scalar_expression) private (lista) shared (lista) default (shared none) firstprivate (lista) reduction (operator: lista) copyin (lista) structured_block Notǎ: Când un fir ajunge la directiva PARALLEL, el creeazǎ un mǎnunchi de fire si devine firul master al acelui fascicul. Master-ul este un membru al acelui fascicul si are numǎrul 0 în fascicul. La începutul acelei regiuni paralel, codul este copiat si este executat apoi de toate firele fasciculului. Existǎ la finalul unei regiuni paralel o barierǎ implicitǎ, numai firul master continuǎ executia dincolo de acest punct. Câte fire? Numǎrul de fire dintr-o regiune paralel este determinat de factorii urmǎtori, în ordinea prezentatǎ: Se utilizeazǎ functia de bibliotecǎ omp_set_num_threads(). Se seteazǎ variabila de mediu OMP_NUM_THREADS. Implementarea default 61

62 Firele sunt numerotate de la 0 (firul master) la N 1. Fire dinamice: Prin default, un program cu regiuni paralel multiple utilizeazǎ acelasi numǎr de fire pentru a executa fiecare dintre regiuni. Aceastǎ comportare poate fi modificatǎ pentru a permite la vremea executiei modificarea dinamicǎ a firelor create pentru o anumitǎ sectiune paralel. Cele douǎ metode disponibile pentru a permite fire dinamice sunt: Utilizarea functiei de bibliotecǎ omp_set_dynamic() Setarea variabilei de mediu OMP_DYNAMIC. Regiuni paralel una-în-alta: O regiune paralel în alta rezultǎ prin crearea unui fascicul nou, constând într-un fir, prin default. Implementǎrile pot permite mai mult de un fir în fasciculul cuprins în alt fascicul. Clauze: Dacǎ apare clauza IF, ea trebuie sǎ producǎ.true. (în Fortran) sau o valoare nenulǎ (în C/C++) pentru a fi creat un fascicul de fire. Altminteri, regiunea este executatǎ de firul master în mod secvential. Celelalte clauze sunt descrise ceva mai încolo. Restrictii: O regiune paralel trebuie sǎ fie un bloc structurat care nu acoperǎ rutine multiple sau fisiere de cod multiple. În Fortran, instructiunile I/O nesincrone prin care mai multe fire se referǎ la aceeasi unitate au o comportare nespecific(at)ǎ. Este ilegalǎ ramificarea din sau într-o regiune paralel. Nu este permisǎ decât o singurǎ clauzǎ IF. Exemplu de regiune paralel Program simplu Hello World. Fiecare fir executǎ întregul cod inclus în regiunea paralel. Rutinele de bibliotecǎ OpenMP sunt utilizate pentru a obtine identificatori de fire si numǎrul total de fire. În Fortran: PROGRAM HELLO INTEGER NTHREADS, TID, OMP_GET_NUM_THREADS, + OMP_GET_THREAD_NUM C Fork a team of threads giving them their own copies of variables!$omp PARALLEL PRIVATE(TID) C Obtain and print thread id TID = OMP_GET_THREAD_NUM() PRINT *, 'Hello World from thread = ', TID C Only master thread does this IF (TID.EQ. 0) THEN NTHREADS = OMP_GET_NUM_THREADS() 62

63 PRINT *, 'Number of threads = ', NTHREADS END IF C All threads join master thread and disband!$omp END PARALLEL END În C/C++: main () { int nthreads, tid; /* Fork a team of threads giving them their own copies of variables */ #pragma omp parallel private(tid) { /* Obtain and print thread id */ tid = omp_get_thread_num(); printf("hello World from thread = %d\n", tid); /* Only master thread does this */ if (tid == 0) { nthreads = omp_get_num_threads(); printf("number of threads = %d\n", nthreads); } } /* All threads join master thread and terminate */ } Constructe Work-Sharing (lucru partajat) Un construct work-sharing împarte executia din regiunea de cod care îl include, între membrii fasciculului care îl întâlnesc. Constructele work-sharing nu lanseazǎ fire noi. Nu existǎ barierǎ implicitǎ la intrarea într-un construct work-sharing, totusi existǎ o barierǎ implicitǎ la sfârsitul unui construct work-sharing. Tipuri de constructe work-sharing DO/for partajeazǎ SECTIONS sparge SINGLE iteratiile unei bucle din lucrul în sectiuni serializeazǎ o sectiune fascicul. Reprezintǎ un separate, discrete. de cod. 63

64 tip de "paralelism pe Fiecare sectiune este date". executatǎ de un fir. Poate fi utilizat pentru implementarea unui tip de "paralelism functional". Restrictii: Un construct work-sharing trebuie sǎ fie inclus dinamic într-o regiune paralel pentru ca directivele sǎ fie excutate în paralel. Constructele work-sharing trebuie sǎ fie întâlnite de toate firele membre ale unui fascicul sau de niciunul. Constructele work-sharing trebuie sǎ fie întâlnite în aceeasi oridine de toate firele membre ale unui fascicul. Constructe work-sharing Directiva DO/for Scopul: Directiva DO/for specificǎ faptul cǎ iteratiile buclei imediat urmǎtoare trebuie sǎ fie executate de fascicul în paralel. Asta presupune cǎ o regiune parlel a fost deja initiatǎ, altminteri ea se executǎ secvential pe un singur procesor. Formatul în Fortran:!$OMP DO [clause...] SCHEDULE (type [,chunk]) ORDERED PRIVATE (list) FIRSTPRIVATE (list) LASTPRIVATE (list) SHARED (list) REDUCTION (operator intrinsic : list) 64

65 do_loop!$omp END DO [ NOWAIT ] Formatul în C/C++: #pragma omp for [clause...] newline schedule (type [,chunk]) ordered private (list) firstprivate (list) lastprivate (list) shared (list) reduction (operator: list) nowait for_loop Clauze: Clauza SCHEDULE: descrie cum sunt partajate iteratiile buclei între firele fasciculului. Atât pantru Fortran cât si pentru C/C++: STATIC: Iteratiile buclei sunt împǎrtite în bucǎti de dimensiunea chunk si apoi atribuite static firelor. Dacǎ chunk nu este precizatǎ, iteratiile sunt împǎrtite (dacǎ este posibil) egal si contiguu între fire. DYNAMIC: Iteratiile buclei sunt divizate în bucǎti de dimensiunea chunk si distribuite dinamic între fire; când un fir încheie o bucatǎ, i se atribuie dinamic alta. Dimensiunea bucǎtilor prin default este 1. GUIDED: Dimensiunea fragmentului este redusǎ exponential cu fiecare bucatǎ distribuitǎ a spatiului de iterare. Dimensiunea fragmentului specificǎ numǎrul minim de iteratii de distribuit de fiecare datǎ. Dimensiunea bucǎtilor prin default este 1. RUNTIME: Decizia de repartizare este amânatǎ pânǎ la timpul executiei de variabila de mediu OPM_SCHEDULE. Este ilegal a specifica dimensiunea fragmentului pentru aceastǎ clauzǎ. Repartizarea prin default este dependentǎ de implementare. Implementarea poate fi totodatǎ întrucâtva variabilǎ în modul în care repartizǎrile variate sunt implementate. Clauza ORDERED: Trebuie sǎ fie prezentǎ când în directiva DO/for (vezi mai sus) sunt incluse directive ORDERED. Clauza NO WAIT (Fortran)/nowait (C/C++): Dacǎ este specificatǎ, atunci firele nu se sincronizeazǎ la finele buclei paralel. Firele trec direct la declaratia urmǎtoare de dupǎ buclǎ. Pentru Fortran, directiva END DO este optionalǎ cu default-ul NO WAIT. 65

66 Alte clauze sunt descrise mai în detaliu în continuare. Restrictii: Bucla DO nu poate fi o buclǎ DO WHILE sau o buclǎ fǎrǎ control. Totodatǎ, variabila de iteratie a buclei trebuie sǎ fie un întreg si parametrii de control ai buclei trebuie sǎ fie aceiasi pentru toate firele. Corectitudinea programului trebuie sǎ nu depindǎ de care fir executǎ o iteratie particularǎ. Este ilegal a ramifica controlul înafara unei bucle asociate cu directiva DO/for. Dimensiunea fragmetului trebuie sǎ fie specificatǎ ca o expresie întreagǎ invariantǎ, ca si când nu existǎ vreo sincronizare în timpul evaluǎrii ei de fire diferite. Directiva for din C/C++ necesitǎ ca bucla for sǎ aibǎ forma canonicǎ. Clauzele ORDERED si SCHEDULE pot apǎrea fiecare numai o datǎ. Exemplu: Directiva DO/for, program simplu de adunare de vectori. Variabila I va fi private pentru fiecare fir; fiecare fir va avea propriul sǎu exemplar. Iteratiile buclei vor fi distribuite dinamic în fragmente de dimensiunea CHUNK. Firele nu se vor sincroniza la încheierea lucrului lor (NOWAIT). FORTRAN: PROGRAM VEC_ADD_DO INTEGER N, CHUNKSIZE, CHUNK, I PARAMETER (N=1000) PARAMETER (CHUNKSIZE=100) REAL A(N), B(N), C(N)! Some initializations DO I = 1, N A(I) = I * 1.0 B(I) = A(I) ENDDO CHUNK = CHUNKSIZE!$OMP PARALLEL SHARED(A,B,C,CHUNK) PRIVATE(I)!$OMP DO SCHEDULE(DYNAMIC,CHUNK) DO I = 1, N C(I) = A(I) + B(I) ENDDO!$OMP END DO NOWAIT!$OMP END PARALLEL 66

67 END C/C++: #include <omp.h> #define CHUNKSIZE 100 #define N 1000 main () { int i, chunk; float a[n], b[n], c[n]; /* Some initializations */ for (i=0; i < N; i++) a[i] = b[i] = i * 1.0; chunk = CHUNKSIZE; #pragma omp parallel shared(a,b,c,chunk) private(i) { #pragma omp for schedule(dynamic,chunk) nowait for (i=0; i < N; i++) c[i] = a[i] + b[i]; } /* end of parallel section */ } Constructe de divizare a lucrului Directiva SECTIONS Scop: Directiva SECTIONS este un construct de divizare a lucrului neiterativ. Ea specificǎ faptul cǎ sectiunea/sectiunile de cod incluse sunt de divizat între firele din fascicul. Directive SECTION independente pot fi asezate una într-alta în directiva SECTIONS. Fiecare SECTION este executatǎ o datǎ de un fir din fascicul. Sectiuni diferite pot fi executate de fire diferite. Este posibil ca un fir sǎ execute mai mult de o sectiune dacǎ firul este suficient de rapid si implementarea permite asa ceva. Format în Fortran:!$OMP SECTIONS [clause...] 67

68 PRIVATE (list) FIRSTPRIVATE (list) LASTPRIVATE (list) REDUCTION (operator intrinsic : list)!$omp SECTION block!$omp SECTION block!$omp END SECTIONS [ NOWAIT ] Format în C/C++: #pragma omp sections [clause...] newline private (list) firstprivate (list) lastprivate (list) reduction (operator: list) nowait { #pragma omp section newline structured_block #pragma omp section newline structured_block } Clauze: La finalul unei directive SECTIONS existǎ o barierǎ implicitǎ cu exceptia cazului în care se utilizeazǎ o clauzǎ nowait/nowait. Clauzele sunt descrise în detaliu mai departe. Întrebǎri: Ce se întâmplǎ dacǎ numǎrul de fire si numǎrul de SECTION sunt diferite? Mai multe fire decât SECTION? Mai putine fire decât SECTION? Dacǎ sunt mai multe fire decât sectiuni, unele fire nu vor executa sectiuni. Dacǎ sectiunile sunt mai multe decât firele, implementarea trebuie sǎ defineascǎ modul cum sectiunile rǎmase vor fi executate. Cum se asociazǎ firele cu sectiunile? Din nou implementarea trebuie sǎ decidǎ care sectiune va fi executatǎ de care fir si aceastǎ repartizare poate varia de la executie la executie. 68

69 Restricitii: Este ilegal a ramifica în sau din blocurile sectiunii. Directivele SECTION trebuie sǎ aparǎ în extinderea lexicalǎ a unei directive SECTIONS care le include. Exemplu pentru directiva SECTIONS: program de adunare simplǎ a vectorilor similar exemplului utilizat mai devreme pentru directiva DO/for. Primele n/2 iteratii ale buclei DO sunt distribuite primului fir, restul se distribuie firului al doilea. Când un fir terminǎ blocul lui de iteratii, trece la executarea a ceea ce urmeazǎ conform codului (NOWAIT). Pentru Fortran: PROGRAM VEC_ADD_SECTIONS INTEGER N, I PARAMETER (N=1000) REAL A(N), B(N), C(N)! Some initializations DO I = 1, N A(I) = I * 1.0 B(I) = A(I) ENDDO!$OMP PARALLEL SHARED(A,B,C), PRIVATE(I)!$OMP SECTIONS!$OMP SECTION DO I = 1, N/2 C(I) = A(I) + B(I) ENDDO!$OMP SECTION DO I = 1+N/2, N C(I) = A(I) + B(I) ENDDO!$OMP END SECTIONS NOWAIT!$OMP END PARALLEL END Pentru C/C++: #include <omp.h> #define N

70 main () { int i; float a[n], b[n], c[n]; /* Some initializations */ for (i=0; i < N; i++) a[i] = b[i] = i * 1.0; #pragma omp parallel shared(a,b,c) private(i) { #pragma omp sections nowait { #pragma omp section for (i=0; i < N/2; i++) c[i] = a[i] + b[i]; #pragma omp section for (i=n/2; i < N; i++) c[i] = a[i] + b[i]; } } /* end of sections */ /* end of parallel section */ } Directiva SINGLE Scop: Directiva SINGLE specificǎ faptul cǎ secventa de cod inclusǎ trebuie executatǎ numai de un fir din fascicul. Poate fi utilǎ în tratarea sectiunilor codului care nu sunt sigure pe orice fir (cum sunt operatiile I/O). Formatul în Fortran:!$OMP SINGLE [clause...] PRIVATE (list) FIRSTPRIVATE (list) block!$omp END SINGLE [ NOWAIT ] 70

71 Formatul în C/C++: #pragma omp single [clause...] newline private (list) firstprivate (list) nowait structured_block Clauze: Firele din fascicul care nu executǎ directiva SINGLE asteaptǎ la finalul blocului de cod inclus, cu exceptia cazului în care este specificatǎ o clauzǎ nowait (C/C++) sai NOWAIT (Fortran). Clauzele sunt descrise ceva mai departe. Restrictii: Este inacceptabil a ramifica în sau înafara unui bloc SINGLE. Constructe de divizare a lucrului paralel combinate Directiva PARALLEL DO/parallel for Iteratiile buclei DO/for se distribuie în blocuri de dimensiune egalǎ fiecǎrui fir din fascicul (SCHEDULE STATIC). Exemplu pentru Fortran: PROGRAM VECTOR_ADD INTEGER N, I, CHUNKSIZE, CHUNK PARAMETER (N=1000) PARAMETER (CHUNKSIZE=100) REAL A(N), B(N), C(N)! Some initializations DO I = 1, N A(I) = I * 1.0 B(I) = A(I) ENDDO CHUNK = CHUNKSIZE!$OMP PARALLEL DO!$OMP& SHARED(A,B,C,CHUNK) PRIVATE(I)!$OMP& SCHEDULE(STATIC,CHUNK) DO I = 1, N C(I) = A(I) + B(I) ENDDO 71

72 !$OMP END PARALLEL DO END Exemplu pentru C/C++: #include <omp.h> #define N 1000 #define CHUNKSIZE 100 main () { int i, chunk; float a[n], b[n], c[n]; /* Some initializations */ for (i=0; i < N; i++) a[i] = b[i] = i * 1.0; chunk = CHUNKSIZE; #pragma omp parallel for \ shared(a,b,c,chunk) private(i) \ schedule(static,chunk) for (i=0; i < n; i++) c[i] = a[i] + b[i]; } Directiva PARALLEL SECTIONS Scop: Directiva PARALLEL SECTIONS specificǎ o regiune paralel care contine o directivǎ SECTIONS unicǎ. Directiva SECTIONS unicǎ trebuie sǎ urmeze imediat, ca declaratie imediat urmǎtoare. Format în Fortran:!$OMP PARALLEL SECTIONS [clause...] DEFAULT (PRIVATE SHARED NONE) SHARED (list) PRIVATE (list) FIRSTPRIVATE (list) LASTPRIVATE (list) REDUCTION (operator intrinsic : list) COPYIN (list) ORDERED structured_block 72

73 !$OMP END PARALLEL SECTIONS Format în C/C++: #pragma omp parallel sections [clause...] newline default (shared none) shared (list) private (list) firstprivate (list) lastprivate (list) reduction (operator: list) copyin (list) ordered structured_block Clauze: Clauzele acceptate pot fi oricare din cele acceptate de directivele PARALLEL si SECTIONS. Clauzele nediscutate încǎ sunt descrise în detaliu mai departe, în sectiunea Clauze cu atribute de domeniu pentru date. Constructe de sincronizare Se considerǎ un exemplu simplu în care douǎ fire pe douǎ procesoare diferite încearcǎ ambele sǎ incrementeze o variabilǎ x în acelasi timp (se presupune cǎ x este la început 0): THREAD 1: increment(x) { x = x + 1; } THREAD 1: 10 LOAD A, (x address) 20 ADD A, 1 30 STORE A, (x address) THREAD 2: increment(x) { x = x + 1; } THREAD 2: 10 LOAD A, (x address) 20 ADD A, 1 30 STORE A, (x address) O secventǎ la executie posibilǎ este: Firul 1 încarcǎ valoarea lui x în registrul A. Firul 2 încarcǎ valoarea lui x în registrul A. Firul 1 adunǎ 1 la registrul A. Firul 2 adunǎ 1 la registrul A. Firul 1 depune registrul A în locatia x. Firul 2 depune registrul A în locatia x. 73

74 Valoarea rezultatǎ pentru x va fi 1, nu 2 cum ar trebui sǎ fie. Pentru a evita situatiile de acest gen, incrementarea lui x trebuie sǎ fie sincronizatǎ între cele douǎ fire pentru a ne asigura de rezultatul corect. OpenMP asigurǎ o varietate de constructe de sincronizare care controleazǎ cum se deruleazǎ executia fiecǎrui fir în relatie cu alte fire ale fasciculului. Directiva MASTER Scop: Directiva MASTER specificǎ o regiune care trebuie executatǎ numai de firul master al fasciculului. Toate celelalte fire din fascicul sar aceastǎ sectiune a codului. Nu existǎ vreo barierǎ implicitǎ asociatǎ cu aceastǎ directivǎ. Formatul Fortran:!$OMP MASTER block!$omp END MASTER Formatul C/C++: #pragma omp master newline structured_block Restrictii: Este interzis a ramifica în sau înafara blocului MASTER. Directiva CRITICAL Scop: Directiva CRITICAL specificǎ o regiune de cod care trebuie executatǎ succesiv (nu concomitent) de firele din fascicul. Formatul Fortran:!$OMP CRITICAL [ name ] block!$omp END CRITICAL Formatul C/C++: #pragma omp critical [ name ] structured_block Note: 74 newline

75 Dacǎ un fir executǎ curent o regiune CRITICAL si un altul ajunge la acea regiune CRITICAL si încearcǎ sǎ o execute, el va sta blocat pânǎ când primul fir pǎrǎseste regiunea CRITICAL. Un nume optional face posibilǎ existenta regiunilor CRITICAL multiple: numele actioneazǎ ca identificatori globali. Regiunile CRITICAL diferite cu acelasi nume sunt tratate ca aceeasi regiune. Toate sectiunile CRITICAL fǎrǎ nume sunt tratate ca o aceeasi sectiune. Restrictii: nu este permis a se ramifica controlul în sau înafara unui bloc CRITICAL. Exemplu de construct CRITICAL: Toate firele dintr-un fascicul vor încerca sǎ execute paralel din cauza constructului CRITICAL care încorporeazǎ incrementul lui x, numai un fir va fi abilitat sǎ citeascǎ/incrementeze/citeascǎ x la un moment dat. În Fortran: PROGRAM CRITICAL INTEGER X X = 0!$OMP PARALLEL SHARED(X)!$OMP CRITICAL X = X + 1!$OMP END CRITICAL!$OMP END PARALLEL END În C/C++: #include <omp.h> main() { int x; x = 0; #pragma omp parallel shared(x) { #pragma omp critical x = x + 1; 75

76 } /* end of parallel section */ Constructe de sincronizare Directiva BARRIER Scop: Directiva BARRIER sincronizeazǎ toate firele unui fascicul. Când o directivǎ BARRIER este atinsǎ, orice fir asteaptǎ în acel punct pânǎ când toate celelalte fire ating si ele acea barierǎ. Toate firele reiau atunci executia în paralel a codului consecutiv barierei. Format în Fortran:!$OMP BARRIER Format în C/C++: #pragma omp barrier newline Restrictii: în C/C++, cea mai micǎ declaratie care contine o barierǎ trebuie sǎ fie un bloc structurat. De exemplu: GRESIT CORECT if (x == 0) { if (x == 0) #pragma omp barrier #pragma omp barrier } Directiva ATOMIC Scopul: Directiva ATOMIC specificǎ faptul cǎ o locatie particularǎ de memorie trebuie sǎ fie actualizatǎ atomic si nu lǎsate mai multe fire sǎ încerce sǎ scrie în ea. În esentǎ, aceastǎ directivǎ asigurǎ o mini-sectiune CRITICAL. Format în Fortran:!$OMP ATOMIC statement_expression Format în C/C++: #pragma omp atomic newline statement_expression 76

77 Restrictii: directiva se aplicǎ numai unei declaratii, cea imediat urmǎtoare. O declaratie atomicǎ trebuie sǎ aibe una din formele urmǎtoare: În Fortran: x x x x = = = = x operator expr expr operator x intrinsic(x, expr) intrinsic(expr, x) x este o variabilǎ scalarǎ, expr este o expresie scalarǎ care nu face referire la x, intrinsic este una din functiile MAX, MIN, IAND, IOR sau IEOR, operator este unul din urmǎtorii: +, *, -, /,.AND.,.OR.,.EQV. sau.neqv. În C/C++: x binop = expr x++ ++x x---x x este o variabilǎ scalarǎ, expr este o expresie scalarǎ care nu face referire la x, binop nu este overloaded1 si este una din urmǎtoarele +, *, -, /, &, ^,, >> sau <<. Restrictii: Directiva se aplicǎ numai unei declaratii, cea care urmeazǎ imediat. O declaratie atomicǎ trebuie sǎ aibǎ una din formele urmǎtoare: În Fortran: x x x x = = = = x operator expr expr operator x intrinsic(x, expr) intrinsic(expr, x) x este o variabilǎ scalarǎ, expr este o expresie scalarǎ care nu face referire la x, intrinsic este una din functiile MAX, MIN, IAND, IOR sau IEOR, operator este unul din urmǎtorii: +, *, -, /,.AND.,.OR.,.EQV. sau.neqv. În C/C++: 1 Overloading: În programare, abilitatea de a utiliza acelasi nume pentru mai mult de o variabilǎ sau procedurǎ, care cere compilatorului sǎ facǎ diferenta între ele contextual. 77

78 x binop = expr x++ ++x x---x x este o variabilǎ scalarǎ, expr este o expresie scalarǎ care nu face referire la x, binop nu este overloaded si este una din urmǎtoarele +, *, -, /, &, ^,, >> sau <<. Notǎ: numai încǎrcarea si depozitarea lui x sunt atomice; evaluarea expresiei nu este atomicǎ. Directiva FLUSH Scopul: directiva FLUSH identificǎ un punct de sincronizare la care implementarea trebuie sǎ furnizeze o vedere consistentǎ a memoriei. La acest punct, variabilele vizibile din fir sunt scrise înapoi în memorie. Formatul în Fortran:!$OMP FLUSH (list) Formatul în C/C++: #pragma omp flush (list) newline Note: Lista optionalǎ este o listǎ de variabile cu nume care vor fi evacuate în scopul evitǎrii evacuǎrii tuturor variabilelor. Pentru pointerii din listǎ, pointerii însisi sunt evacuati, nu obiectele la care ei se referǎ. Implementǎrile trebuie sǎ asigure cǎ orice modificare a variabilelor vizibile din fir este vizibilǎ tuturor firelor dupǎ acest punct; compilatoarele trebuie sǎ restituie valorile din registre în memorie, hardware-ul ar putea necesita evacuarea bufferelor de scriere etc. Directiva FLUSH este implicatǎ pentru directivele din tabelul de mai jos. Directiva nu este implicatǎ dacǎ este prezentǎ o clauzǎ NOWAIT. În Fortran În C / C++ BARRIER CRITICAL si END CRITICAL END DO END PARALLEL END SECTIONS END SINGLE barrier critical la intrare si la iesire ordered la intrare si la iesire parallel la iesire for la iesire sections la iesire 78

79 ORDERED si END ORDERED single la iesire Directiva ORDERED Scop: directiva ORDERED specificǎ faptul cǎ iteratiile buclei incluse vor fi executate în aceeasi ordine ca si când ar fi executate de un procesor secvential. Formatul în Fortran:!$OMP ORDERED (block)!$omp END ORDERED Formatul în C/C++: #pragma omp ordered newline structured_block Restricitii: o directivǎ ORDERED poate apǎrea numai în extensia dinamicǎ a directivelor DO sau PARALLEL DO din Fortran si parallel for din C/C++. Numai un fir este permis într-o sectiune ordered la un moment dat. Nu este permisǎ ramificarea în sau din blocurile ORDERED. O iteratie a unei bucle nu trebuie sǎ execute aceeasi directivǎ ORDERED mai mult decât o datǎ si nu trebuie sǎ execute mai mult de o directivǎ ORDERED. O buclǎ care contine o directivǎ ORDERED trebuie sǎ fie o buclǎ cu o clauzǎ ORDERED. Directiva THREADPRIVATE Scopul: directiva THREADPRIVATE este folositǎ pentru a face variabilele de domeniu fisier global (în C/C++) sau blocurile common (în Fortran) locale si persistente pentru un fir în executie de regiuni paralele multiple. Formatul în Fortran:!$OMP THREADPRIVATE (/cb/,...) cu cb nume de bloc common. Formatul în C/C++: #pragma omp threadprivate (list) Note: 79

80 Directiva trebuie sǎ aparǎ dupǎ declaratia listei de variabile/blocuri common. Fiecare fir îsi ia apoi propria sa copie a variabilelor/blocului comun, astfel datele scrise de un fir nu sunt vizibile celorlalte fire. De exemplu: În Fortran: PROGRAM THREADPRIV INTEGER ALPHA(10), BETA(10), I COMMON /A/ ALPHA!$OMP THREADPRIVATE(/A/) C Explicitly turn off dynamic threads CALL OMP_SET_DYNAMIC(.FALSE.) C First parallel region!$omp PARALLEL PRIVATE(BETA, I) DO I=1,10 ALPHA(I) = I BETA(I) = I END DO!$OMP END PARALLEL C Second parallel region!$omp PARALLEL PRINT *, 'ALPHA(3)=',ALPHA(3), ' BETA(3)=',BETA(3)!$OMP END PARALLEL END În C/C++: #include <omp.h> int alpha[10], beta[10], i; #pragma omp threadprivate(alpha) main () { /* Explicitly turn off dynamic threads */ omp_set_dynamic(0); /* First parallel region */ #pragma omp parallel private(i,beta) for (i=0; i < 10; i++) alpha[i] = beta[i] = i; 80

81 /* Second parallel region */ #pragma omp parallel printf("alpha[3]= %d and beta[3]= %d\n",alpha[3], beta[3]); } La prima intrare într-o regiune paralel, datele din variabilele si blocurile comune THREADPRIVATE ar trebui presupuse nedefinite, cu exceptia cazului în care în directiva PARALLEL este mentionatǎ clauza COPYIN. Variabilele THREADPRIVATE diferǎ de variabilele PRIVATE (discutate mai jos) deoarece ele sunt abilitate sǎ persiste între sectiuni paralel diferite ale codului. Restrictii: Datele din obiectele THREADPRIVATE sunt garantate a persista numai dacǎ mecanismul firelor dinamice este închis (turned off) si numǎrul de fire în regiuni paralel diferite rǎmâne constant. Setarea prin default a firelor dinamice este nedefinitǎ. Directiva THREADPRIVATE trebuie sǎ aparǎ dupǎ fiecare declaratie a unei variabile private/unui bloc comun din fir. În Fortran, numai blocurile comune cu nume pot fi fǎcute THREADPRIVATE. Clauze privind atributul de domeniu al datelor O problemǎ importantǎ pentru programarea OpenMP este întelegerea si utilizarea domeniului acoperit de date. Deoarece OpenMP se bazeazǎ pe modelul de programare cu memorie partajatǎ, cele mai multe variabile sunt utilizate în comun (shared) prin default. Variabilele globale includ în Fortran blocurile COMMON, variabilele SAVE, variabilele MODULE, iar în C variabilele cu domeniu fisier, statice. Variabilele private includ indicii pentru bucle, variabilele de stivǎ din subrutinele apelate din regiuni paralele. În Fortran variabilele automate dintr-un bloc de declaratii. Clauzele privind atributele de domeniu ale datelor sunt utilizate pentru a defini explicit cum trebuie utilizate variabilele în domenii. În lista clauzelor regǎsim: PRIVATE FIRSTPRIVATE LASTPRIVATE SHARED DEFAULT REDUCTION COPYIN Clauzele privind atributele de domeniu al datelor sunt utilizate în combinatie cu mai multe dirctive (PARALLEL, DO/for si SECTIONS) pentru a controla domeniul de utilizare a variabilelor incluse. 81

82 Aceste constructe fac posibil controlul mediului de date în timpul executǎrii constructelor paralel. Ele definesc cum si care variabile din sectiunea secventialǎ a programului sunt transferate cǎtre sectiunile paralel ale programului si invers. Ele definesc care variabile vor fi vizibile tuturor firelor din sectiunile paralel si care variabile vor fi alocate privat de toate firele. Notǎ: clauzele privind atributele de domeniu au efect numai în extinderea lor lexicalǎ/staticǎ. A se consulta tabelul cu sumarul clauzelor/directivelor pentru asocierea directive-clauze. Clauza PRIVATE Scop: Clauza PRIVATE declarǎ variabile care sunt private pentru fiecare fir. Formatul în Fortran: PRIVATE (list) Formatul în C/C++: private (list) Note: Variabilele PRIVATE se comportǎ dupǎ cum urmeazǎ: Un obiect nou de acelasi tip se declarǎ o datǎ pentru fiecare fir din fascicul. Toate referirile la obiectul originar sunt înlocuite cu referiri la obiectul nou. Variabilele declarate PRIVATE sunt neinitializate pentru fiecare fir. Comparatie între PRIVATE si THREADPRIVATE: PRIVATE THREADPRIVATE Articol de date C/C++: variabilǎ Fortran: variabilǎ sau bloc common C/C++: variabilǎ Fortran: bloc common Unde se declarǎ La începutul regiunii sau În declaratiile fiecǎrei rutine grupei de lucru partajat utilizând domeniul de bloc sau de fisier global Persistenta? Nu Da Extindere Dinamic Numai lexical cu exceptia trecerii ca argument al unei subrutine 82

83 Initializare Cu FIRSTPRIVATE Cu COPYIN Întrebǎri: pentru exemplele de cod cu THREADPRIVATE în C/C++ si Fortran: Ce rezultat asteptati în alpha[3] si în beta[3] în programele de mai sus? De ce? Pentru ambele exemple, alpha[3] trebuie sǎ fie 3, beta[3] trebuie sǎ fie zero sau sǎ aibǎ o valoare nedefinitǎ. Aceasta se întâmplǎ deoarece numai variabilele THREADPRIVATE pot persista în regiuni paralele succesive. Clauza SHARED Scop: clauza SARED declarǎ în lista ei variabile care sunt partajate între toate firele fascicolului. Formatul în Fortran: SAHRED (listǎ) Formatul în C/C++: shared (listǎ) Note: O variabilǎ partajatǎ existǎ numai într-o locatie de memorie si toate firele pot citi sau scrie la acea adresǎ. Este în responsabilitatea programatorului a asigura cǎ firele multiple au acces adecvat la variabilele SHARED (cum ar fi prin sectiunile CRITICAL). Clauza DEFAULT Scop: Clauza DEFAULT permite utilizatorului sǎ specifice prin default un domeniu PRIVATE, SHARED sau NONE pentru toate variabilele din extinderea lexicalǎ a oricǎrei regiuni paralel. Formatul în Fortran: DEFAULT (PRIVATE SHARED NONE) Formatul în C/C++: default (shared none) Note: Variabilele specifice pot fi absolvite de default utilizând clauzele PRIVATE, SHARED, FIRSTPRIVATE, LASTPRIVATE si REDUCTION. 83

84 Specificatia în C/C++ din OpenMP nu include private ca un default posibil. Totusi, unele implementǎri pot avea prevǎzutǎ aceastǎ optiune. Restrictii: numai clauza DEFAULT poate fi specificatǎ pe o directivǎ PARALLEL. Clauza FIRSTPRIVATE Scop: Clauza FIRSTPRIVATE combinǎ comportarea clauzei PRIVATE cu initializarea automatǎ a variabilelor din lista ei. Formatul în Fortran: FIRSTPRIVATE (listǎ) Formatul în C/C++: firstprivate (listǎ) Note: Variabilele listate sunt initializate potrivit cu valorile obiectelor lor originare înainte de intrarea în constructul paralel de lucru partajat. Clauza LASTPRIVATE Scop: Clauza LASTPRIVATE combinǎ comportarea clauzei PRIVATE cu copierea din iteratia ultimǎ din buclǎ sau sectiune în variabila obiect originarǎ. Formatul în Fortran: LASTPRIVATE (listǎ) Formatul în C/C++: lastprivate (listǎ) Note: Valorile copiate înapoi în variabilele obiect originare se obtin din ultima iteratie sau sectiune (secventialǎ) a constructului care o contine. De pildǎ, un fir membru al unui fascicul care executǎ iteratia finalǎ a unei sectiuni DO sau un fir membru al unui fascicul care executǎ ultima SECTION a unui context SECTIONS executǎ copierea cu propriile lui valori. Clauza COPYIN Scop: Clauza COPYIN asigurǎ un mijloc de a atribui aceeasi valoare variabilelor THREADPRIVATE pentru toate firele unui fascicul. 84

85 Formatul în Fortran: COPYIN (listǎ) Formatul în C/C++: copyin (listǎ) Note: Lista contine numele variabilelor de copiat. În Fortran lista poate contine atât nume de blocuri common cât si nume de variabile. Variabilele firului master sunt sursa tuturor cópiilor. Firele fasciculului sunt initializate cu valorile lor la intrarea în constructul paralel. Clauza REDUCTION Scop: Clauza REDUCTION executǎ o reducere pe variabilele care apar în listǎ. Pentru fiecare fir se creazǎ o copie privatǎ pentru fiecare variabilǎ din listǎ. La sfârsitul reducerii, variabila de reducere este aplicatǎ tuturor cópiilor private ale variabilelor partajate si rezultatul final este scris în variabila globalǎ folositǎ partajat. Formatul în Fortran: REDUCTION (operator intrinsic: list) Formatul în C/C++: reduction (operator: list) Exemplu: REDUCTION produsul scalar de vectori: Iteratiile buclei paralel vor fi distribuite în blocuri de dimensiune egalǎ fiecǎrui fir din fascicul (SCHEDULE STATIC). La finalul constructului buclei paralel toate firele vor aduna valorile rezultatelor lor pentru a actualiza copia globalǎ din firul master. În Fortran: PROGRAM DOT_PRODUCT INTEGER N, CHUNKSIZE, CHUNK, I PARAMETER (N=100) PARAMETER (CHUNKSIZE=10) REAL A(N), B(N), RESULT 85

86 ! Some initializations DO I = 1, N A(I) = I * 1.0 B(I) = I * 2.0 ENDDO RESULT= 0.0 CHUNK = CHUNKSIZE!$OMP!$OMP&!$OMP&!$OMP& PARALLEL DO DEFAULT(SHARED) PRIVATE(I) SCHEDULE(STATIC,CHUNK) REDUCTION(+:RESULT) DO I = 1, N RESULT = RESULT + (A(I) * B(I)) ENDDO!$OMP END PARALLEL DO NOWAIT PRINT *, 'Final Result= ', RESULT END În C/C++: #include <omp.h> main () { int i, n, chunk; float a[100], b[100], result; /* Some initializations */ n = 100; chunk = 10; result = 0.0; for (i=0; i < n; i++) { a[i] = i * 1.0; b[i] = i * 2.0; } #pragma omp parallel for default(shared) private(i) schedule(static,chunk) reduction(+:result) \ \ \ 86

87 for (i=0; i < n; i++) result = result + (a[i] * b[i]); printf("final result= %f\n",result); } Restrictii: Variabilele din listǎ trebuie sǎ fie variabile scalare cu nume. Ele nu pot fi masive sau variabile de tipul stucturilor. Ele trebuie de asemenea sǎ fie declarate SHARED în contextul care le include. Operatiile de reducere pot sǎ nu fie asociative pentru numere reale. Clauza REDUCTION este gânditǎ pentru a fi utilizatǎ pe o regiune sau pe un construct cu lucru partajat în care variabilele de reducere sunt utilizate numai în declaratii care au una din formele urmǎtoare: Fortran C / C++ x = x operator expr x = expr operator x (except subtraction) x = intrinsic(x, expr) x = intrinsic(expr, x) x = x op expr x = expr op x (except subtraction) x binop = expr x++ ++x x---x x este o variabilǎ scalarǎ din listǎ expr este o expresie scalarǎ care nu face referire la x intrinsic este MAX, MIN, IAND, IOR sau IEOR operator este +, *, -,.AND.,.OR.,.EQV. sau.neqv. x este o variabilǎ scalarǎ din listǎ expr este o expresie scalarǎ care nu face referire la x op nu este overloaded si este +, *, -, /, &, ^,, && sau binop nu este overloaded si este +, *, -, /, &, ^ sau Un sumar al clauzelor/directivelor OpenMP Tabelul urmǎtor sumarizeazǎ clauzele si acceptarea lor de directivele OpenMP. Clauze Directive 87

88 x x SHARED x x DEFAULT x FIRSTPRIVATE x LASTPRIVATE REDUCTION x COPYIN x x SINGLE x x SECTIONSPARALLEL PRIVATE DO/forPARALLEL x SECTIONS DO/for PARALLEL IF x x x x x x x x x x x x x x x x x x x x x x SCHEDULE x x ORDERED x x NOWAIT x x x Urmǎtoarele directive OpenMP nu admit clauze: MASTER CRITICAL BARRIER ATOMIC FLUSH ORDERED THREADPRIVATE Implememtǎrile pot diferi si diferǎ uneori de standard în ceea ce priveste acceptarea clauzelor de cǎtre fiecare directivǎ. 88

89 Reguli de legǎturǎ si de asezare una-în-alta pentru directive2 Cu exceptia mentiunii exprese, regulile se aplicǎ atât pentru implementǎrile Fortran cât si pentru cele C/C++. Notǎ: Fortranul API defineste de asemenea un numǎr de reguli pentru Data Environment. Acele reguli nu au fost reluate aici. Reguli de legǎturǎ pentru directive: Directivele DO/for, SECTIONS, SINGLE, MASTER si BARRIER sunt legate de includerea dinamicǎ PARALLEL dacǎ existǎ o asemenea includere. Dacǎ nu este executatǎ o regiune paralel, directivele acestea nu au nici un efect. Directiva ORDERED se leagǎ de buclele DO/for dinamice care o includ. Directiva ATOMIC obligǎ accesul exclusiv în raport cu directivele ATOMIC din toate firele, nu numai din fasciculul curent. Directiva CRITICAL obligǎ accesul exclusiv în raport cu directivele CRITICAL din toate firele, nu numai din fasciculul curent. O directivǎ nu poate niciodatǎ sǎ se lege la vreo directivǎ din afara celei mai apropiate directive PARALLEL care o include. Reguli de asezare una-în-alta: O directivǎ PARALLEL interioarǎ dinamic unei alte directive PARALLEL stabileste un nou fascicul care este compus numai din firul curent cu exceptia când a fost abilitat paralelismul unul-în-altul. Directivelor DO/for, SECTIONS si SINGLE care sunt legate de aceeasi directivǎ PARALLEL nu li se permite a fi una-în-alta. Directivele DO/for, SECTIONS si SINGLE nu sunt admise în extinderea dinamicǎ a regiunilor CRITICAL, ORDERED si MASTER. Directivele CRITICAL cu acelasi nume nu sunt permise a fi una în interiorul alteia. Directivele BARRIER nu sunt permise în extinderea dinamicǎ a regiunilor DO/for, ORDERED, SECTIONS, SINGLE, MASTER si CRITICAL. Directivele MASTER nu sunt permise în extinderea dinamicǎ a directivelor DO/for, SECTIONS si SINGLE. Diectivele ORDERED nu sunt permise în extinderea dinamicǎ a regiunilor CRITICAL. Orice directivǎ care este permisǎ când se executǎ dinamic în interiorul unei regiuni PARALLEL este de asemenea legalǎ când se executǎ în afara regiunii paralel. Când se executǎ dinamic în afara unei regiuni paralel specificatǎ de utilizator, directiva este executatǎ în raport cu un fascicul compus numai din firul master. Rutinele de bibiliotecǎ run-time 2 Sectiunea aceasta este în bunǎ mǎsurǎ orientativǎ. Utilizatorii sunt îndemnati sǎ consulte documentatia implementǎrii de care dispun. Este posibil ca regulile sǎ fie diferite de cele prezentate aici. 89

90 Privire generalǎ: Standardul OpenMP defineste o interfatǎ API pentru apeluri la bibiliotecǎ care executǎ o varietate de functii: Aflǎ prin chestionare numǎrul de fire/procesoare, stabileste numǎrul de fire de utilizat. Blocǎri de domeniu general prin rutine adecvate (semafoare). Rutine portabile pentru mǎsurarea timpului universal (wall clock time). Setarea functiilor de mediu de excutie: paralelism unul-în-altul, ajustarea dinamicǎ a firelor. Pentru C/C++ poate fi necesarǎ specificarea fisierului de incluziune omp.h. Pentru functiile/rutinele de încuiere (Lock): Variabiele lacǎt trebuie sǎ fie accesate numai prin rutinele de încuiere. Pentru Fortran, variabilele lacǎt trebuie sǎ fie de tipul întreg si de un gen suficient de larg pentru a retine o adresǎ. Pentru C/C++, variabila lacǎt trebuie sǎ aibǎ tipul omp_lock_t sau tipul omp_nest_lock_t, în functie de functia utilizatǎ. Note de implemetare: Implementarea poate sǎ suporte sau poate sǎ nu suporte paralelismul unul-înaltul si/sau firele dinamice. Dacǎ paralelismul unul-în-altul este suportat, este adesea numai nominal prin acea cǎ o regiune paralel una-în-alta poate avea numai un fir. Oricum, documentatia implementǎrii trebuie consultatǎ pentru aceste detalii sau se pot experimenta unele aspecte pentru a afla ceea ce nu este scris explicit în documentatie. OMP_SET_NUM_THREADS Scop: Seteazǎ numǎrul de fire care vor fi utilizate în regiunea paralel urmǎtoare. Trebuie sǎ fie un întreg pozitiv. Formatul în Fortran: SUBROUTINE OMP_SET_NUM_THREADS(scalar_integer_expression) Formatul în C/C++: #include <omp.h> void omp_set_num_threads(int num_threads) Note si restrictii: Mecanismul firelor dinamice modificǎ efectul acestei rutine. 90

91 Enabled: specificǎ numǎrul maxim de fire care pot fi utilizate pentru orice regiune paralel prin mecanismul firelor dinamice. Disabled: specificǎ numǎrul exact de fire de utilizat pânǎ la apelul urmǎtor la aceastǎ rutinǎ. Aceastǎ rutinǎ poate fi apelatǎ numai din portiunile secventiale ale codului. Acest apel are precedentǎ fatǎ de variabila de mediu OMP_NUM_THREADS. OMP_GET_NUM_THREADS Scop: returneazǎ numǎrul de fire care sunt în fasciculul curent si executǎ regiunea pralel din care este apelatǎ. Format în Fortran: INTEGER FUNCTION OMP_GET_NUM_THREADS() Format în C/C++: #include <omp.h> int omp_get_num_threads(void) Note si restrictii: Dacǎ acest apel este fǎcut dintr-o portiune secventialǎ a programului sau dintr-o regiune paralel una-în-alta care este serializatǎ, returul este 1. Numǎrul prin default al firelor este dependent de implementare. OMP_GET_MAX_THREADS Scop: returneazǎ valoarea maximǎ care poate fi returnatǎ de un apel la functia OPM_GET_NUM_THREADS. Format în Fortran: INTEGER FUNCTION OMP_GET_MAX_THREADS() Format în C/C++: #include <omp.h> int omp_get_max_threads(void) Note si restrictii: Reflectǎ în general numǎrul de fire setat de variabila de mediu OMP_NUM_THREADS sau de rutina OMP_SET_NUM_THREADS() din bibliotecǎ. Poate fi apelatǎ atât din regiunile seriale ale codului cât si din cele paralele. 91

92 OMP_GET_THREAD_NUM Scop: returneazǎ numǎrul de fir al firului, în interiorul fasciculului, prin acest apel. Numǎrul acesta va fi între 0 si OMP_GET_NUM_THREADS 1. Firul master din fascicul este firul 0. Format în Fotran: INTEGER FUNCTION OMP_GET_THREAD_NUM() Format în C/C++: #include <omp.h> int omp_get_thread_num(void) Note si restrictii: dacǎ este apelatǎ dintr-o regiune paralel una-în-alta, functia aceasta returneazǎ 0. Exemple: Exemplul 1 este modul corect de a determina numǎrul de fire într-o regiune paralel. Exemplul 2 este incorect variabila TID trebuie sǎ fie PRIVATE. Exemplul 3 este incorect apelul OMP_GET_THREAD_NUM este în afara unei regiuni paralel. Exemplele de determinare a numǎrului de fire dintr-o regiune paralel (în Fortran): Exemplul 1: PROGRAM HELLO INTEGER TID, OMP_GET_THREAD_NUM!$OMP PARALLEL PRIVATE(TID) TID = OMP_GET_THREAD_NUM() PRINT *, 'Hello World from thread = ', TID...!$OMP END PARALLEL END Exemplul 2: 92

93 PROGRAM HELLO INTEGER TID, OMP_GET_THREAD_NUM!$OMP PARALLEL TID = OMP_GET_THREAD_NUM() PRINT *, 'Hello World from thread = ', TID...!$OMP END PARALLEL END Exemplul 3: PROGRAM HELLO INTEGER TID, OMP_GET_THREAD_NUM TID = OMP_GET_THREAD_NUM() PRINT *, 'Hello World from thread = ', TID!$OMP PARALLEL...!$OMP END PARALLEL END OMP_GET_NUM_PROCS Scop: returneazǎ numǎrul de procesoare care sunt la dispozitia programului. Format în Fortran: INTEGER FUNCTION OMP_GET_NUM_PROCS() Format în C/C++: #include <omp.h> int omp_get_num_procs(void) OMP_IN_PARALLEL 93

94 Scop: poate fi apelatǎ pentru a determina dacǎ sectiunea de cod în executie este paralel sau nu. Formatul în Fortran: LOGICAL FUNCTION OMP_IN_PARALLEL() Formatul în C/C++: #include <omp.h> int omp_in_parallel(void) Note si restrictii: În Fortran aceastǎ functie returneazǎ.true. dacǎ este apelatǎ din extensia dinamicǎ a unei regiuni care lucreazǎ în paralel si.false. în alte situatii. În C/C++ ea returneazǎ un întreg nenul dacǎ apelul este dintr-o zonǎ paralel, zero altminteri. OMP_SET_DYNAMIC Scop: abiliteazǎ si desabiliteazǎ ajustarea dinamicǎ (de sistemul de executie) a numǎrului de fire disponibile pentru executarea regiunilor paralel. Formatul în Fortran: SUBROUTINE OMP_SET_DYNAMIC(scalar_logical_expression) Formatul în C/C++: #include <omp.h> void omp_set_dynamic(int dynamic_threads) Note si restrictii: Pentru Fortran, dacǎ este apelatǎ cu.true. atunci numǎrul de fire disponibile pentru regiunile paralel urmǎtoare poate fi modificat dinamic de mediul de executie (run-time). Dacǎ este apelatǎ cu.false. ca argument, modificarea dinamicǎ este fǎcutǎ imposibilǎ, este dezabilitatǎ. Pentru C/C++, dacǎ argumentul dynamic_threads este nenul, atunci mecanismul este abilitat, altminteri este dezabilitat. Subrutina OMP_SET_DYMAMIC are întâietate fatǎ de variabila de mediu OMP_DYNAMIC. Setarea prin default depinde de implementare. Poate fi apelatǎ dintr-o sectiune serialǎ/secventialǎ a programului. 94

95 OMP_GET_DYNAMIC Scop: determinarea stǎrii abilitat/dezabilitat a modificǎrii dinamice a firelor. Formatul în Fortran: LOGICAL FUNCTION OMP_GET_DYNAMIC() Formatul în C/C++: #include <omp.h> int omp_get_dynamic(void) Note si restrictii: Pentru Fortran, aceastǎ functie returneazǎ.true. sau.false. dupǎ cum modificarea dinamicǎ a firelor este abilitatǎ/dezabilitatǎ. Pentru C/C++, rezultatul apelului este non-zero/zero pentru cele douǎ situatii. OMP_SET_NESTED Scop: abilitarea sau dezabilitarea paralelismului unul-în-altul. Formatul în Fortran: SUBROUTINE OMP_SET_NESTED(scalar_logical_expression) Formatul în C/C++: #include <omp.h> void omp_set_nested(int nested) Note si restrictii: Pentru Fortran, apelarea acestei functii cu argumentul.false. dezabiliteazǎ paralelismul unul-în-altul si îl abiliteazǎ dacǎ argumentul este.true. Pentru C/C++, dacǎ variabila nested este nenulǎ, atunci paralelismul unul-înaltul este abilitat; dacǎ este nulǎ îl dezabiliteazǎ. Defaultul este cu paralelismul unul-în-altul dezabilitat, suspendat. Apelul este mai tare ca precedentǎ fatǎ de variabila de mediu OPM_NESTED. OMP_GET_NESTED Scop: determinǎ dacǎ paralelismul unul-în-altul este abilitat sau nu. Formatul în Fortran: LOGICAL FUNCTION OMP_GET_NESTED 95

96 Formatul în C/C++: #include <omp.h> int omp_get_nested (void) Note si restrictii: În Fortran, aceastǎ functie returneazǎ.true. dacǎ paralelismul unul-în-altul este abilitat si.false. în caz contrar. În C/C++, se returneazǎ o valoare nenulǎ dacǎ paralelismul unul-în-altul este abilitat si zero în caz contrar. OMP_INIT_LOCK Scopul: subrutina initializezǎ un lacǎt asociat cu variabila de lock. Formatul în Fortran: SUBROUTINE OMP_INIT_LOCK(var) SUBROUTINE OMP_INIT_NEST_LOCK(var) Formatul în C/C++: #include <omp.h> void omp_init_lock(omp_lock_t *lock) void omp_init_nest_lock(omp_nest_lock_t *lock) Note si restrictii: Starea initialǎ este unlocked. Pentru versiunea Fortran var trebuie sǎ fie un întreg suficient de mare pentru a retine o adresǎ, cum ar fi INTEGER*8 pentru sistemele pe 64 de biti. OMP_DESTROY_LOCK Scop: aceastǎ subrutinǎ disociazǎ o variabilǎ lacǎt de orice lacǎt. Formatul în Fortran: SUBROUTINE OMP_DESTROY_LOCK(var) SUBROUTINE OMP_DESTROY_NEST_LOCK(var) Formatul în C/C++: #include <omp.h> void omp_destroy_lock(omp_lock_t *lock) void omp_destroy_nest_lock(omp_nest_lock_t *lock) 96

97 Note si restrictii: Este nepermis a apela aceastǎ subrutinǎ cu o variabilǎ lock care nu este initializatǎ. În Fortran var trebuie sǎ fie un întreg suficient de larg pentru a retine o adresǎ, cum este INTEGER*8 pentru sistemele pe 64 de biti. OMP_SET_LOCK Scop: aceastǎ subrutinǎ obligǎ firul executant sǎ astepte pânǎ când un lacǎt specificat este disponibil. Un fir este proprietar al unui lock când acesta devine disponibil. Formatul în Fortran: SUBROUTINE OMP_SET_LOCK(var) SUBROUTINE OMP_SET_NEST_LOCK(var) Formatul în C/C++: #include <omp.h> void omp_set_lock(omp_lock_t *lock) void omp_set_nest_lock(omp_nest_lock_t *lock) Note si restrictii: Este nepermis a apela aceastǎ rutinǎ cu o variabilǎ lock neinitializatǎ. Pentru Fortran, var trebuie sǎ fie un întreg suficient de larg pentru a retine o adresǎ, de pildǎ INTEGER*8 pentru sistemele pe 64 de biti. OMP_UNSET_LOCK Scop: aceastǎ subrutinǎ descuie un lock dintr-o subrutinǎ în executie. Formatul în Fortran: SUBROUTINE OMP_UNSET_LOCK(var) SUBROUTINE OMP_UNSET_NEST_LOCK(var) Formatul în C/C++: #include <omp.h> void omp_unset_lock(omp_lock_t *lock) void omp_unset_nest_lock(omp_nest_lock_t *lock) Note si restrictii: Nu este permis a se apela aceastǎ subrutinǎ cu o variabilǎ lock neinitializatǎ. 97

98 Pentru Fortran, var trebuie sǎ fie un întreg suficient de mare pentru a retine o adresǎ, de pildǎ INTEGER*8 pentru un sistem pe 64 de biti. OMP_TEST_LOCK Scop: aceastǎ subrutinǎ încearcǎ a seta un lock dar nu blocheazǎ dacǎ lacǎtul este indisponibil. Formatul în Fortran: SUBROUTINE OMP_TEST_LOCK(var) SUBROUTINE OMP_TEST_NEST_LOCK(var) Formatul în C/C++: #include <omp.h> int omp_test_lock(omp_lock_t *lock) int omp_test_nest_lock(omp_nest_lock_t *lock) Note si restrictii: În Fortran, este restituit.true. dacǎ lacǎtul a fost setat cu succes, altminteri se returneazǎ.false. Tot în Fortran, var trebuie sǎ fie un întreg suficient de mare pentru a retine o adresǎ, de pildǎ INTEGER*8 pentru un sistem pe 64 de biti. Pentru C/C++, este restituitǎ o valoare nenulǎ dacǎ lacǎtul a fost setat cu succes, altminteri este restituit zero. Este interzis a apela aceastǎ subrutinǎ cu o variabilǎ lock neinitializatǎ. OMP_GET_WTIME Scop: furnizeazǎ o rutinǎ portabilǎ de temporizare în timp universal (wall clock). Returneazǎ o valoare în dublǎ precizie egalǎ cu numǎrul de secunde scurse de la un anumit punct în trecut. Uzual, este folositǎ în pereche cu valoarea de la primul apel scǎzutǎ din valoarea apelului al doilea pentru a obtine timpul scurs pentru un bloc de cod. Proiectatǎ a da timpii pe fir si de aceea nu poate fi consistentǎ global, pe toate firele unui fascicul; depinde de ceea ce face un fir comparativ cu alte fire. Formatul în Fortran: DOUBLE PRECISION FUNCTION OMP_GET_WTIME() Formatul în C/C++: 98

99 #include <omp.h> double omp_get_wtime(void) Note si restrictii: Necesitǎ suportul versiunii OpenMP 2.0. OMP_GET_WTICK Scop: furnizeazǎ o rutinǎ portabilǎ de temporizare în timp universal (wall clock). Returneazǎ o valoare în dublǎ precizie egalǎ cu numǎrul de secunde între douǎ tic-uri succesive ale ceasului. Formatul în Fortran: DOUBLE PRECISION FUNCTION OMP_GET_WTICK() Formatul în C/C++: #include <omp.h> double omp_get_wtick(void) Note si restrictii: Necesitǎ suportul versiunii OpenMP 2.0. Variable de mediu (de programare) OpenMP furnizeazǎ patru variabile de mediu pentru controlul executiei unui cod paralel. Toate numele variabilelor de mediu sunt scrise cu majuscule. Valorile atribuite lor nu sunt sensibile la upper/lower case. OMP_SCHEDULE Se aplicǎ numai la directivele DO, PRALLEL DO (Fortran) si for, parallel for (C/C++) care au clauzele lor schedule setate în timpul executiei (RUNTIME). Valoarea acestei variabile determinǎ modul cum sunt planificate iteratiile buclei pe procesoare. De pildǎ: setenv OMP_SCHEDULE "guided, 4" setenv OMP_SCHEDULE "dynamic" OMP_NUM_THREADS Fixeazǎ numǎrul maxim de fire utilizate în timpul executiei. De exemplu: setenv OMP_NUM_THREADS 8 99

100 OMP_DYNAMIC Abiliteazǎ sau dezabiliteazǎ ajustarea dinamicǎ a numǎrului de fire disponibile pentru executarea unei regiuni paralel. Valorile valide sunt TRUE sau FALSE. De exemplu: setenv OMP_DYNAMIC TRUE OMP_NESTED Abiliteazǎ sau dezabiliteazǎ paralelismul unul-în-altul. Valorile valide sunt TRUE sau FALSE. De exemplu: setenv OMP_NESTED TRUE Note de implementare: O implementare sau alta poate sǎ permitǎ sau nu paralelismul unul-în-altul si/sau firele dinamice. Dacǎ paralelismul unul-în-altul este suportat, el este adesea numai nominal, în aceea cǎ o regiune paralel una-în-alta poate avea numai un fir. Pentru detalii trebuie consultatǎ documentatia implementǎrii utilizate sau se poate experimenta pentru a afla ceea ce nu se poate gǎsi în documentatie. Probleme de memorie si performantǎ Dimensiunea stivei de fir: Standardul OpenMP nu specificǎ cât spatiu de stivǎ trebuie sǎ aibǎ un fir. În consecintǎ, implementǎrile pot diferi prin dimensiunea de default a stivei de fir. De obicei, dimensiunea prin default a stivei de fir este usor a fi epuizatǎ. De pildǎ: Compilator Limita stivei Dimesiunea aproximativǎ a matricilor (dublǎ precizie) KAI Guide 1 MB 353 x 353 IBM AIX 4 MB 707 x 707 HP/Compaq Tru64 5 MB 790 x 790 Intel Linux 8 MB 1000 x 1000 IA32 100

101 Firele care depǎsesc alocarea lor de stivǎ pot sau nu da eroare de segmentare. O aplicatie poate continua executia cu coruperea datelor. Cresterea limitei stivei de fir este de obicei posibilǎ. Tabela de mai jos aratǎ cum se majoreazǎ dimensiunea stivei la 12 MB pentru mai multe platforme uzuale. Platforma Comenzi shell csh Comenzi shell ksh IBM AIX limit stacksize setenv XLSMPOPTS "stack= " ulimit -s export XLSMPOPTS="stack= " IA-32 Linux limit stacksize setenv KMP_STACKSIZE ulimit -s export KMP_STACKSIZE= HP/Compaq Tru64 limit stacksize setenv MP_STACK_SIZE ulimit -s export MP_STACK_SIZE= SGI Origin limit stacksize setenv MP_SLAVE_STACKSIZE ulimit -s export MP_SLAVE_STACKSIZE= Codurile legate statistic ar putea fi supuse la restrictii de stivǎ suplimentare. 101

102 MPI MESSAGE PASSING INTERFACE Ce este MPI? MPI (Message Passing Interface) este o interfatǎ care poate fi consideratǎ o specificatie pentru cei care dezvoltǎ si utilizeazǎ bibliotecile pentru transferul de mesaje. Interfata MPI nu este ea însǎsi o bibliotecǎ, ci mai curând o descriere a ceea ce ar trebui sǎ fie o astfel de bibliotecǎ. Mai direct, scopul MPI este acela de a furniza un standard de uz larg în scrierea de programe care transferǎ mesaje. Interfata încearcǎ sǎ fie practicǎ, portabilǎ, eficientǎ, flexibilǎ. Specificatiile interfetei au fost definite pentru programe scrise în C/C++ si în Fortran. Istorie si evolutie MPI a rezultat din eforturile mai multor grupuri si persoane, eforturi care s-au extins pe o perioadǎ de circa 2 ani, între 1992 si Câteva repere istorice: În anii 80 si anii 90 timpurii ai secolului trecut se dezvoltǎ calculul paralel cu memorie distribuitǎ dar si un numǎr de instrumente software (incompatibile mutual) de scriere a programelor, uzual cu compromisuri între portabilitate, performante, functionalitate si pret. S-a nǎscut în mod natural necesitatea unui standard. 102

103 În aprilie 1992 are loc un Workshop on Standards for Message Passing in a Distributed Memory Environment sponsorizat de Center for Research on Parallel Computing, Williamsburg, Virginia. S-a discutat despre trǎsǎturile de bazǎ ale unui standard de transfer al mesajelor, s-a constituit un grup de lucru pentru continuarea procesului de standardizare. Imediat s-a elaborat si o propunere preliminarǎ. În noiembrie 1992 grupul de lucru se întruneste la Minneapolis. Este prezentat în proiect MPI-1 de cǎtre ORNL (Oak Ridge National Laboratory). Grupul adoptǎ procedurile si organizarea pentru a forma un MPI Forum. MPIF a cuprins ulterior 175 de persoane si 40 de organizatii care includeau producǎtori de calculatoare paralel, producǎtori de software, persoane din mediul academic si de cercetare. În noiembrie 1993 are loc Supercomputing 93 Conference unde este prezentat în proiect standardul MPI. Versiunea finalǎ a fost lansatǎ în mai 1994 si este accesibilǎ la: MPI-2 a recoltat ceea ce prima specificatie MPI a lǎsat în urmǎ si se referǎ la subiectele care sunt dincolo de acea primǎ specificatie. Originalul MPI a devenit cunoscut ca MPI-1. MPI-2 este descris pe scurt mai jos. A fost finalizat în Azi, implementǎrile MPI sunt o combinatie de MPI-1 si MPI-2. Putine implementǎri includ functionalitǎtile complete ale ambelor versiuni. Ratiuni de utilizare a MPI Standardizare: MPI este unica bibliotecǎ de transfer de mesaje care poate fi consideratǎ un standard. Este suportatǎ de aproape toate platformele HPC (High Performance Computing). Practic, MPI a înlocuit toate bibliotecile anterioare care sunt orientate pe transferul de mesaje. Portabilitate: Nu trebuie modificat codul sursǎ când se trece de la o platformǎ la alta dacǎ platformele suportǎ (sau se pliazǎ pe) standardul MPI. Performante: Implementǎrile producǎtorilor sunt abilitate sǎ exploateze particularitǎtile hardware native pentru a optimiza performatele. Functionalitate: Sunt definite peste 115 rutine. Accesibilitate: Este accesibilǎ o varietate de implementǎri, atât de domeniul public cât si proprietate de firmǎ. Modelul de programare 103

104 MPI se preteazǎ la cele mai multe (dacǎ nu la toate) modele(le) de programare paralel cu memorie distribuitǎ. În plus, MPI este utilizat la modul comun în implementarea (din culise a) unor modele cu memorie partajatǎ, cum este cel paralel-pe-date, pe arhitecturi cu memorie distribuitǎ. Platforme hardware Memorie distribuitǎ: la origine, MPI a fost destinat sistemelor cu memorie distribuitǎ. Memorie partajatǎ: pe mǎsurǎ ce sistemele cu memorie partajatǎ s-au rǎspândit, în particular arhitecturile SMP/NUMA (Symmetric MultiProcessing/NonUniform Memory Access), au apǎrut si implementǎrile MPI pe acest gen de platforme. Hibride: interfata MPI este acum utilizatǎ aroape pe orice arhitecturǎ paralelǎ obisnuitǎ, inclusiv pe masinile masiv paralele, clusterele SMP, clusterele de statii de lucru si retelele eterogene. Întregul paralelism este explicit: programatorul este responsabil pentru identificarea corectǎ a paralelismului si pentru implementarea algoritmilor paraleli prin mijlocirea constructelor MPI. Numǎrul de taskuri dedicate de rulat într-un program paralel este static. Taskurile noi nu pot fi derulate dinamic în timpul executiei (MPI-2 se ocupǎ de aceastǎ problemǎ). Initializare Fisierul header: cerut pentru toate programele/rutinele care fac apel la biblioteca MPI. În C #include mpi.h În Fortran include mpif.h Formatul apelurilor MPI: În C rc = MPI_Xxxxx(parametru, ) Exemplu: rc = MPI_Bsend(&buf,count,type,dest,tag,comm) Cod de eroare: returnat ca rc. MPI_SUCCESS dacǎ apelul a reusit. În Fortran CALL MPI_XXXXX(parametru,, ierr) call mpi_xxxxx(parametru,, ierr) Exemplu: CALL MPI_BSEND(buf,count,type,dest,tag,comm,ierr) 104

105 Cod de eroare: returnat ca parametru ierr. MPI_SUCCESS dacǎ apelul a reusit. Numele din C sunt sensibile la upper/lower case. Numele din Fortran nu fac distinctie între caracterele mari si mici. Structura generalǎ a programelor MPI Fisierul MPI include... Initializarea MPI environment... Executie si apeluri pentru transferul de mesaje... Încheierea MPI environmemt Comunicatori si grupuri Pentru a defini procesele grupate într-o colectie, procese care pot comunica între ele, MPI utilizeazǎ obiecte numite comunicatori si grupuri. Multe dintre rutinele MPI cer specificarea unui comunicator ca argument. Comunicatorii si grupurile vor fi obiectul unei discutii mai târziu. Deocamdatǎ se utilizeazǎ simplu MPI_COMM_WORLD ori de câte ori se cere un comunicator; acesta este comunicatorul predefinit care include toate procesele MPI. Rang 105

106 Într-un comunicator, fiecare proces are propriul sǎu identificator de tipul întreg atribuit de sistem la initializarea sistemului. Un rang este uneori denumit identificator de proces (process ID). Rangurile sunt numerotate fǎrǎ lacune si numerotarea începe cu 0. Rangul este utilizat de programator pentru a specifica sursa sau destinatia mesajelor. Uneori este utilizat de aplicatie conditional pentru a controla executia programului (if rank = 0 etc.). Rutine de administrare a mediului Rutinele de administrare a mediului MPI sunt utilizate pentru definirea domeniilor, cum ar fi initializarea si încheierea mediului MPI, pentru chestionarea mediului si identificare etc. Cea mai mare parte a acestor rutine utilizate curent sunt descrise în continuare. MPI_Init. Initializeazǎ mediul MPI de executie. Aceastǎ functie trebuie apelatǎ în orice program MPI înainte de orice altǎ functie MPI si trebuie sǎ fie chematǎ o singurǎ datǎ într-un program. Pentru programele în C, MPI_Init poate fi utilizat pentru a trece argumentele din linia de comandǎ tuturor proceselor, desi aceastǎ trecere nu-i cerutǎ de standard si este dependentǎ de implementare. MPI_Init (&argc, &argv) MPI_INIT (ierr) MPI_Comm_size. Determinǎ numǎrul de procese într-un grup asociat cu un comunicator. În general se utilizeazǎ în comunicatorul MPI_COMM_WORLD pentru a determina numǎrul de procese utilizate de o aplicatie. MPI_Comm_size (comm, &size) MPI_COMM_SIZE (comm, size, ierr) MPI_Comm_rank. Determinǎ rangul procesului apelant într-un comunicator. Initial, fiecǎrui proces i se atribuie un rang întreg unic între 0 si numǎrul de procesoare 1 cuprinse în comunicatorul MPI_COMM_WORLD. Acest rang este numit uneori task ID, identificator de task. Dacǎ un proces se asociazǎ cu alti comunicatori, el va avea un rang unic în fiecare din acesti comunicatori. MPI_Comm_rank (comm, &rank) MPI_COMM_RANK (comm, rank, ierr) MPI_Abort. Încheie un proces asociat cu un comunicator. În cele mai multe implementǎri MPI aceastǎ functie încheie toate procesele indiferent de comunicatorul specificat. MPI_Abort (comm, errorcode) MPI_ABORT (comm, errorcode, ierr) 106

107 MPI_Get_processor_name. Returneazǎ numele procesorului dar si lungimea numelui. Bufferul pentru name trebuie sǎ fie de cel putin MPI_MAX_PROCESSOR_NAME caractere. Ce se returneazǎ în name este dependent de implementare poate sǎ nu fie acelasi lucru cu iesirea comenzilor hostname sau host. MPI_Get_processor_name (&name, &resultlength) MPI_GET_PROCESSOR_NAME (name, resultlength, ierr) MPI_Initialized. Indicǎ dacǎ s-a apelat MPI_Init si returneazǎ un flag logic true (1) sau false (0). MPI cere ca MPI_Init sǎ fie apelat o datǎ si numai o datǎ de fiecare proces. Acestǎ problemǎ se pune pentru module care vor sǎ utilizeze MPI si astfel sunt pregǎtite sǎ apeleze MPI_Init dacǎ este necesar. MPI_Initialized rezolvǎ tocmai aceastǎ problemǎ. MPI_Initialized (&flag) MPI_INITIALIZED (flag, ierr) MPI_Wtime. Returneazǎ în secunde (dublǎ precizie) timpul universal (wall clock time) scurs pe procesorul apelant. MPI_Wtime () MPI_WTIME () MPI_Wtick. Returneazǎ rezolutia în secunde (dublǎ precizie) a MPI_Wtime. MPI_Wtick () MPI_WTICK () MPI_Finalize. Încheie mediul de executie MPI. Aceastǎ functie trebuie sǎ fie apelatǎ ultima în orice program MPI nici o altǎ rutinǎ MPI nu mai poate fi apelatǎ dupǎ ea. MPI_Finalize () MPI_FINALIZE (ierr) Exemple de rutine de administrare a mediului: În C: #include "mpi.h" #include <stdio.h> int main(argc,argv) int argc; char *argv[]; { int numtasks, rank, rc; rc = MPI_Init(&argc,&argv); if (rc!= MPI_SUCCESS) { 107

108 printf ("Error starting MPI program. Terminating.\n"); MPI_Abort(MPI_COMM_WORLD, rc); } MPI_Comm_size(MPI_COMM_WORLD,&numtasks); MPI_Comm_rank(MPI_COMM_WORLD,&rank); printf ("Number of tasks= %d My rank= %d\n", numtasks,rank); /******* do some work *******/ MPI_Finalize(); } În Fortran: program simple include 'mpif.h' integer numtasks, rank, ierr, rc call MPI_INIT(ierr) if (ierr.ne. MPI_SUCCESS) then print *,'Error starting MPI program. Terminating.' call MPI_ABORT(MPI_COMM_WORLD, rc, ierr) end if call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr) print *, 'Number of tasks=',numtasks,' My rank=',rank C ****** do some work ****** call MPI_FINALIZE(ierr) end Rutine de comunicare punct la punct Concepte generale Tipuri de operatii punct-la-punct: Operatiile MPI punct-la-punct constau în principal în transferul de mesaje între douǎ si numai douǎ taskuri MPI diferite. Un task executǎ o operatie de expediere si celǎlalt task executǎ operatia de primire. 108

109 Sunt tipuri diferite de rutine de trimitere si de primire utilizate pentru scopuri diferite. Exemple: Send sincron Send/receive blocant Send/receive fǎrǎ blocare Send bufferizat Send/receive combinat Send de tipul ready Orice tip de rutinǎ de trimitere (send) trebuie sǎ aibǎ ca pereche o rutinǎ de primire (receive). MPI asigurǎ si câteva rutine asociate cu operatiile send receive, cum sunt cele pentru asteptarea sosirii unui mesaj sau pentru verificarea sosirii la destinatie a unui mesaj. Bufferizare: Într-un univers perfect, fiecare operatie send ar fi perfect sincronizatǎ cu perechea receive. Practic, rareori se întâmplǎ asa. Într-un mod sau altul, implementǎrile MPI trebuie sǎ aibǎ capacitatea de a memora date dacǎ cele douǎ taskuri sunt nesincrone. Iatǎ douǎ cazuri: Procesul A trimite un mesaj cu 5 secunde mai înainte ca receptia în B sǎ fie pregǎtitǎ. Unde se gǎseste mesajul pânǎ la momentul când procesul B este gata sǎ-l preia? Mai multe trimiteri sosesc deodatǎ la acelasi proces destinatie, proces care nu poate accepta trimiterile altfel decât una dupǎ alta: ce se întâmplǎ cu mesajele sosite? Implementarea MPI (nu standardul MPI) decide ce se întâmplǎ cu datele în aceste cazuri. Tipic, este alocat/rezervat un buffer de sistem pentru a retine datele în tranzit. Figura alǎturatǎ ilustreazǎ o posibilitate. 109

110 Spatiul de bufferizare al sistemului este: Opac pentru programator si este administrat integral de biblioteca MPI. Resursǎ finitǎ care poate fi cu usurintǎ epuizatǎ. Adesea misterios si nu prea bine documentat/explicat. Posibil a exista la procesul expeditor, la procesul receptor sau la ambele procese. Ceva care poate spori performanta programului deoarece admite ca operatiile send receive sǎ fie asincrone. Spatiul de adresare administrat de utilizator (variabilele programului) este denumit buffer de aplicatie. MPI asigurǎ si un buffer de trimiteri administrabil de utilizator. Cu blocare/fǎrǎ blocare: Multe din rutinele MPI punct-la-punct pot fi blocante sau non-blocante. Cu blocare: O rutinǎ de trimitere cu blocare revine numai dupǎ ce este sigurǎ cǎ a modificat bufferul de aplicatie (prin trimiterea datelor) care este gata pentru a fi reutilizat. Sigur înseamnǎ cǎ modificǎrile nu vor afecta datele destinate taskului de receptie. Sigur nu implicǎ receptionarea efectivǎ a acelor date: ele pot foarte bine sǎ mai stea încǎ un timp în bufferul de sistem. O trimitere cu blocare poate fi sincronǎ, ceea ce înseamnǎ cǎ existǎ un schimb (handshaking) cu taskul de primire care confirmǎ trimiterea în sigurantǎ. O trimitere cu blocare poate fi asincronǎ dacǎ este utilizat un buffer de sistem pentru retinerea (temporarǎ a) datelor în vederea livrǎrii ulterioare cǎtre receptor. O primire cu blocare revine numai dupǎ ce datele au sosit si sunt gata pentru a fi utilizate de program. 110

111 Fǎrǎ blocare: Rutinele de trimitere si de primire fǎrǎ blocare se comportǎ similar: ele revin aproape imediat. Pentru a se încheia, ele nu asteaptǎ vreun eveniment comunicational, cum ar fi copierea unui mesaj din memoria utilizator în spatiul bufferului de sistem sau sosirea efectivǎ a mesajului. Operatiile fǎrǎ blocare cer pur si simplu bibliotecii MPI sǎ execute operatia de îndatǎ ce poate. Utilizatorul nu poate prezice când se va produce executia acelei operatii. Este nesigur a modifica bufferul de aplicatie (spatiul variabilelor) pânǎ când nu se cunoaste faptul cǎ operatia fǎrǎ blocare cerutǎ a fost efectiv executatǎ de bibliotecǎ. Existǎ rutine de asteptare utilizate pentru a face aceastǎ confirmare. Comunicatiile fǎrǎ blocare sunt utilizate în primul rând pentru a suprapune calculele cu comunicarea si pentru exploatarea unor posibile câstiguri de performantǎ. Ordine si corectitudine: Ordine: MPI garanteazǎ cǎ mesajele nu se amestecǎ unul cu altul. Dacǎ un expeditor trimite succesiv douǎ mesaje (mesajul 1 si mesajul 2) la aceeasi destinatie si ambele sunt pereche cu acelasi receive, operatia de receptie va primi mesajul 1 înainte de mesajul 2. Dacǎ un receptor posteazǎ succesiv douǎ primiri (primirea 1 si primirea 2) si ambele cautǎ spre acelasi mesaj, primirea 1 se va produce înaintea primirii 2. Regulile de ordine nu se aplicǎ dacǎ sunt mai multe fire care participǎ la operatiile de comunicare. Corectitudine: Interfata MPI nu garanteazǎ corectitudinea este obligatia programatorului a preveni operatiunile incomplete ( operation starvation ). Exemplu: Taskul 0 trimite un mesaj la taskul 2. Dar si taskul 1 trimite un mesaj în competitie care este pereche cu receive-ul din taskul 2. Numai una din trimiteri va fi executatǎ pânǎ la capǎt. Argumentele rutinelor MPI de transfer de mesaje Rutinele MPI de comunicare punct-la-punct au în general o listǎ de argumente care aratǎ ca în exemplele care urmeazǎ. Trimitere cu blocare: MPI_Send(buffer,count,type,dest,tag,comm) Trimitere fǎrǎ blocare: MPI_Isend(buffer,count,type,dest,tag,comm,request) Receptie cu blocare: MPI_Recv(buffer,count,type,source,tag,comm,status) Receptie fǎrǎ blocare: MPI_Irecv(buffer,count,type,source,tag,comm,request) Buffer: spatiul de adresare al unei aplicatii (program) care se asociazǎ datelor care trebuie trimise sau primite. În cele mai multe cazuri, acesta este pur si simplu numele variabilei care trebuie trimisǎ/primitǎ. Pentru programele în C, 111

112 acest argument este trecut prin referire si trebuie uzual sǎ fie prefixat de caracterul ampersand: &var1. Contor de date (count): indicǎ numǎrul de articole-date de un anumit tip care trebuie trimise. Tipul datelor (type): din ratiuni de portabilitate, MPI predefineste tipurile sale de date elementare. Tabelul care urmeazǎ contine tipurile de date prevǎzute de standardul MPI. Tipuri de date în C Tipuri de date în Fortran MPI_CHAR char cu semn MPI_SHORT short int cu semn MPI_INT int cu semn MPI_LONG long int cu semn MPI_UNSIGNED_CHAR char fǎrǎ semn MPI_CHARACTER Character(1) MPI_INTEGER integer real MPI_UNSIGNED_SHORT short int fǎrǎ semn MPI_UNSIGNED int fǎrǎ semn MPI_UNSIGNED_LONG long int fǎrǎ semn MPI_FLOAT float MPI_REAL MPI_DOUBLE double MPI_DOUBLE_PRECISION double precision MPI_LONG_DOUBLE long double MPI_COMPLEX complex MPI_DOUBLE_COMPLEX double complex MPI_LOGICAL logical MPI_BYTE 8 digiti binari MPI_BYTE 8 digiti binari MPI_PACKED date în pachete sau nu, cu MPI_Pack()/ MPI_PACKED date în pachete sau nu, cu MPI_Pack()/ 112

113 MPI_Unpack MPI_Unpack Note: Programatorii pot crea tipuri de date proprii (tipuri de date derivate; v.mai jos). MPI_BYTE si MPI_PACKED nu corespund tipurilor standard din C sau Fortran. Standardul MPI include urmǎtoarele tipuri de date optionale: C: MPI_LONG_LONG_INT. Fortran: MPI_INTEGER1, MPI_INTEGER2, MPI_INTEGER4, MPI_REAL2, MPI_REAL4, MPI_REAL8. Unele implementǎri pot include tipuri de date elementare în plus (MPI_LOGICAL2, MPI_COMPLEX32 etc.). Trebuie verificat fisierul MPI header. Destinatie (dest): un argument al rutinelor de trimitere care indicǎ procesul unde mesajul trebuie livrat. Se mentioneazǎ ca rangul procesului primitor. Sursa (source): un argument al rutinelor de primire care indicǎ procesul de provenientǎ a mesajului. Specificat ca rangul procesului expeditor. Sursa poate fi setatǎ universal ca fiind MPI_ANY_SOURCE, ceea ce face posibilǎ primirea unui mesaj de la orice task. Tag: un întreg nenegativ arbitrar atribuit de programator pentru identificarea unicǎ a mesajului. Operatiile send si receive trebuie sǎ se potriveascǎ la etichetele (tags) mesajului. Pentru operatia de primire se poate utiliza MPI_ANY_TAG pentru a primi orice mesaj, indiferent de eticheta lui. Standardul MPI garanteazǎ utilizarea de etichete (tags) de la 0 la dar unele implementǎri permit domenii mai întinse decât acesta. Comunicator (comm): indicǎ contextul comunicǎrii sau multimea de procese pentru care câmpurile sursǎ si destinatie sunt valide. Cu exceptia cazurilor în care programatorul creeazǎ comunicatori noi, se foloseste de obicei comunicatorul predefinit MPI_COMM_WORLD. Status: pentru o operatie de primire, indicǎ sursa mesajului si eticheta lui. În C, acest argument este un pointer la o structurǎ predefinitǎ MPI_Status (explicit: stat.mpi_source stat.mpi_tag). În Fortran, este vorba de un masiv de întregi de dimensiunea MPI_STATUS_SIZE (explicit: stat(mpi_source) stat(mpi_tag). În plus, numǎrul adevǎrat de bytes primiti este obtenabil din Status via rutina MPI_Get_count. Request: utilizat de operatiile de trimitere si primire fǎrǎ blocare. Deoarece operatiile fǎrǎ blocare pot reveni înainte ca spatiul cerut de bufferul sistemului sǎ fie obtinut, sistemul genereazǎ un request number unic. Programatorul utilizeazǎ acest handle atribuit (într-o rutinǎ de tip WAIT) pentru a determina încheierea operatiei fǎrǎ blocare. În C, acest argument este un pointer cǎtre o structurǎ predefinitǎ MPI_Request. În Fortran acesta este un întreg. 113

114 Rutine de transfer de mesaje cu blocare Rutinele de transfer de mesaje cu blocare cel mai frecvent utilizate sunt descrise în continuare. MPI_Send. Operatia de trimitere cu blocare de bazǎ. Rutina revine numai dupǎ ce bufferul de aplicatie din taskul expeditor este liber pentru refolosire. De retinut cǎ aceastǎ rutinǎ poate fi implementatǎ diferit pe sisteme diferite. Standardul MPI permite utilizarea unui buffer de sistem dar nu-l reclamǎ neapǎrat. Unele implementǎri pot utiliza în realitate o trimitere sincronǎ (discutatǎ mai departe) pentru a implementa trimiterea de bazǎ cu blocare. MPI_Send (&buf,count,datatype,dest,tag,comm) MPI_SEND (buf,count,datatype,dest,tag,comm,ierr) MPI_Recv. Primeste un mesaj si blocheazǎ pânǎ când datele cerute sunt disponibile în bufferul de aplicatie din taskul receptor. MPI_Recv(&buf,count,datatype,source,tag,comm, &status) MPI_RECV(buf,count,datatype,source,tag,comm, status,ierr) MPI_Ssend. Trimitere sincronǎ cu blocare. Trimite un mesaj si blocheazǎ pânǎ când bufferul de aplicatie din taskul expeditor este liber pentru reutilizare si pânǎ când procesul destinatar a început primirea mesajului. MPI_Ssend (&buf,count,datatype,dest,tag,comm) MPI_SSEND (buf,count,datatype,dest,tag,comm,ierr) MPI_Bsend. Trimitere bufferizatǎ cu blocare: permite programatorului sǎ aloce spatiul necesar bufferului în care datele pot fi copiate/depuse pânǎ când sunt expediate. Fereste comunicarea de problemele asociate cu un spatiu al bufferului de sistem insuficient. Rutina revine dupǎ ce datele au fost copiate din spatiul bufferului de aplicatie în bufferul alocat trimiterii. Trebuie utilizatǎ cu rutina MPI_Buffer_attach. MPI_Bsend (&buf,count,datatype,dest,tag,comm) MPI_BSEND (buf,count,datatype,dest,tag,comm,ierr) MPI_Buffer_attach si MPI_Buffer_detach sunt utilizate de programator pentru alocarea/dealocarea spatiului pentru bufferul de mesaj utilizat de rutina MPI_Bsend. Argumentul size este specificat în bytes date actuale, nu ca un numǎr de elemente-date. Unui proces nu i se poate atasa mai multe buffere concomitent, ci unul singur. De notat cǎ implementarea IBM utilizeazǎ MPI_BSEND_OVERHEAD bytes ai bufferului alocat pentru overhead. MPI_Buffer_attach MPI_Buffer_detach MPI_BUFFER_ATTACH MPI_BUFFER_DETACH (&buffer,size) (&buffer,size) (buffer,size,ierr) (buffer,size,ierr) 114

115 MPI_Rsend. Trimitere ready cu blocare. Trebuie utilizatǎ numai atunci când programatorul este sigur cǎ perechea receive a fost deja postatǎ, este activǎ. MPI_Rsend (&buf,count,datatype,dest,tag,comm) MPI_RSEND (buf,count,datatype,dest,tag,comm,ierr) MPI_Sendrecv. Expediazǎ un mesaj si afiseazǎ un receive înainte de blocare. Blocheazǎ pânǎ când bufferul de aplicatie expeditor este liber pentru reutilizare si pânǎ când bufferul de aplicatie receptor contine mesajul receptionat. MPI_Sendrecv(&sendbuf,sendcount,sendtype,dest, sendtag,&recvbuf,recvcount,recvtype,source, recvtag,comm,&status) MPI_SENDRECV(sendbuf,sendcount,sendtype,dest, sendtag,recvbuf,recvcount,recvtype,source, recvtag,comm,status,ierr) MPI_Wait MPI_Waitany MPI_Waitall MPI_Waitsome. MPI_Wait blocheazǎ pânǎ când o operatie specificatǎ de trimitere sau primire fǎrǎ blocare este încheiatǎ. Pentru operatii fǎrǎ blocare multiple programatorul poate specifica un final oarecare, toate finalurile sau unele din finaluri. MPI_Wait (&request,&status) MPI_Waitany (count,&array_of_requests,&index, &status) MPI_Waitall (count,&array_of_requests, &array_of_statuses) MPI_Waitsome (incount,&array_of_requests,&outcount, &array_of_offsets, &array_of_statuses) MPI_WAIT (request,status,ierr) MPI_WAITANY (count,array_of_requests,index,status, ierr) MPI_WAITALL (count,array_of_requests, array_of_statuses,ierr) MPI_WAITSOME (incount,array_of_requests,outcount, array_of_offsets, array_of_statuses,ierr) MPI_Probe. Executǎ o testare a blocǎrii pentru un mesaj. Argumentele generale MPI_ANY_SOURCE si MPI_ANY_TAG pot fi utilizate pentru a testa un mesaj de la nu importǎ ce sursǎ la nu importǎ ce destinatie. Pentru rutina în C, se returneazǎ sursa si eticheta realǎ în structura de stare status, ca status.mpi_source si status.mpi_tag. Pentru rutina în Fortran, sursa si eticheta se returneazǎ în masivele întregi status(mpi_source) si status(mpi_tag). MPI_Probe (source,tag,comm,&status) MPI_PROBE (source,tag,comm,status,ierr) Exemple de rutine de transfer de mesaje cu blocare. Taskul 0 trimite un ping la taskul 1 si asteaptǎ returnarea unui ping. 115

116 În C: #include "mpi.h" #include <stdio.h> int main(argc,argv) int argc; char *argv[]; { int numtasks, rank, dest, source, rc, count, tag=1; char inmsg, outmsg='x'; MPI_Status Stat; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank == 0) { dest = 1; source = 1; rc = MPI_Send(&outmsg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD); rc = MPI_Recv(&inmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat); } else if (rank == 1) { dest = 0; source = 0; rc = MPI_Recv(&inmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat); rc = MPI_Send(&outmsg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD); } rc = MPI_Get_count(&Stat, MPI_CHAR, &count); printf("task %d: Received %d char(s) from task %d with tag %d \n", rank, count, Stat.MPI_SOURCE, Stat.MPI_TAG); MPI_Finalize(); } În Fortran: program ping 116

117 include 'mpif.h' integer numtasks, rank, dest, source, count, tag, ierr integer stat(mpi_status_size) character inmsg, outmsg outmsg = 'x' tag = 1 call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr) if (rank.eq. 0) then dest = 1 source = 1 call MPI_SEND(outmsg, 1, MPI_CHARACTER, dest, tag, & MPI_COMM_WORLD, ierr) call MPI_RECV(inmsg, 1, MPI_CHARACTER, source, tag, & MPI_COMM_WORLD, stat, ierr) else if (rank.eq. 1) then dest = 0 source = 0 call MPI_RECV(inmsg, 1, MPI_CHARACTER, source, tag, & MPI_COMM_WORLD, stat, err) call MPI_SEND(outmsg, 1, MPI_CHARACTER, dest, tag, & MPI_COMM_WORLD, err) endif call MPI_GET_COUNT(stat, MPI_CHARACTER, count, ierr) print *, 'Task ',rank,': Received', count, 'char(s) from task', & stat(mpi_source), 'with tag',stat(mpi_tag) call MPI_FINALIZE(ierr) end Rutine pentru transferul de mesaje fǎrǎ blocare Sunt descrise mai jos cele mai utilizate rutine pentru transferul de mesaje fǎrǎ blocare. MPI_Isend. Identificǎ o zonǎ de memorie care sǎ serveascǎ ca buffer de trimitere. Procesarea continuǎ imediat fǎrǎ asteptarea copierii mesajului din bufferul de aplicatie. Un handle de cerere de comunicare este returnat pentru a manipula starea (status) mesajului în derulare. Programul nu trebuie sǎ 117

118 modifice bufferul de aplicatie pânǎ când apelurile urmǎtoare la MPI_Wait sau la MPI_Test nu indicǎ încheierea acelei expedieri fǎrǎ blocare. MPI_Isend (&buf,count,datatype,dest,tag,comm, &request) MPI_ISEND (buf,count,datatype,dest,tag,comm, request,ierr) MPI_Irecv. Identificǎ o zonǎ din memorie care sǎ serveascǎ ca buffer de primire. Procesarea continuǎ imediat fǎrǎ a astepta ca mesajul sǎ fie primit si copiat în bufferul de aplicatie. Este returnat un handle pentru solicitarea de comunicare, pentru manipularea stǎrii mesajului în derulare. Programul trebuie sǎ utilizeze apeluri la la MPI_Wait sau la MPI_Test pentru a determina dacǎ operatia de primire fǎrǎ blocare s-a finalizat si mesajul cerut este disponibil în bufferul de aplicatie. MPI_Irecv (&buf,count,datatype,source,tag,comm, &request) MPI_IRECV (buf,count,datatype,source,tag,comm, request,ierr) MPI_Issend. Trimitere sincronǎ fǎrǎ blocare. Similarǎ cu MPI_Isend(), cu exceptia detaliului cǎ MPI_Wait() sau MPI_Test() indicǎ momentul când procesul destinatar a primit mesajul. MPI_Issend (&buf,count,datatype,dest,tag,comm, &request) MPI_ISSEND (buf,count,datatype,dest,tag,comm, request,ierr) MPI_Ibsend. Trimitere bufferizatǎ fǎrǎ blocare. Similarǎ cu MPI_Bsend() cu exceptia faptului cǎ MPI_Wait() sau MPI_Test() indicǎ momentul când procesul destinatar a primit mesajul. Trebuie utilizatǎ cu rutina MPI_Buffer_attach. MPI_Ibsend (&buf,count,datatype,dest,tag,comm, &request) MPI_IBSEND (buf,count,datatype,dest,tag,comm, request,ierr) MPI_Irsend. Trimitere ready fǎrǎ blocare. Similarǎ cu MPI_Rsend() cu deosebirea cǎ MPI_Wait() sau MPI_Test() indicǎ momentul când procesul destinatar a primit mesajul. Trebuie utilizatǎ numai dacǎ programatorul este sigur cǎ receive-ul pereche a fost deja postat. MPI_Irsend (&buf,count,datatype,dest,tag,comm, &request) MPI_IRSEND (buf,count,datatype,dest,tag,comm, request,ierr) MPI_Test MPI_Testany MPI_Testall MPI_Testsome. MPI_Test verificǎ statutul/starea unei operatii de trimitere sau de primire fǎrǎ blocare. Parametrul flag este returnat ca true (1) dacǎ operatia 118

119 s-a încheiat, sau ca false (0) dacǎ operatia nu s-a încheiat. Pentru operatii fǎrǎ blocare multiple, programatorul poate specifica any, all sau some adicǎ orice finalizare, toate finalizǎrile sau unele finalizǎri. MPI_Test (&request,&flag,&status) MPI_Testany (count,&array_of_requests,&index,&flag, &status) MPI_Testall (count,&array_of_requests,&flag, &array_of_statuses) MPI_Testsome (incount,&array_of_requests,&outcount, &array_of_offsets, &array_of_statuses) MPI_TEST (request,flag,status,ierr) MPI_TESTANY (count,array_of_requests,index,flag, status,ierr) MPI_TESTALL (count,array_of_requests,flag, array_of_statuses,ierr) MPI_TESTSOME (incount,array_of_requests,outcount, array_of_offsets, array_of_statuses,ierr) MPI_Iprobe. Executǎ un test fǎrǎ blocare pentru un mesaj. Identificatorii generali MPI_ANY_SOURCE si MPI_ANY_TAG pot fi utilizati pentru testarea unui mesaj din nu importǎ ce sursǎ sau care poartǎ indiferent ce etichetǎ. Parametrul întreg flag este returnat true (1) dacǎ un mesaj a sosit si false (0) dacǎ acesta nu a sosit. Pentru rutina în C, sursa realǎ si eticheta realǎ sunt returnate în structura de stare ca status.mpi_source si status.mpi_tag. Pentru rutina Fortran, ele sunt returnate în masivele intregi status(mpi_source) si status(mpi_tag). MPI_Iprobe (source,tag,comm,&flag,&status) MPI_IPROBE (source,tag,comm,flag,status,ierr) Exemple de rutine de transfer de mesaje: schimbarea cu vecinul cel mai apropiat în topologia circularǎ. În limbajul C: #include "mpi.h" #include <stdio.h> int main(argc,argv) int argc; char *argv[]; { int numtasks, rank, next, prev, buf[2], tag1=1, tag2=2; MPI_Request reqs[4]; MPI_Status stats[4]; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); MPI_Comm_rank(MPI_COMM_WORLD, &rank); 119

120 prev = rank-1; next = rank+1; if (rank == 0) prev = numtasks - 1; if (rank == (numtasks - 1)) next = 0; MPI_Irecv(&buf[0], 1, MPI_INT, prev, tag1, MPI_COMM_WORLD, &reqs[0]); MPI_Irecv(&buf[1], 1, MPI_INT, next, tag2, MPI_COMM_WORLD, &reqs[1]); MPI_Isend(&rank, 1, MPI_INT, prev, tag2, MPI_COMM_WORLD, &reqs[2]); MPI_Isend(&rank, 1, MPI_INT, next, tag1, MPI_COMM_WORLD, &reqs[3]); { do some work } MPI_Waitall(4, reqs, stats); MPI_Finalize(); } În Fortran: program ringtopo include 'mpif.h' integer numtasks, rank, next, prev, buf(2), tag1, tag2, ierr integer stats(mpi_status_size,4), reqs(4) tag1 = 1 tag2 = 2 call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr) prev = rank - 1 next = rank + 1 if (rank.eq. 0) then prev = numtasks - 1 endif if (rank.eq. numtasks - 1) then next = 0 endif 120

121 call MPI_IRECV(buf(1), 1, MPI_INTEGER, prev, tag1, MPI_COMM_WORLD, reqs(1), ierr) call MPI_IRECV(buf(2), 1, MPI_INTEGER, next, tag2, & MPI_COMM_WORLD, reqs(2), ierr) & call MPI_ISEND(rank, 1, MPI_INTEGER, prev, tag2, MPI_COMM_WORLD, reqs(3), ierr) call MPI_ISEND(rank, 1, MPI_INTEGER, next, tag1, & MPI_COMM_WORLD, reqs(4), ierr) & C do some work call MPI_WAITALL(4, reqs, stats, ierr); call MPI_FINALIZE(ierr) end Rutine de comunicare colectivǎ Comunicarea colectivǎ trebuie sǎ implice toate procesele din domeniul unui comunicator. Toate procesele sunt prin default membre ale comunicatorului MPI_COMM_WORLD. Este responsabilitatea programatorului a se asigura cǎ toate procesele dintr-un comunicator participǎ în orice operatie colectivǎ. Tipuri de operatii colective: Sincronizarea procesele asteaptǎ pânǎ când toate procesele membre ale grupului au atins punctul de sincronizare. Deplasǎri de date difuzare (broadcast), distribuire/colectare, toti-cu-toti. Calcule colective (reduceri) un membru al grupului colecteazǎ date de la ceilalti membri si executǎ o operatie (min, max, add, multiply etc.) asupra acelor date. Consideratii si restrictii la programare: Operatiile colective sunt blocante. Rutinele de comunicare colectivǎ nu preiau ca argumente etichete de mesaj. Operatiile colective într-un subset de procese sunt executate prin partitionarea prealabilǎ a subseturilor în grupe noi si apoi atasarea grupelor noi la comunicatori noi (ceea ce se discutǎ mai jos în sectiunea privind administrarea rutinelor de comunicare în grup si pe comunicator). Se pot utiliza numai cu tipurile MPI predefinite, nu cu tipurile MPI derivate. Rutinele de comunicare colectivǎ sunt prezentate sistematic imediat mai jos. 121

122 MPI_Barrier. Creazǎ o sincronizare cu barierǎ într-un grup. Când ajunge la apelul MPI_Barrier, fiecare task se blocheazǎ pânǎ când toate taskurile din grup ating acelasi apel la MPI_Barrier. MPI_Barrier (comm) MPI_BARRIER (comm,ierr) MPI_Bcast. Difuzeazǎ (trimite) un mesaj de la procesul cu rangul root tuturor celorlalte procese din grup. MPI_Bcast (&buffer,count,datatype,root,comm) MPI_BCAST (buffer,count,datatype,root,comm,ierr) MPI_Scatter MPI_Scatter. Distribuie mesaje distincte de la o singurǎ sursǎ fiecǎrui task din grup. MPI_Scatter (&sendbuf,sendcnt,sendtype,&recvbuf, recvcnt,recvtype,root,comm) MPI_SCATTER (sendbuf,sendcnt,sendtype,recvbuf, recvcnt,recvtype,root,comm,ierr) 122

123 MPI_Gather MPI_Gather. Colecteazǎ mesaje distincte de la fiecare task din grup pentru un singur task destinatie. Este o rutinǎ reciprocǎ fatǎ de rutina MPI_Scatter. MPI_Gather (&sendbuf,sendcnt,sendtype,&recvbuf, recvcount,recvtype,root,comm) MPI_GATHER (sendbuf,sendcnt,sendtype,recvbuf, recvcount,recvtype,root,comm,ierr) MPI_Allgather. Concatenarea de date (de) la toate taskurile din grup. Fiecare task din grup executǎ ca efect o operatie de difuzare unul-la-toate în cadrul grupului. MPI_Allgather (&sendbuf,sendcount,sendtype,&recvbuf, recvcount,recvtype,comm) MPI_ALLGATHER (sendbuf,sendcount,sendtype,recvbuf, recvcount,recvtype,comm,info) MPI_Reduce. Aplicǎ o operatie de reducere pe toate taskurile din grup si plaseazǎ rezultatul la un task. 123

124 MPI_Reduce (&sendbuf,&recvbuf,count,datatype,op, root,comm) MPI_REDUCE (sendbuf,recvbuf,count,datatype,op, root,comm,ierr) Operatiile de reducere MPI predefinite sunt date imediat mai jos. Utilizatorii pot defini ei însisi functii de reducere utilizând rutina MPI_Op_create. Operatia de reducere MPI Tipuri de date C Tipuri de date Fortran MPI_MAX maximum integer, float integer, real, complex MPI_MIN minimum integer, float integer, real, complex MPI_SUM sumǎ integer, float integer, real, complex MPI_PROD produs integer, float integer, real, complex MPI_LAND AND logic integer logical MPI_BAND AND bit-cu-bit integer, MPI_BYTE integer, MPI_BYTE MPI_LOR OR logic integer logical MPI_BOR OR bit-cu-bit integer, MPI_BYTE integer, MPI_BYTE MPI_LXOR XOR logic integer logical MPI_BXOR XOR bit-cu-bit integer, MPI_BYTE integer, MPI_BYTE MPI_MAXLOC Valoarea maximǎ si locatia float, double and long double real, complex,double precision MPI_MINLOC Valoarea minimǎ si locatia float, double and long double real, complex, double precision 124

125 MPI_Allreduce. Aplicǎ o operatie de reducere si plaseazǎ rezultatul la toate taskurile grupului. Este echivalentǎ cu un MPI_Reduce urmat de un MPI_Bcast. MPI_Allreduce (&sendbuf,&recvbuf,count,datatype, op,comm) MPI_ALLREDUCE (sendbuf,recvbuf,count,datatype, op,comm,ierr) MPI_Reduce_scatter. Mai întâi face o reducere element-cu-element pe un vector în toate taskurile din grup. Apoi vectorul rezultat este separat în segmente disjuncte si distribuit pe taskuri. Aceasta este echivalent cu un MPI_Reduce urmat de o operatie MPI_Scatter. MPI_Reduce_scatter (&sendbuf,&recvbuf,recvcount, datatype,op,comm) MPI_REDUCE_SCATTER (sendbuf,recvbuf,recvcount, datatype,op,comm,ierr) MPI_Alltoall. Fiecare task dintr-un grup executǎ o operatie de distribuire (scatter) trimitând un mesaj distinct tuturor taskurilor din grup ordonat prin indice. MPI_Alltoall (&sendbuf,sendcount,sendtype,&recvbuf, recvcnt,recvtype,comm) MPI_ALLTOALL (sendbuf,sendcount,sendtype,recvbuf, recvcnt,recvtype,comm,ierr) MPI_Alltoall MPI_Scan. Executǎ o operatie de scanare în raport cu o operatie de reducere pe un grup de taskuri. MPI_Scan (&sendbuf,&recvbuf,count,datatype,op,comm) MPI_SCAN (sendbuf,recvbuf,count,datatype,op,comm, ierr) 125

126 Exemple de comunicare colectivǎ: se executǎ o operatie de distribuire pe linii a unui masiv. În limbajul C: #include "mpi.h" #include <stdio.h> #define SIZE 4 int main(argc,argv) int argc; char *argv[]; { int numtasks, rank, sendcount, recvcount, source; float sendbuf[size][size] = { {1.0, 2.0, 3.0, 4.0}, {5.0, 6.0, 7.0, 8.0}, {9.0, 10.0, 11.0, 12.0}, {13.0, 14.0, 15.0, 16.0} }; float recvbuf[size]; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); if (numtasks == SIZE) { source = 1; sendcount = SIZE; recvcount = SIZE; MPI_Scatter(sendbuf,sendcount,MPI_FLOAT,recvbuf,recvcoun t, MPI_FLOAT,source,MPI_COMM_WORLD); printf("rank= %d Results: %f %f %f %f\n",rank,recvbuf[0], recvbuf[1],recvbuf[2],recvbuf[3]); } else printf("must specify %d processors. Terminating.\n",SIZE); MPI_Finalize(); } În Fortran: program scatter 126

127 include 'mpif.h' integer SIZE parameter(size=4) integer numtasks,rank,sendcount,recvcount,source,ierr real*4 sendbuf(size,size), recvbuf(size) C C Fortran stores this array in column major order, so the scatter will actually scatter columns, not rows. data sendbuf /1.0, 2.0, 3.0, 4.0, & 5.0, 6.0, 7.0, 8.0, & 9.0, 10.0, 11.0, 12.0, & 13.0, 14.0, 15.0, 16.0 / call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr) if (numtasks.eq. SIZE) then source = 1 sendcount = SIZE recvcount = SIZE call MPI_SCATTER(sendbuf,sendcount,MPI_REAL,recvbuf, & recvcount, MPI_REAL, source, MPI_COMM_WORLD, ierr) print *, 'rank= ',rank,' Results: ',recvbuf else print *, 'Must specify',size, ' processors. Terminating.' endif call MPI_FINALIZE(ierr) end Iesire ilustrativǎ a programului: rank= rank= rank= rank= Results: Results: Results: Results: Tipuri de date derivate Cum s-a mentionat mai devreme, MPI îsi predefineste tipurile de date primitive: 127

128 Tipuri de date în C Tipuri de date în Fortran MPI_CHAR MPI_SHORT MPI_INT MPI_LONG MPI_UNSIGNED_CHAR MPI_UNSIGNED_SHORT MPI_UNSIGNED_LONG MPI_UNSIGNED MPI_FLOAT MPI_DOUBLE MPI_LONG_DOUBLE MPI_BYTE MPI_PACKED MPI_CHARACTER MPI_INTEGER MPI_REAL MPI_DOUBLE_PRECISION MPI_COMPLEX MPI_DOUBLE_COMPLEX MPI_LOGICAL MPI_BYTE MPI_PACKED MPI dǎ posibilitatea programatorului sǎ defineascǎ propriile structuri de date bazate pe secvente ale tipurilor primitive de date MPI. Asemenea structuri definite de utilizator sunt numite tipuri derivate de date. Tipurile de date primitive sunt contigue, tipurile de date derivate permit specificarea de date necontigue într-o manierǎ convenabilǎ si utilizarea lor ca si când ar fi contigue. MPI furnizeazǎ mai multe metode de a construi tipuri derivate de date: contigue, vectori, indexate, structuri. Rutine pentru tipuri de date derivate MPI_Type_contiguous. Este cel mai simplu constructor. Produce un tip de date nou prin efectuarea unor cópii numǎrate ale unui tip existent de date. MPI_Type_contiguous (count,oldtype,&newtype) MPI_TYPE_CONTIGUOUS (count,oldtype,newtype,ierr) MPI_Type_vector MPI_Type_hvector. Similare rutinei contiguous, dar permit spatii regulate (stride3) în deplasare. MPI_Type_hvector si MPI_Type_vector sunt identice cu exceptia faptului cǎ pasul (stride) este specificat în bytes pentru prima dintre rutine. MPI_Type_vector (count,blocklength,stride,oldtype, &newtype) MPI_TYPE_VECTOR (count,blocklength,stride,oldtype, newtype,ierr) MPI_Type_indexed MPI_Type_hindexed. Este furnizat un masiv de deplasǎri pentru tipul de date 3 strided se spune despre o secventǎ de citiri sau scrieri ale memoriei la adrese separate fiecare de ultima printr-un interval constant numit lungimea-de-pas (the stride length) sau numai pasul (the stride). 128

129 de intrare, ca o hartǎ pentru noul tip de date. MPI_Type_hindexed este identic cu MPI_Type_indexed cu exceptia faptului cǎ offseturile sunt specificate în bytes. MPI_Type_indexed (count,blocklens[],offsets[], old_type,&newtype) MPI_TYPE_INDEXED (count,blocklens(),offsets(), old_type,newtype,ierr) MPI_Type_struct. Noul tip de date este format potrivit unei hǎrti complet definite de tipuri de date componente. MPI_Type_struct (count,blocklens[],offsets[], old_types,&newtype) MPI_TYPE_STRUCT (count,blocklens(),offsets(), old_types,newtype,ierr) MPI_Type_extent. Returneazǎ dimensiunea în bytes a tipului de date specificat. Util pentru subrutinele MPI care cer specificarea offsetului în bytes. MPI_Type_extent (datatype,&extent) MPI_TYPE_EXTENT (datatype,extent,ierr) MPI_Type_commit. Angajeazǎ tipuri de date noi pe sistem. Cerut de toate tipurile de date (derivate) construite de utilizator. MPI_Type_commit (&datatype) MPI_TYPE_COMMIT (datatype,ierr) MPI_Type_free. Dealocarea obiectului de tipul de date specificat. Utilizarea acestei rutine este de importantǎ specialǎ în prevenirea epuizǎrii memoriei când sunt create multe obiecte tip de date cum ar fi într-o buclǎ. MPI_Type_free (&datatype) MPI_TYPE_FREE (datatype,ierr) Exemple pentru tipul de date derivat Contiguous (contiguu): se creazǎ un tip de date care reprezintǎ o linie a unui masiv si se distribuie o linie diferitǎ tuturor proceselor. În C: #include "mpi.h" #include <stdio.h> #define SIZE 4 int main(argc,argv) int argc; char *argv[]; { int numtasks, rank, source=0, dest, tag=1, i; float a[size][size] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0}; 129

130 float b[size]; MPI_Status stat; MPI_Datatype rowtype; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); MPI_Type_contiguous(SIZE, MPI_FLOAT, &rowtype); MPI_Type_commit(&rowtype); if (numtasks == SIZE) { if (rank == 0) { for (i=0; i<numtasks; i++) MPI_Send(&a[i][0],1,rowtype,i,tag,MPI_COMM_WORLD); } MPI_Recv(b,SIZE,MPI_FLOAT,source,tag,MPI_COMM_WORLD, &stat); printf("rank= %d b= %3.1f %3.1f %3.1f %3.1f\n", rank,b[0],b[1],b[2],b[3]); } else printf("must specify %d processors. Terminating.\n",SIZE); MPI_Type_free(&rowtype); MPI_Finalize(); } În Fortran: program contiguous include 'mpif.h' integer SIZE parameter(size=4) integer numtasks, rank, source, dest, tag, i, real*4 a(0:size-1,0:size-1), b(0:size-1) integer stat(mpi_status_size), columntype C Fortran stores this array in column major order data a /1.0, 2.0, 3.0, 4.0, & 5.0, 6.0, 7.0, 8.0, & 9.0, 10.0, 11.0, 12.0, & 13.0, 14.0, 15.0, 16.0 / ierr 130

131 call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr) call MPI_TYPE_CONTIGUOUS(SIZE,MPI_REAL,columntype,ierr) call MPI_TYPE_COMMIT(columntype, ierr) tag = 1 if (numtasks.eq. SIZE) then if (rank.eq. 0) then do 10 i=0, numtasks-1 call MPI_SEND(a(0,i), 1, columntype, i, tag, & MPI_COMM_WORLD,ierr) 10 continue endif source = 0 call MPI_RECV(b, SIZE, MPI_REAL, source, tag, MPI_COMM_WORLD, stat, ierr) print *, 'rank= ',rank,' b= ',b & else print *, 'Must specify',size, ' processors. Terminating.' endif call MPI_TYPE_FREE(columntype, ierr) call MPI_FINALIZE(ierr) end Iesire ilustrativǎ a programului: rank= rank= rank= rank= b= b= b= b= Exemple pentru tipul derivat Vector: se creazǎ un tip de date care reprezintǎ o coloanǎ a unui masiv si se distribuie coloane diferite tuturor proceselor. În C: #include "mpi.h" #include <stdio.h> 131

132 #define SIZE 4 int main(argc,argv) int argc; char *argv[]; { int numtasks, rank, source=0, dest, tag=1, i; float a[size][size] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0}; float b[size]; MPI_Status stat; MPI_Datatype columntype; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); MPI_Type_vector(SIZE, 1, SIZE, MPI_FLOAT, &columntype); MPI_Type_commit(&columntype); if (numtasks == SIZE) { if (rank == 0) { for (i=0; i<numtasks; i++) MPI_Send(&a[0] [i],1,columntype,i,tag,mpi_comm_world); } MPI_Recv(b,SIZE,MPI_FLOAT,source,tag,MPI_COMM_WORLD, &stat); printf("rank= %d b= %3.1f %3.1f %3.1f %3.1f\n", rank,b[0],b[1],b[2],b[3]); } else printf("must specify %d processors. Terminating.\n",SIZE); MPI_Type_free(&columntype); MPI_Finalize(); } În Fortran: program vector include 'mpif.h' 132

133 integer SIZE parameter(size=4) integer numtasks,rank,source,dest,tag,i,ierr real*4 a(0:size-1,0:size-1), b(0:size-1) integer stat(mpi_status_size), rowtype C Fortran stores this array in column major order data a /1.0, 2.0, 3.0, 4.0, & 5.0, 6.0, 7.0, 8.0, & 9.0, 10.0, 11.0, 12.0, & 13.0, 14.0, 15.0, 16.0 / call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr) call MPI_TYPE_VECTOR(SIZE,1,SIZE,MPI_REAL,rowtype,ierr) call MPI_TYPE_COMMIT(rowtype, ierr) tag = 1 if (numtasks.eq. SIZE) then if (rank.eq. 0) then do 10 i=0, numtasks-1 call MPI_SEND(a(i,0), 1, rowtype, i, tag, & MPI_COMM_WORLD, ierr) 10 continue endif source = 0 call MPI_RECV(b, SIZE, MPI_REAL, source, tag, MPI_COMM_WORLD, stat, ierr) print *, 'rank= ',rank,' b= ',b & else print *, 'Must specify',size,' processors. Terminating.' endif call MPI_TYPE_FREE(rowtype, ierr) call MPI_FINALIZE(ierr) end Iesire ilustrativǎ a programului: rank= 0 b=

134 rank= 1 rank= 2 rank= 3 b= b= b= Exemple pentru tipul de date derivat Indexed: se creazǎ un tip de variabilǎ prin extragerea de portiuni dintr-un masiv si distribuindu-l tuturor taskurilor. În C: #include "mpi.h" #include <stdio.h> #define NELEMENTS 6 int main(argc,argv) int argc; char *argv[]; { int numtasks, rank, source=0, dest, tag=1, i; int blocklengths[2], displacements[2]; float a[16] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0}; float b[nelements]; MPI_Status stat; MPI_Datatype indextype; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); blocklengths[0] = 4; blocklengths[1] = 2; displacements[0] = 5; displacements[1] = 12; MPI_Type_indexed(2, blocklengths, MPI_FLOAT, &indextype); MPI_Type_commit(&indextype); displacements, if (rank == 0) { for (i=0; i<numtasks; i++) MPI_Send(a, 1, indextype, i, tag, MPI_COMM_WORLD); } MPI_Recv(b, NELEMENTS, MPI_COMM_WORLD, &stat); MPI_FLOAT, 134 source, tag,

135 printf("rank= %d b= %3.1f %3.1f %3.1f %3.1f\n", rank,b[0],b[1],b[2],b[3],b[4],b[5]); %3.1f %3.1f MPI_Type_free(&indextype); MPI_Finalize(); } În Fortran: program indexed include 'mpif.h' integer NELEMENTS parameter(nelements=6) integer numtasks, rank, source, dest, tag, i, integer blocklengths(0:1), displacements(0:1) real*4 a(0:15), b(0:nelements-1) integer stat(mpi_status_size), indextype data a & ierr /1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 / call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr) blocklengths(0) = 4 blocklengths(1) = 2 displacements(0) = 5 displacements(1) = 12 call MPI_TYPE_INDEXED(2,blocklengths,displacements,MPI_REAL, & indextype, ierr) call MPI_TYPE_COMMIT(indextype, ierr) tag = 1 if (rank.eq. 0) then do 10 i=0, numtasks-1 MPI_SEND(a,1,indextype,i,tag,MPI_COMM_WORLD,ierr) 10 continue endif source = call

136 call MPI_RECV(b,NELEMENTS,MPI_REAL,source,tag,MPI_COMM_WORLD, & stat, ierr) print *, 'rank= ',rank,' b= ',b call MPI_TYPE_FREE(indextype, ierr) call MPI_FINALIZE(ierr) end Iesire ilustrativǎ a programului: rank= rank= rank= rank= b= b= b= b= Exemple pentru tipul de date derivat Struct: se creazǎ un tip de date care reprezintǎ o particulǎ si se distribuie un masiv de astfel de particule tuturor proceselor. În C: #include "mpi.h" #include <stdio.h> #define NELEM 25 int main(argc,argv) int argc; char *argv[]; { int numtasks, rank, source=0, dest, tag=1, i; typedef struct { float x, y, z; float velocity; int n, type; } Particle; Particle p[nelem], particles[nelem]; MPI_Datatype particletype, oldtypes[2]; int blockcounts[2]; /* MPI_Aint type used to be consistent with syntax of */ /* MPI_Type_extent routine */ MPI_Aint offsets[2], extent; MPI_Status stat; 136

137 MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); /* Setup description of the 4 MPI_FLOAT fields x, y, z, velocity */ offsets[0] = 0; oldtypes[0] = MPI_FLOAT; blockcounts[0] = 4; /* Setup description of the 2 MPI_INT fields n, type */ /* Need to first figure offset by getting size of MPI_FLOAT */ MPI_Type_extent(MPI_FLOAT, &extent); offsets[1] = 4 * extent; oldtypes[1] = MPI_INT; blockcounts[1] = 2; /* Now define structured type and commit it */ MPI_Type_struct(2,blockcounts,offsets,oldtypes, &particletype); MPI_Type_commit(&particletype); /* Initialize the particle array and then send it to each task */ if (rank == 0) { for (i=0; i<nelem; i++) { particles[i].x = i * 1.0; particles[i].y = i * -1.0; particles[i].z = i * 1.0; particles[i].velocity = 0.25; particles[i].n = i; particles[i].type = i % 2; } for (i=0; i<numtasks; i++) MPI_Send(particles,NELEM,particletype,i,tag, MPI_COMM_WORLD); } MPI_Recv(p,NELEM,particletype,source,tag,MPI_COMM_WORLD, &stat); /* Print a sample of what was received */ printf("rank= %d %3.2f %3.2f %3.2f %3.2f %d %d\n",rank, p[3].x,p[3].y,p[3].z,p[3].velocity,p[3].n,p[3].type); 137

138 MPI_Type_free(&particletype); MPI_Finalize(); } În Fortran: program struct include 'mpif.h' integer NELEM parameter(nelem=25) integer numtasks, rank, source, dest, tag, i, integer stat(mpi_status_size) ierr type Particle sequence real*4 x, y, z, velocity integer n, type end type Particle type (Particle) p(nelem), particles(nelem) integer particletype, oldtypes(0:1), blockcounts(0:1), & offsets(0:1), extent call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr) C Setup description of the 4 MPI_REAL fields x, y, z, velocity offsets(0) = 0 oldtypes(0) = MPI_REAL blockcounts(0) = 4 C C Setup description of the 2 MPI_INTEGER fields n, type Need to first figure offset by getting size of MPI_REAL call MPI_TYPE_EXTENT(MPI_REAL, extent, ierr) offsets(1) = 4 * extent oldtypes(1) = MPI_INTEGER blockcounts(1) = 2 C Now define structured type and commit it call MPI_TYPE_STRUCT(2, blockcounts, offsets, oldtypes, & particletype, ierr) call MPI_TYPE_COMMIT(particletype, ierr) 138

139 C Initialize the particle array and then send it to each task tag = 1 if (rank.eq. 0) then do 10 i=0, NELEM-1 particles(i) = Particle ( 1.0*i, -1.0*i, 1.0*i, & 0.25, i, mod(i,2) ) 10 continue do 20 i=0, numtasks-1 call MPI_SEND(particles,NELEM,particletype,i,tag, & MPI_COMM_WORLD, ierr) 20 continue endif source = 0 call MPI_RECV(p, NELEM, particletype, source, tag, & MPI_COMM_WORLD, stat, ierr) print *, 'rank= ',rank,' p(3)= ',p(3) call MPI_TYPE_FREE(particletype, ierr) call MPI_FINALIZE(ierr) end Iesire ilustrativǎ a programului: rank= rank= rank= rank= Rutine de administrare a comunicatorului si a grupelor Grupe si comunicatori: O grupǎ este o multime ordonatǎ de procese. Fiecare proces dintr-un grup este asociat unui rang întreg unic. Valorile rangului pornesc de la 0 si merg pânǎ la N 1, unde N este numǎrul de procese din grup. În MPI, un grup este reprezentat în memoria sistemului ca un obiect. El este accesibil programatorului numai printr-un handle. Un grup este totdeauna asociat cu un obiect comunicator. Un comunicator cuprinde un grup de procese care pot comunica între ele. Toate mesajele MPI trebuie sǎ specifice un comunicator. În sensul cel mai simplu, comunicatorul este o etichetǎ suplimentarǎ care trebuie inclusǎ în apelurile MPI. Ca si grupele, comunicatorii sunt reprezentati în memoria sistemului ca obiecte si sunt accesibili programatorului numai prin handles. De exemplu, 139

140 un handle pentru comunicatorul care cuprinde toate taskurile este MPI_COMM_WORLD. Din perspectiva programatorului, un grup si un comunicator sunt totuna. Rutinele grupului sunt utilizate în principal pentru a specifica procesele care trebuie utilizate pentru a construi un comunicator. Scopurile principale ale obiectelor grup si comunicator: Permit organizarea taskurilor, pe baza unor functii, în grupuri de taskuri. Abiliteazǎ operatiile de comunicare colectivǎ într-un subset de taskuri într-un fel în relatie. Asigurǎ baza pentru implementarea topologiilor virtuale definite de utilizator. Asigurǎ siguranta comunicǎrii. Restrictii si alte consideratii asupra programǎrii: Grupurile/comunicatorii sunt obiecte dinamice pot fi create si distruse în timpul executiei programului. Procesele pot fi în mai mult de un grup/comunicator. Ele vor avea un rang unic în fiecare grup/comunicator. MPI contine peste 40 de rutine relativ la grupuri, comunicatori si topologii virtuale. Utilizǎri tipice: Extragere de handle al unui grup global din MPI_COMM_WORLD utilizând MPI_Comm_group. Formarea unui grup nou ca o submultime a unui grup global utilizând MPI_Group_incl. Crearea unui comunicator nou pentru un grup nou utilizând MPI_Comm_create. Determinarea unui rang nou într-un comunicator nou utilizând MPI_Comm_rank. Conducerea comunicǎrii utilizând orice rutinǎ MPI de transfer de mesaje. Când calculul se terminǎ, eliberarea comunicatorului nou si (optional) a grupului nou, utilizând MPI_Comm_free si MPI_Group_free. Rutine de administrare a grupurilor si a comunicatorilor Exemple: Sunt create douǎ grupuri de procese diferite pentru schimb separat de comunicare colectivǎ. Este cerutǎ si crearea de comunicatori noi. În C: #include "mpi.h" #include <stdio.h> #define NPROCS 8 140

141 int main(argc,argv) int argc; char *argv[]; { int rank, new_rank, sendbuf, recvbuf, numtasks, ranks1[4]={0,1,2,3}, ranks2[4]={4,5,6,7}; MPI_Group orig_group, new_group; MPI_Comm new_comm; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); if (numtasks!= NPROCS) { printf("must specify MP_PROCS= %d. Terminating.\n",NPROCS); MPI_Finalize(); exit(0); } sendbuf = rank; /* Extract the original group handle */ MPI_Comm_group(MPI_COMM_WORLD, &orig_group); /* Divide tasks into two distinct groups based upon rank */ if (rank < NPROCS/2) { MPI_Group_incl(orig_group,NPROCS/2,ranks1,&new_group); } else { MPI_Group_incl(orig_group,NPROCS/2,ranks2,&new_group); } /* Create new new communicator and then perform collective communications */ 141

142 MPI_Comm_create(MPI_COMM_WORLD, new_group, &new_comm); MPI_Allreduce(&sendbuf,&recvbuf,1,MPI_INT,MPI_SUM, new_comm); MPI_Group_rank (new_group, &new_rank); printf("rank= %d newrank= %d recvbuf= %d\n", rank,new_rank,recvbuf); MPI_Finalize(); } În Fortran: program group include 'mpif.h' integer NPROCS parameter(nprocs=8) integer rank, new_rank, sendbuf, recvbuf, numtasks integer ranks1(4), ranks2(4), ierr 142

143 integer orig_group, new_group, new_comm data ranks1 /0, 1, 2, 3/, ranks2 /4, 5, 6, 7/ call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr) if (numtasks.ne. NPROCS) then print *, 'Must specify MPROCS= ',NPROCS, ' Terminating.' call MPI_FINALIZE(ierr) stop endif sendbuf = rank C Extract the original group handle call MPI_COMM_GROUP(MPI_COMM_WORLD, orig_group, ierr) C Divide tasks into two distinct groups based upon rank if (rank.lt. NPROCS/2) then call MPI_GROUP_INCL(orig_group, NPROCS/2, ranks1, & new_group, ierr) else call MPI_GROUP_INCL(orig_group, NPROCS/2, ranks2, & new_group, ierr) endif call MPI_COMM_CREATE(MPI_COMM_WORLD, new_group, new_comm, ierr) call MPI_ALLREDUCE(sendbuf, recvbuf, 1, MPI_INTEGER, & MPI_SUM, new_comm, ierr) & call MPI_GROUP_RANK(new_group, new_rank, ierr) print *, 'rank= ',rank,' newrank= ',new_rank,' recvbuf= ', & recvbuf call MPI_FINALIZE(ierr) end Iesire a programului exemplificatoare: rank= rank= rank= rank= newrank= newrank= newrank= newrank= recvbuf= recvbuf= recvbuf= recvbuf=

144 rank= rank= rank= rank= newrank= newrank= newrank= newrank= recvbuf= recvbuf= recvbuf= recvbuf= Topologii virtuale Ce sunt aceste topologii? În termenii MPI, o topologie virtualǎ descrie o aplicatie/ordonare a proceselor MPI într-o formǎ geometricǎ. Cele douǎ tipuri principale de topologii suportate de MPI sunt cea cartezianǎ (grilǎ) si cea sub formǎ de graf. Topologiile MPI sunt virtuale poate sǎ nu existe nici o relatie între structura fizicǎ a unei masini paralel si topologia proceselor. Topologiile virtuale sunt construite pe grupuri si comunicatori MPI. Trebuie sǎ fie programate de cel care dezvoltǎ aplicatia. Care este utilitatea lor? Sunt convenabile. Topologiile virtuale pot fi utile pentru aplicatii cu forme de comunicare specifice forme (patterns) care se potrivesc unei structuri topologice MPI. De exemplu, o topologie cartezianǎ se poate dovedi convenabilǎ pentru o aplicatie care reclamǎ comunicare cu 4 din vecinii cei mai apropiati pentru date bazate pe grile. Eficienta comunicǎrii. Unele arhitecturi hardware pot exhiba penalitǎti pentru comunicarea între noduri succesive distante. O implementare particularǎ poate optimiza aplicarea (mapping) proceselor pe baza caracteristicilor fizice ale unei masini paralel date. Aplicarea de procese într-o topologie virtualǎ MPI este dependentǎ de implementarea MPI si poate fi ignoratǎ total. Exemplu: în figura de mai sus se dǎ o aplicare simplificatǎ a proceselor într-o topologie virtualǎ cartezianǎ. 144

145 Rutine de topologie virtualǎ Creazǎ o topologie cartezianǎ 4 4 din 16 procesoare si face ca fiecare proces sǎ schimbe rangul sǎu cu patru vecini. În C: #include "mpi.h" #include <stdio.h> #define SIZE 16 #define UP 0 #define DOWN 1 #define LEFT 2 #define RIGHT 3 int main(argc,argv) int argc; char *argv[]; { int numtasks, rank, source, dest, outbuf, i, tag=1, inbuf[4]={mpi_proc_null,mpi_proc_null,mpi_proc_null, MPI_PROC_NULL,}, nbrs[4], dims[2]={4,4}, periods[2]={0,0}, reorder=0, coords[2]; MPI_Request reqs[8]; MPI_Status stats[8]; MPI_Comm cartcomm; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); if (numtasks == SIZE) { MPI_Cart_create(MPI_COMM_WORLD, 2, dims, periods, reorder, &cartcomm); MPI_Comm_rank(cartcomm, &rank); MPI_Cart_coords(cartcomm, rank, 2, coords); MPI_Cart_shift(cartcomm, 0, 1, &nbrs[up], &nbrs[down]); MPI_Cart_shift(cartcomm, 1, 1, &nbrs[left], &nbrs[right]); outbuf = rank; for (i=0; i<4; i++) { dest = nbrs[i]; source = nbrs[i]; MPI_Isend(&outbuf, 1, MPI_INT, dest, tag, 145

146 MPI_COMM_WORLD, &reqs[i]); MPI_Irecv(&inbuf[i], 1, MPI_INT, source, tag, MPI_COMM_WORLD, &reqs[i+4]); } MPI_Waitall(8, reqs, stats); printf("rank= %d coords= %d %d neighbors(u,d,l,r)= %d %d %d %d\n",rank,coords[0],coords[1],nbrs[up], nbrs[down],nbrs[left],nbrs[right]); printf("rank= %d inbuf(u,d,l,r)= %d %d %d %d\n", rank,inbuf[up],inbuf[down],inbuf[left], inbuf[right]); } else printf("must specify %d processors. Terminating.\n",SIZE); MPI_Finalize(); } În Fortran: program cartesian include 'mpif.h' integer SIZE, UP, DOWN, LEFT, RIGHT parameter(size=16) parameter(up=1) parameter(down=2) parameter(left=3) parameter(right=4) integer numtasks,rank,source,dest,outbuf,i,tag,ierr, & inbuf(4),nbrs(4),dims(2), oords(2), & stats(mpi_status_size, 8), reqs(8), cartcomm, & periods(2), reorder data inbuf /MPI_PROC_NULL,MPI_PROC_NULL,MPI_PROC_NULL, & MPI_PROC_NULL/, dims /4,4/, tag /1/, & periods /0,0/, reorder /0/ call MPI_INIT(ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr) if (numtasks.eq. SIZE) then MPI_CART_CREATE(MPI_COMM_WORLD,2,dims,periods,reorder, & cartcomm,ierr) 146 call

147 call MPI_COMM_RANK(cartcomm, rank, ierr) call MPI_CART_COORDS(cartcomm,rank,2,coords,ierr) print *,'rank= ',rank,'coords= ',coords call MPI_CART_SHIFT(cartcomm,0,1,nbrs(UP), nbrs(down),ierr) call MPI_CART_SHIFT(cartcomm, 1, 1, nbrs(left), nbrs(right), & ierr) outbuf = rank do i=1,4 dest = nbrs(i) source = nbrs(i) call MPI_ISEND(outbuf,1,MPI_INTEGER,dest,tag, MPI_COMM_WORLD, reqs(i), ierr) call MPI_IRECV(inbuf(i),1,MPI_INTEGER,source,tag, MPI_COMM_WORLD, reqs(i+4), ierr) enddo & & call MPI_WAITALL(8, reqs, stats, ierr) print *,'rank= ',rank,' coords= ',coords, ' neighbors(u,d,l,r)= ',nbrs print *,'rank= ',rank,' ', ' inbuf(u,d,l,r)= ',inbuf & & else print *,'Must specify',size, ' processors. Terminating.' endif call MPI_FINALIZE(ierr) end Iesire (partialǎ) ilustrativǎ a programului: rank= rank= rank= rank= rank= rank= 0 coords= coords= coords= rank= rank= rank= rank= 14 coords= coords= neighbors(u,d,l,r)= -3 inbuf(u,d,l,r)= -3 4 neighbors(u,d,l,r)= -3 inbuf(u,d,l,r)= -3 5 neighbors(u,d,l,r)= -3 inbuf(u,d,l,r)= neighbors(u,d,l,r)= inbuf(u,d,l,r)= neighbors(u,d,l,r)= inbuf(u,d,l,r)=

148 Scurtǎ prezentare a MPI-2 Istorie: Deliberat, specificatiile MPI nu se ocupǎ de mai multe probleme dificile. Din ratiuni de expunere condensatǎ aceste probleme au fost rezervate pentru specificatia evoluatǎ MPI-2. În martie 1995, urmare a lansǎrii specificatiei initiale MPI, Forumul MPI a început discutarea îmbunǎtǎtirilor standardului MPI. Urmând acestuia: Decembrie 1995: conferinta Supercomputing 95 întâlnirea Birds of a Feather (dupǎ denumirea unui sitcom britanic de succes) pentru a discuta extensiile propuse pentru MPI. Noiembrie 1996: conferinta Supercomputing 96 s-a generat un proiect MPI2. S-a solicitat dezbaterea lui publicǎ. Întâlnire pentru a discuta extinderile interfetei MPI-2. Proiectul prezentat la Supercomputing 96 a devenit foarte curând standardul MPI-2, În prezent, cei mai multi producǎtori din aria HPC au numai implementǎri partiale ale MPI-2. Domenii cheie si functionalitǎti noi: Procese dinamice extinderi care înlocuiesc modelul procesului static al MPI. Furnizeazǎ rutine de creat procese noi. Comunicatii unilaterale furnizeazǎ rutine pentru comunicatii unidirectionale. Includ operatii cu memorie partajatǎ (put/get) si operatiuni de acumulare la distantǎ. Operatii colective extinse permite operatii colective fǎrǎ blocare si aplicatii ale operatiilor colective la inter-comunicatori. Interfete externe defineste rutine care permit dezvoltatorilor a pune straturi (layers) suplimentare peste MPI cum sunt programele de depanare (debuggers) si profilers. Noi legǎturi cu limbajele de programare descrie legǎturi în C++ si discutǎ probleme legate de Fortran-90. I/O paralel descrie suportul MPI pentru I/O paralel. Mai multe informatii despre MPI-2: pe site-ul The Argonne National Lab existǎ pagini dedicate informatiilor despre MPI-2. LLNL Lawrence Livermore National Laboratory Informatii specifice si recomandǎri Implementǎri MPI LC (Library Computer) suportǎ pe sistemele sale urmǎtoarele implementǎri MPI: 148

149 Platforme IBM AIX Implementǎri IBM MPI threaded library IBM MPI signal library MPICH Comentarii Recommended Not thread safe and not recommended. POWER3 systems only. Not thread safe. POWER3 systems only. Recommended. Uses shared memory for on-node communications and message Quadrics MPI passing over the Quadrics switch for inter-node communications. Not threadintel Linux safe On-node communications. Not thread MPICH shared safe. Only for machines without a memory Quadrics switch. Compaq MPI On-node communications. Use -pthread shared memory compile flag for thread-safety. MPICH shared On-node communications. Not thread COMPAQ memory safe Tru64 Inter-node communications. Not thread safe. Not recommeded due to lack of high MPICH P4 speed interconnect between nodes (no switch). Pe fiecare masinǎ sunt instalate versiuni multiple pentru fiecare implementare. Sunt suportate limbajele C, C++, Fortran 77 si Fortran 90. Compilare, linkare, rulare: Tabelul de mai jos cuprinde un sumar al comenzilor MPI de compilare/executie pentru toate sistemele LC. De retinut cǎ acesta este numai un rezumat, detaliile pot fi gǎsite prin consultarea surselor bibliografice. Platforma Implementǎri Compile/Link Run IBM AIX IBM MPI mpcc_r code.c threaded library mpxlc_r code.c mpguidec code.c mpcc_r code.c mpxlc_r code.c mpguidec++ code.c mpxlf_r code.f mpguidef77 code.f 149

150 mpxlf90_r code.f mpguidef90 code.f mpxlf95_r code.f Set required POE environment variables, then either: a.out args poe a.out args Or, use POE flags instead of environment variables: a.out args poe_args poe a.out args poe_args setenv LLNL_COMPILE_SINGLE_THREADED TRUE mpcc code.c mpxlc code.c mpcc code.c mpxlc code.c IBM MPI signal mpxlf code.f library mpxlf90 code.f (POWER3 mpxlf95 code.f systems only) Set required POE environment variables, then either: a.out args poe a.out args Or, use POE flags instead of environment variables: a.out args poe_args poe a.out args poe_args Intel Linux setenv LLNL_COMPILE_SINGLE_THREADED TRUE mpicc code.c MPICH mpicc code.c (POWER3 mpif77 code.f systems only) mpif90 code.f mpirun -nodes n -np p a.out args - OR setenv MP_NODES n mpirun -np p a.out args Quadrics MPI mpicc code.c (clusters with a mpiicc code.c 150

151 mpipgcc code.c mpicc code.c mpipgcc code.c mpif77 code.f Quadrics switch mpiifc code.f only) mpipgf77 code.f mpif90 code.f mpipgf90 code.f srun -n n -p partition a.out args mpicc code.c mpiicc code.c mpipgcc code.c MPICH shared mpicc code.c memory mpipgcc code.c (clusters without mpif77 code.f a Quadrics mpiifc code.f switch) mpipgf77 code.f mpif90 code.f mpipgf90 code.f mpirun -nodes n -np p a.out args cc code.c -lmpi -pthread gcc code.c -lmpi -pthread cxx code.c -lmpi -pthread Compaq MPI KCC code.c -lmpi -pthread shared memory g++ code.c -lmpi -pthread f77 code.f -lfmpi -lmpi -pthread f90 code.f -lfmpi -lmpi -pthread dmpirun -np p a.out args mpicc code.c mpicc code.c COMPAQ MPICH shared mpicxx code.c Tru64 memory mpif77 code.f mpif90 code.f mpirun -np p a.out args mpicc_p4 code.c mpicc_p4 code.c mpicxx_p4 code.c MPICH P4 mpif77_p4 code.f mpif90_p4 code.f mpirun_p4 -machinefile user_machine_file -np p a.out args 151

152 Variabile de mediu (environmemnt): Variabilele de mediu POE (Parallel Operating Environment) IBM: Variabilele de mediu POE joacǎ un rol critic în modul cum se comportǎ o aplicatie MPI pe toate sistemele ASC IBM. LLNL seteazǎ explicit mai multe din aceste variabile pe fiecare masinǎ ASC (Advanced Systems Center) IBM. Variabilele de mediu Elan (Emulated Local Area Network) pentru sistemele Linux: Quadrics MPI furnizeazǎ totodatǎ un numǎr de variabile de mediu, dintre care unele sunt setate automat de LC din ratiuni de performantǎ. 32 de biti fatǎ-n-fatǎ cu 64 de biti: De la retragerea sistemelor ASC Blue, toate SP-urile IBM de la LC sunt arhitecturi pe 64 de biti. Toate clusterele Linux IA32 sunt, desigur, arhitecturi pe 32 de biti. Thunder este o arhitecturǎ Itanium pe 64 de biti. Arhitecturile pe 64 de biti au spatiul adreselor de 64 de biti 18 miloane de terabytes. Arhitecturile pe 32 de biti rǎmân la cca. 4 Gbytes. Sistemele IBM POWER3 fac compilarea prin default pe 32 de biti. POWER4 si POWER5 fac compilarea prin default pe 64 de biti. Este probabil o idee bunǎ a utiliza la compilare flag-urile q64 sau q32 dacǎ default-ul nu este ceea ce trebuie. Obiectele pe 32 de biti si pe 64 de biti nu se pot amesteca. O aplicatie trebuie sǎ fie de de-a-ntregul ori una ori alta. Sunt probleme importante de luat în considerare la portabilitatea sau la dezvoltarea aplicatiilor pe 64 de biti. 152

153 MASINI PARALELE SI MODELE DE PROGRAMARE Figura alǎturatǎ ilustreazǎ o arhitecturǎ paralel genericǎ Unul din aspectele de detaliu îl reprezintǎ localizarea fizicǎ a memoriei. În figurǎ se pot observa memorii atasate procesoarelor si memoria în utilizare comunǎ tuturor procesoarelor. În ceea ce priveste modelele diverse de programare paralel trebuie avute în vedere mai multe aspecte: 1. Controlul, cu detalierea: Cum este creat paralelismul Ce ordine existǎ în executarea diferitelor operatii Cum se sincronizeazǎ firele de control (threads) diferite 2. Datele: Care date sunt private, care date sunt folosite în diviziune Cum sunt accesate sau comunicate logic datele în diviziune 3. Operatiile: Care sunt operatiile atomice, indivizibile 4. Costul: Cum se contabilizeazǎ costurile fiecǎrei pozitii din cele de mai sus Un exemplu simplu. Se considerǎ o sumǎ a valorilor unei functii de un masiv de n 1 date: f ( A[i ]). O descompunere paralel posibilǎ: i= 0 Fiecare evaluare si fiecare sumǎ partialǎ se constituie ca un task separat, se atribuie n/p numere fiecǎruia din cele p proces(oar)e Fiecare proces calculeazǎ si obtine rezultate independente si sume partiale private 153

154 Unul dintre procese (sau toate) colecteazǎ cele p sume partiale si calculeazǎ suma generalǎ Se disting douǎ clase de date: Date care sunt logic în diviziune numerele initiale (n) si suma generalǎ Date care sunt logic private, particulare rezultatele evaluǎrilor individuale ale functiei Dar ce se poate spune despre sumele partiale individuale? Sunt aici mai multe rǎspunsuri. Modelul de programare 1: Memorie în indiviziune (partajatǎ). Programul este o colectie de fire de control (threads) care sunt initiate de la bun început sau în unele limbaje pot fi create dinamic (mid-execution). Fiecare fir are un set de variabile private, de pildǎ variabilele din stiva localǎ. Existǎ, de asemenea, un set de variabile în indiviziune, partajate, de pildǎ variabilele statice, blocurile comune în indiviziune sau heap-ul global. Firele comunicǎ implicit prin scrierea si lectura variabilelor partajate si se coordoneazǎ pe aceste variabile prin sincronizare. Figura de mai sus este baza prezentǎrii unui scurt program (cod) cu memorie partajatǎ, pentru calculul unei sume 154

155 Apare problema unei competitii (a unei conditii race) pe variabila s din program. O conditie race sau data race apare când: Douǎ procesoare (sau douǎ fire) acceseazǎ aceeasi variabilǎ si cel putin unul face o scriere Accesǎrile sunt concurente (nu sunt sincronizate) astfel încât ele ar trebui sǎ aibǎ loc simultan Se admite cǎ s = 27, f(a[i]) = 7 pe firul 1 si f(a[i]) = 9 pe firul 2. Dacǎ programul lucreazǎ corect, s ar trebui sǎ fie la final 43, dar poate fi 43, 34 sau 36. Operatiile atomice sunt citirile si scrierile si niciodatǎ nu trebuie sǎ se vadǎ un numǎr numai pe jumǎtate. Toate calculele se produc în registre (private). Iatǎ acum un cod pentru calculul sumei de mai sus îmbunǎtǎtit. Deoarece adunarea este o operatie aritmeticǎ asociativǎ si comutativǎ, rearanjarea ordinei este oricând permisǎ. Cea mai mare parte a calculului se face în variabile private. Frecventa de utilizare partajatǎ aste si ea redusǎ, ceea ce ar putea mǎri viteza de calcul 155

156 Dar încǎ existǎ o conditie race la actualizarea variabilei partajate s Conditia race poate fi rezolvatǎ prin adǎugarea de interdictii (locks) cu precizarea cǎ numai un fir poate detine un lock la un moment; celelalte fire asteaptǎ pentru ca acel lock, acea interdicitie de acces sǎ fie deblocat(ǎ) (unlock). Modelul de programare 1a: Memorie în indiviziune (partajatǎ). Toate procesoarele sunt conectate la o memorie în indiviziune cuprinzǎtoare. Tipic, asemenea sisteme de calcul sunt denumite multiprocesoare simetrice (SMP Symmetric MultiProcessors). Existǎ în uz multe asemenea SMP-uri produse de Sun, HP, Intel, IBM etc. Memoria localǎ nu este (de obicei) parte separatǎ din hardware. Structura este dificil de scalat la numǎr mare de procesoare, tipic mai putin de 32 de procesoare. Avantajul major: acces uniform la memorie (UMA uniform memory access). Relativ la costuri: mult, mult mai ieftin accesul la date în memoria cache decât în memoria principalǎ. Figura urmǎtoare ilustreazǎ structura unui SMP (fǎrǎ a evidentia grafic simetria liminalǎ). Aceastǎ structurǎ are probleme cu scalarea memoriei partajate. Se pune firesc întrebarea, de ce nu se pun laolaltǎ mai multe procesoare (cu memorie mai mare)? Rǎspunsul: bus-ul memoriei devine loc îngust, este stangulant. Un exemplu de astfel de situatie îl furnizeazǎ aplicatia PSTSWM (Parallel Spectral Transform Shallow Water Model) dezvoltatǎ pentru a evalua algoritmii paralel pentru metoda transformǎrii spectrale asa cum este utilizatǎ în modelele globale de circulatie atmosfericǎ. În cod sunt încorporati algoritmi paraleli multipli, care pot fi selectati în timpul executiei în raport cu dimensiunea problemei, cu numǎrul de procesoare, cu descompunerea datelor. O sursǎ de detalii posibilǎ: Graficul care urmeazǎ prezintǎ performanta unei masini IBM p690 pe modelul PSTSW si sensibilitatea ei la încǎrcare. 156

157 Degradarea performantei este o functie netedǎ de numǎrul de proces(oar)e. Problema nu implicǎ nici un fel de date partajate între procese, astfel cǎ ar trebui sǎ existe un paralelism perfect. Codul a fost rulat pentru 18 niveluri verticale cu un domeniu (range) pe dimensiunea orizontalǎ fix. Model al masinii 1b: memoria partajatǎ este distribuitǎ. Memoria este logic în indiviziune dar fizic este distribuitǎ. Orice procesor poate accesa orice adresǎ din memorie. Liniile cache (sau paginile) sunt transferate peste tot (passed around) în masinǎ. Origin SGI (Silicon Graphics, Inc.) este exemplul canonic (la fel masinile de cercetare). Scalare la sute de ori Limitarea constǎ în protocoalele coerente din punctul de vedere al memoriilor cache: necesitǎ a detine pentru aceeasi adresǎ cópii în cache consistente Modelul de programare 2: transmiterea de mesaje. Programul constǎ într-o colectie de proces(oar)e cu nume. 157

158 Numele sunt fixate uzual la momentul pornirii programului Firul de control plus spatiul de adresare sunt locale datele sunt utilizate partajat NU (non uniform) Datele în indiviziune logicǎ sunt partitionate pe procese locale Procesele comunicǎ prin perechi de instructiuni explicite trimite/primeste (send/receive) Coordonarea este implicitǎ în fiecare eveniment comunicational MPI (Message Passing Interface) este exemplul cel mai comun Un exemplu simplu: calculul sumei s = A[1] + A[2] pe fiecare procesor. Prima solutie posibilǎ: Ce ar putea merge rǎu: Dacǎ send/receive actioneazǎ ca în sistemul telefonic? Dacǎ send/receive actioneazǎ ca prin oficiul postal? A doua solutie posibilǎ: Notǎ de traducere: se pare cǎ în firul procesorului 2 trebuie pus xlocal si nu xloadl. În 2002 MPI a devenit standardul de facto pentru calculul paralel. O provocare pentru producǎtorii de software: depǎsirea limitelor MPI MPI a creat finalmente un standard pentru dezvoltarea de aplicatii în comunitatea HPC (High Performance Computing) 158

159 Standardele sunt totdeauna un obstacol pentru continuarea dezvoltǎrilor Standardul MPI este o constructie ca un numitor comun minimal în raport cu tehnologia anilor 80 mijlocii Modelul de programare reflectǎ structura hardware. Nu sunt sigur cum voi programa un calculator de Petaflops, dar sunt sigur cǎ voi avea nevoie de MPI undeva HDS 2001 Modelul de masinǎ 2a: memorie distribuitǎ. Cray T3E, NOW, IBM SP2 IBM SP3, Millenium, CITRIS sunt masini cu memorie distribuitǎ dar nodurile sunt SMP-uri. Fiecare procesor are propria sa memorie si propriul sǎu domeniu cache dar nu poate accesa direct memoria vreunui alt procesor. Fiecare nod are o interfatǎ de retea (NI Network Interface) pentru toatǎ comunicarea si pentru sincronizare. Clusterele de PC-uri, contributiile de genul Beowulf reprezintǎ un experiment interesant în materie de sisteme de calcul în paralel. Se bazeazǎ pe o viziune de cost scǎzut pentru calcule cu final înalt. A demonstrat eficacitatea clusterelor de PC-uri pentru unele (nu toate) clase de aplicatii. A generat si a furnizat software de retea. A transferat rezultatele cǎtre o comunitate largǎ (great PR). A generat tutoriale si cǎrti. A generat standarde de proiectare pentru ralierea (rally) comunitǎtii celor care se ocupǎ cu calculul paralel, a generat cǎrti, oameni educati/priceputi, cu alte cuvinte un cerc virtuos. Fotografia alǎturatǎ aratǎ un cluster de PC-uri. 159

160 Adaptat dupǎ Gordon Bell, prezentare la Salishan Clusterele au creat modelul de software open source pentru HPC (High Performance Computing). Este de citat aici legea lui Linus, numitǎ dupǎ Linus Torvalds, creatorul Linux-ului, care afirmǎ cǎ pentru ochi suficienti, toate erorile sunt superficiale ( given enough eyeballs, all bugs are shallow ). Toate codurile sursǎ sunt deschise Fiecare structurǎ gen cluster este un loc de testare Orice porneste mult mai rapid dacǎ fiecare lucreazǎ pe un cod existent, la îndemânǎ (HPC: nimic nu se face dacǎ resursele sunt disperse). Software-ul este sau ar trebui sǎ fie gratuit (Stallman). Oricine poate oferi suport si poate comercializa codul pentru orice pret. Sofware-ul de cost nul atrage utilizatorii! Previne situatia în care comunitatea ar pierde sofware HPC (exemple CM5, T3E). Existǎ în lume clustere de Tflop/s. Iatǎ câteva exemple de clustere configurate din componente separate de retea si procesoare: Shell: clusterul de engineering/stiintific cel mai mare NCSA: cluster de 1024 de procesoare (IA64) Clusterul universitǎtii din Heidelberg PNNL: cluster de IA64 anuntat a fi de 8 Tflops (la vârf), alcǎtuit din HP cu interconectare Quadrics DTF în US: 4 clustere anuntate pentru un total de 13 Teraflops (la vârf) O mentiune necesarǎ: procesoarele Itanium si McKinley nu sunt produse de tipul commodity, adicǎ foarte ieftine Sunt de amintit aici si calculele executate pe Internet detalii la adresa SETI@home. Rularea ar putea avea loc pe PC-uri, aproximativ

161 CPU-an pe zi. Deocamdatǎ CPU-an. Sunt distribuite seturi de date de la radiotelescopul Arecibo (figura urmǎtoare). Pasul urmǎtor preconizat reteaua de telescoape Allen (figura de mai jos). Modelul de programare 2b: spatiu de adresare global. Programul constǎ într-o colectie de fire (threads) cu nume Uzual stabilite la momentul pornirii programului Datele sunt locale si partajate ca în modelul cu memorie partajatǎ Dar datele partajate sunt partitionate pe procese locale Modelele costului spun cǎ datele situate la distantǎ sunt costisitoare. Exemple: UPC, Titanium, CoArray Fortran Programarea cu spatiu de adresare globalǎ este un punct intermediar între transferul de mesaje si memoria în diviziune Modelul de masinǎ 2b: spatiul de adresare global. Exemple: Cray T3D, T3E, X1 si clusterul HP Alphaserver, Clusterele construite cu Quadrics, Myrinet sau Infiniband. 161

162 Interfata de retea suportǎ RDMA (Remote Direct Memory Access) NI (network interface) poate accesa direct memoria fǎrǎ întreruperea CPU Un procesor poate citi/scrie din/în memorie cu operatii unilaterale (put/get) Nu este numai o operatie load/store ca pe o masinǎ cu memorie partajatǎ Datele situate departe (remote) sunt tipic ne-cache-ate local Spatiul de adresare global poate fi suportat în grade diferite Modelul de programare 3: date paralel. Un singur fir al controlului care constǎ din operatii paralel. Operatiile paralel se aplicǎ întregii structuri de date (sau unui subset definit al acelei structuri), uzual unui masiv. Comunicarea este implicitǎ în operatorii paralel Modelul este elegant, usor de înteles si de a rationa asuprǎ-i Coordonarea este implicitǎ declaratiile (instructiunile) sunt executate sincron Similarǎ limbajului Matlab pentru operatii cu masive. Neajunsuri: Nu toate problemele se potrivesc în acest model Dificil de aplicat (to map) pe masini grosier organizate (coarse-grained) A = masivul tuturor datelor, fa = f(a), s = sum(fa) Modelul de masinǎ 3a: sisteme SIMD (Single Instruction Multiple Data) Un numǎr mare de procesoare (uzual) mici Un procesor de control unic genereazǎ fiecare instructiune Fiecare procesor executǎ aceeasi instructiune 162

163 Unele procesoare pot fi oprite (turned off) pentru unele instructiuni. Masinile sunt foarte specializate pe calculul stiintific, astfel cǎ nu sunt foarte populare printre distribuitori (CM2, Maspar) Modelul de programare poate fi implementat în compilator Aplicarea paralelismului se face n-uplu pe p procesoare, n>>p, dar este dificil (exemplu, HPF (High Performance Fortran)) Modelul 3b: masini vectoriale. Arhitecturile vectoriale sunt bazate pe un singur procesor Unitǎti functionale multiple Toate executǎ aceeasi operatie Instructiunile pot specifica prin ele însesi o cantitate mare de paralelism (de pildǎ 64 de cǎi) dar hardware-ul executǎ numai un subset în paralel Importante sub aspect istoric Preluate de MPP-uri în anii 90 Re-apǎrute în anii din urmǎ, recenti La o scarǎ mare în simulatorul terestru (NEC SX6) si Cray X1 La o scarǎ micǎ în extensiile media SIMD la microprocesoare SSE, SSE2 (Intel: Pentium, IA64) Altivec (IBM/Motorola/Apple: PowerPC) VIS (Sun: Sparc) Ideea cheie: compilatorul face o parte din munca dificilǎ de a gǎsi paralelism, astfel cǎ hardware-ul nu trebuie sǎ facǎ asta Procesoare vectoriale. Instructiunile vectoriale opereazǎ pe un vector de elemente Acestea sunt specificate ca operatii pe registre vectoriale Un registru vetorial al unui supercomputer retine ~ elemente 163

164 Numǎrul de elemente este mai mare decât cantitatea de hardware paralel, denumit pipes sau piste (lanes) vectoriale, sǎ spunem 2-4 Hardware-ul executǎ o operatie vectorialǎ completǎ în #elemente-pe-registru-vectorial / #pipes Nodul Cray X1. Cray X1 construieste un vector virtual mai mare, denumit un MSP (Multiprocessing Server Pack) 4 SSP-uri (Switch to Switch Protocol) (fiecare un procesor vectorial cu 2 pipe-uri) alcǎtuiesc un MSP Compilatorul va face (sau va încerca) vectorizarea/paralelizarea pe MSP Sursa figurii: J.Levesque, Cray Cray X1: arhitecturǎ vectorialǎ paralelǎ Cray combinǎ în X1 mai multe tehnologii Procesoare vectoriale de 12,8 Gflop/s (MSP) Cache-uri partajate (neuzuale în masinile vectoriale vechi/anterioare) Noduri de 4 procesoare care împart pânǎ la 64 GB de memorie Imaginea unui sistem unic pe 4096 procesoare Put/get de la distantǎ între noduri (mai rapid decât MPI) 164 mai

165 Arhitectura simulatorului terestru/global Arhitecturǎ vectorialǎ paralelǎ Procesoare vectoriale de mare vitezǎ Lǎrgime de bandǎ mare pentru memorie (arhitecturǎ vectorialǎ) Retea rapidǎ (comutare nouǎ crossbar) Rearanjarea pǎrtilor (la pret de commodity) nu poate atinge aceastǎ performantǎ Modelul de masinǎ 4: clustere de SMP-uri. SMP-urile sunt cele mai rapide masini la pret de commodity astfel cǎ ele sunt utilizate ca blocuri constructive pentru masini mai mari cu o retea de comunicare Nume obisnuite: CLUMP = clusters of SMP-uri 165

166 Masini ierarhizate, constelatii Multe masini moderne aratǎ în acest mod: Millenium, IBM SP-urile (dar nu T3E-urile) Care este modelul de programare potrivit pentru #4? Se trateazǎ masina ca platǎ ( flat ), se utilizeazǎ totdeauna transferul de mesaje, chiar în SMP-uri (simplu, dar ignorǎ o importantǎ parte din ierarhia memoriei) Memorie partajatǎ într-un SMP, dar transmitere de mesaje în afara unui SMP Tratarea ca un cluster de SMP-uri Un supercomputer este un server extrem de extins. Sistemul paralel este construit prin asamblarea de noduri care sunt de dimensiuni modeste, comerciale, servere SMP se pun mai multe laolaltǎ Imagine de la LLNL (Lawrence Livermore National Laboratory) Tendinte în lumea masinilor reale. TOP500 O listǎ a celor mai puternice 500 de calculatoare din lume. Jalonul: Rmax din Linpack pentru varianta densǎ a problemei Ax = b 166

167 Actualizat de douǎ ori pe an: În Germania ISC xy, în iunie xy În SUA SC xy, în noiembrie xy Toate datele acestea pot fi vǎzute pe site-ul 167

168 MASINI PARALELE CU MEMORIE PARTAJATǍ Arhitectura de bazǎ pentru calculul paralel pe memorie partajatǎ Procesoarele sunt conectate toate la o memorie cuprinzǎtoare partajatǎ, mai bine zis o memorie utilizatǎ în indiviziune. Fiecare procesor detine o memorie cache localǎ. Din punct de vedere al costurilor, adicǎ al consumurilor de timp, lucrul cu memoria cache este mai ieftin decât lucrul cu mempria principalǎ. În mediul cu memorie partajatǎ realizarea de programe este relativ usoarǎ. Ceva mai dificilǎ este scalarea4. Acum o privire mai îndeaproape la structurǎ, costuri, limite: Din perspectiva istoricǎ, masinile paralel cu memorie partajatǎ mentionabile sunt: Masinile bazate pe bus Pentium SMP Nodul IBM SP Masinile bazate pe directoare (CC-NUMA, Cache Coherent NonUniform Memory Access) Origin 2000 Masinile cu spatiu de adresare global Cray T3D si (genul) T3E 4 Scalabil este echivalent cu expandabil. Când se referǎ la hardware sau software, termenul are un sens întrucâtva diferit: un dispozitiv sau o aplicatie înalt scalabil(ǎ) înseamnǎ cǎ fǎrǎ eforturi exagerate face posibile utilizarea de mai multi utilizatori, încǎrcarea mai mare cu taskuri sau cu tranzactii. Scalabil nu înseamnǎ totdeauna cǎ expansiunea nu costǎ nimic. Pentru a obtine maximum de scalabilitate se cer uneori cheltuieli suplimentare cu hardware-ul sau software-ul. 168

169 Masinile multiprocesoare din anii '60 ai secolului trecut aveau structura din figura alǎturatǎ. Capacitatea de memorare sau posibilitatea de comunicare I/O se puteau ameliora prin adǎugarea de module de memorie si de dispozitive I/O. Cresterea capacitǎtii de procesare se putea realiza prin adǎugarea de procesoare. Apare deja necesitatea unei interconectǎri a modulelor de memorie si a procesoarelor, la fel a legǎturilor cu canalele I/O (IOC). Se foloseau retele de tip cross-bar sau multistage (multietajate). Memoriile cache, marea loviturǎ a anilor 70 au fost de naturǎ a influenta puternic structurile de memorare. Sistemele de memorie scalate prin adǎugarea de module suplimentare aveau nevoie si de capacitate dar si de vitezǎ (bandwidth). Memoria era totusi o sursǎ de strangulǎri. Introducerea memoriilor cache a schimbat aproape radical datele problemei. O memorie cache este capabilǎ a face douǎ lucruri foarte importante: 169

170 Reducerea timpului mediu de acces (latenţa) Diminuarea necesitǎtii de crestere a vitezei de transfer la si de la memorie. Cum aratǎ perspectiva tehnologicǎ? Tabelul care urmeazǎ indicǎ tendintele curente. Logica DRAM (Dynamic Random Access Memory) Discuri Cresteri de capacitate 2 ori la 3 ani Cresteri de vitezǎ 2 ori la 3 ani 4 ori la 3 ani 1,4 ori la 10 ani 2 ori la 3 ani 1,4 ori la 10 ani Variante de a construi masini paralele. În medalion este cuprinsǎ o masinǎ cu memoria partajatǎ din anii 80: memoria cache este partajatǎ. Asa erau: Alliant FX8 (în anii '80 timpurii) Opt procesoare Motorola cu crossbar si cache intercalat de 512 KB. Encore si Sequent produse de firmele cu aceleasi nume Primele microcalculatoare pe 32 de biti (N32032) Douǎ procesoare pe o placǎ cu cache în diviziune. 170

171 Figura urmǎtoare reia medalionul la dimensiuni care vizualizeazǎ mai bine detaliile. Avantajele si dezavantajele masinilor paralel cu memorie cache partajatǎ. Avantaje Amplasarea memoriei cache este identicǎ cu aceea a memoriei cache unicǎ. Se retine numai o copie a fiecǎrui bloc de cache. Granularitatea finǎ (fine grain) este posibilǎ Existenta unei interferente utile: un procesor poate pre-localiza date pentru un altul; se poate utiliza partajat date dintr-o linie de cache fǎrǎ a deplasa linia. Dezavantaje Apare o limitare de vitezǎ (bandwidth) Existǎ si o interferentǎ nedoritǎ: un procesor poate spǎla (flush) datele utile unui alt procesor. 171

172 Limitele solutiei cu cache partajat. Se presupune: procesorul generic (32 biţi) la 1 GHz fǎrǎ cache este capabil de o vitezǎ (BW) de 4 GB/s pentru instructiuni si de o vitezǎ (BW) de 1,2 GB/s pentru date la încǎrcare-memorare (load-store), ceea ce este o cotǎ de 30% din viteza pentru instructiuni. Un procesor necesitǎ asadar o vitezǎ pe bus de 5,2 GB/s. Banda de trecere (BW BandWidth) uzualǎ a unui bus este de circa 1 GB/s. Alternative constructive ale masinilor paralel 172

173 Un model intuitiv al memoriei spune cǎ citirea executatǎ la o adresǎ trebuie sǎ returneze ultima valoare scrisǎ la acea adresǎ. Cu exceptia operatiilor I/O aceastǎ relatie este usor de realizat în cazul procesorului unic. Problema coerentei memoriei cache în cazul masinilor cu mai multe procesoare (cu memorie partajatǎ) este mai delicatǎ si totodatǎ mai criticǎ din punct de vedere al performantelor. Mai riguros, aceasta este de fapt o consistentǎ secventialǎ: Un sistem multiprocesor este consistent secvential dacǎ rezultatul oricǎrei executii este acelasi ca si când operatiile tuturor procesoarelor ar fi executate într-o anume ordine secventialǎ si operatiile fiecǎrui procesor în parte apar în aceastǎ secventǎ în ordinea specificatǎ de programul executiei [Lamport, 1979] Intuirea consistentei secventiale Consistenta secventialǎ spune cǎ masina se comportǎ ca si când ar face operatiile din figura alǎturatǎ imediat mai sus. Semantica consistentei memoriei Ce implicatii are aceasta asupra comportǎrii programului? Nici un proces nu vede vreodatǎ valori gunoi, adicǎ jumǎtate din douǎ valori Procesoarele vǎd totdeauna valorile scrise de oricare alt procesor Valoarea vǎzutǎ este restrictionatǎ de ordinea programului consideratǎ pe toate procesoarele Timpul totdeauna se miscǎ, se scurge înainte Exemplu: P1 scrie data = 1, apoi scrie flag = 1 P2 citeste flag, apoi citeste data 173

174 Dacǎ P2 vede noua valoare a lui y, el trebuie sǎ vadǎ noua valoare a lui x Dacǎ nu existǎ o coerentǎ de cache-uri P1 si P2 au cópii ale datei în cache-uri (ca 0) P1 scrie data = 1 Poate scrie si în memorie ( write through ) P2 citeste data, dar ia copia din cache învechitǎ Asta se poate întâmpla chiar dacǎ a citit o valoare actualizatǎ a unei alte variabile, flag, care vine din memorie Protocoale de coerentǎ de cache (snoopy) iscoditoare 174

175 Bus-ul de memorie este un mediu de difuzare (broadcast). Cache-urile contin informatii despre ce adrese stocheazǎ ele. Controlul de cache snoops (spioneazǎ) toate tranzactiile de pe bus. O tranzactie este o tranzactie relevantǎ dacǎ implicǎ un bloc de cache continut la acel moment în acel cache Se iau mǎsuri de asigurare a coerentei Invalideazǎ, actualizeazǎ sau furnizeazǎ valori Depinde de starea blocului si de protocol Alegeri de bazǎ în coerenta cache-ului În cache se tin informatii de genul: Valid/invalid Murdar (dirty inconsistentǎ cu memoria) Partajate (în alte cache-uri) Când un procesor executǎ o operatie de scriere de date partajate, alegerile de basic design sunt: relativ la memorie: scrie through (pânǎ la capǎt): scrie si în memorie si în cache scrie back: asteaptǎ si scrie mai târziu, când item-ul este spǎlat (flushed) relativ la copiile cache celelalte: actualizeazǎ: dǎ tuturor celorlalte procesoare valoarea nouǎ invalideazǎ: toate celelalte procesoare scot din cache Exemplu: write-through invalidat 175

176 Actualizeazǎ si write-through ambele utilizate; mai multǎ vitezǎ (bandwidth) de memorie dacǎ existǎ scrieri la aceeasi adresǎ actualizeazǎ la celelalte cache-uri write-through la memorie Scheme write-back/ownership Când un singur cache are proprietatea unui bloc, scrierile procesorului nu rezultǎ în scrieri de pe bus, astfel conservând bandwidth. citirile de cǎtre altii produc revenirea blocului la starea shared Multe multiprocesoare de azi bazate pe bus utilizeazǎ astfel de scheme. Multe variante de protocoale pe bazǎ de proprietate (ownwership-based). Limitele memoriei partajate bazate pe bus Se presupune: procesor de 1 GHz fǎrǎ cache 4 GB/s BW pentru instructiuni pe fiecare procesor (32-bit) 1,2 GB/s BW pentru load-store date la 30%. Se admite o ratǎ de succes (hit rate) pentru instructiuni de 98% si o ratǎ de succes pentru date de 95% 80 MB/s BW pentru instructiuni la fiecare procesor 60 MB/s BW pentru date la fiecare procesor 140 MB/s BW combinatǎ. Admitând BW pentru bus de 1 GB/s, 8 procesoare satureazǎ bus-ul 176

177 Inginerie: Intel Pentium Pro Quad SMP-uri pentru mase: toatǎ coerenta si tot lipiciul multiprocesǎrii în modulul procesorului înalt integrat, cu tinta la volum mare latentǎ redusǎ si BW largǎ Inginerie: SUN Enterprise 177

178 Proc + mem card I/O card 16 plǎci de fiecare tip toatǎ memoria accesatǎ pe bus, deci simetric BW mai înaltǎ, bus de latentǎ mai mare Alternative constructive ale masinilor paralel Coerenta de cache bazatǎ pe director Multiprocesoare coerente cache, scalabile din anii

179 SGI Altix 3000 Un nod contine pânǎ la 4 procesoare Itanium 2 si 32GB de memorie. Reteaua este SGI s NUMAlink, tehnologie de interconectare NUMAflex. Utilizeazǎ un amestec de coerentǎ snoopy si directory-based. Pânǎ la 512 procesoare care sunt coerente cache (spatiul adreselor globale este posibil pentru masini mai mari). Coerenta cache si consistenta memoriei Coerenta cache si consistenta secventialǎ Multǎ muncǎ, mult hardware pentru a asigura coerenta cache. Niciodatǎ mai mult de o versiune de date pentru o adresǎ datǎ din cache Datele sunt totdeauna valori scrise de unul din procesoare 179

180 Dar alte particularitǎti hardware pot sparge consistenta secventialǎ (SC) Compilatorul reordoneazǎ/înlocuieste codul (de pildǎ your spin lock blocarea rotirii). Compilatorul alocǎ un registru pentru flag pe procesorul 2 si suceste (spins) valoarea pe acel registru fǎrǎ vreo finalitate. Scrie buffere (loc de stocare a scrierilor în timp ce este asteptat finalul. Procesoarele pot reordona scrierile pentru a unifica (to merge) adrese (not FIFO). Scrie x =1, y = 1, x = 2 (al doilea write în x se poate produce înaintea write-ului în y). Instructiunile de prelocalizare (prefetch) produc reordonarea citirii (citire de date înainte de flag). Reteaua reordoneazǎ cele douǎ mesaje de scriere. Scrierea în flag este în apropiere, in timp ce data este departe. Unele din acestea pot fi prevenite prin declararea de variabile volatile. Violǎri ale consistentei secventiale (SC) Programul flag/data este un exemplu care se bazeazǎ pe SC. Fiind datǎ o memorie coerentǎ, toate violǎrile de SC bazate pe reordonare a operatiilor independente sunt în figurǎ. Vezi articolul lui Shasha si Snir pentru detalii Operatiile pot fi liniarizate (deplaseazǎ timpul înainte) dacǎ SC Conditii suficiente pentru consistentǎ secventialǎ Procesoarele lanseazǎ operatii cu memoria în ordinea din program. Procesorul asteaptǎ pentru store a se finaliza înainte de a lansa orice altǎ operatie cu memoria. De pildǎ, asteaptǎ pentru write-through si invalidǎri. Procesorul asteaptǎ pentru load a se finaliza înainte de a lansa orice altǎ operatie cu memoria. 180

181 De pildǎ, data din alt cache poate cǎ trebuie marcatǎ ca partajatǎ mai curând decât exclusivǎ Un load trebuie sǎ astepte de asemenea pentru ca store-ul care produce valoarea sǎ se isprǎveascǎ De pildǎ, dacǎ data este în cache si evenimentul update schimbǎ valoarea, toate celelalte cache-uri trebuie sǎ fi procesat de asemenea acel update Existǎ si modalitǎti mai agresive de a implementa SC, dar cele mai multe SMPuri comerciale curente renuntǎ (give up) la asemenea metode Clasificare pentru modele relaxate Optimizǎrile pot fi în general categorisite prin Relaxarea ordinei din program Write Read Write Write Read Read, Write Citeste write-ul altora mai întâi Citeste propriul write mai întâi Toate modelele asigurǎ o plasǎ de sigurantǎ (safety net), de pildǎ O instructiune gard de write asteaptǎ ca write-urile sǎ fie complete O gard de read previne prelocalizǎrile de a se deplasa înaintea acestui punct Prelocalizǎrile (prefetches) pot fi sincronizate automat la utilizare Toate modelele mentin dependentele de date si de control uniprocesor, serializarea de write Modelele de memorie diferǎ prin ordine la douǎ locatii diferite Slide source: Sarita Adve et al. Câteva modele curente centrate pe sistem (system-centric) 181

182 Data-race-free-0: unele definitii (se considerǎ executii SC ordine totalǎ globalǎ) Competitie (race) pentru douǎ operatii în conflict dacǎ De la procesoare diferite Se executǎ una dupǎ alta (consecutiv) Competiile (races) etichetate uzual ca sincronizǎri, altii date. Se pot optimiza operatii care niciodatǎ nu vin în competitie. Programarea cu modele de memorie slabe Câteva reguli de programare cu aceste modele evitati conditiile de competitie (race) utilizati primitive de sincronizare furnizate de sistem dacǎ aveti conditii de competitie pe variabile, faceti-le volatile la nivel de asamblare puteti utiliza direct garduri (fences) (sau analoagele) 182

183 Suportul pentru acestea în limbajele de nivel înalt diferǎ. primitivele de sincronizare built-in includ în mod normal operatiile fence necesare lock: include un fence la read unlock: include un fence de write astfel toate operatiile cu memoria se petrec în regiunea criticǎ. Memorie în diviziune cache-coerentǎ si performanta Cache-uri în calculul stiintific Cache-urile tind sǎ lucreze foarte prost pe aplicatii solicitante care opereazǎ pe seturi de date voluminoase procesarea tranzactiilor sistemele de operare matrici rare Codurile stiintifice moderne uzeazǎ de tiling/blocking pentru a deveni cachefriendly mai usor pentru codurile dense decât pentru cele rare tiling-ul si paralelismul sunt transformǎri similare Utilizarea partajatǎ (sharing): o problemǎ de performantǎ Partajarea adevǎratǎ: write-uri frecvente pe o variabilǎ poate crea loc îngust, strangulǎri OK pentru date read-only sau care se scriu infrecvent, rar Technicǎ: se fac cópii ale valorii, una pe fiecare procesor, dacǎ aceasta e posibilǎ în algoritm Problemǎ exemplificatoare: structura de date care înmagazineazǎ freelist/heap pentru malloc/free Partajare falsǎ: Blocul de cache poate de asemenea sǎ introducǎ artefacte Douǎ variabile distincte în acelasi bloc de cache Tehnicǎ: se alocǎ datele utilizate de fiecare procesor în mod contiguu sau cel putin cu evitarea intercalǎrii Problemǎ exemplu: un masiv de întregi, unul scris frecvent de fiecare procesor Ce este de retinut? Programarea masinilor cu memorie partajatǎ: 183

184 Se pot aloca date în regiuni mari partajate fǎrǎ prea mari griji asupra locului unde sunt Ierarhia memoriei este criticǎ pentru performantǎ Chiar mai mult decât pe uniprocesoare, din cauza coerentei de trafic Pentru reglarea (tuning) performantei se urmǎreste partajarea atât cea adevǎratǎ cât si cea falsǎ Semanticǎ: Necesitǎ a bloca (lock) aceesul la variabile partajate pentru readmodify-write Consistenta secventialǎ este semantica naturalǎ Arhitectii lucreazǎ din greu pentru a face asta sǎ lucreze Cache-urile sunt coerente cu bus-urile sau directoarele Nu cache-uri pentru date depǎrtate pe masinile cu spatiu de adresare partajat Dar compilatorul si procesorul pot încǎ s-o scoatǎ la cap Write-urile non-blocking, read-urile prelocalizate, miscarea codului A se evita competitia (races) sau a se utiliza cu grijǎ gardurile specifice masinii 184

185 CALCULATOARE CU MEMORIE DISTRIBUITǍ Perspectiva istoricǎ La început masinile erau: Colectii de microprocesoare Comunicarea era executatǎ utilizând legǎturi bidirectionale între vecinii cei mai apropiati Mesajele erau înaintate de procesoare pe o cale (path) Retelizare era de tipul Memoreazǎ si înaiteazǎ, trimite mai departe În algoritmi exista un accent puternic pe topologie pentru a minimiza numǎrul de sǎrituri (hops) de la un nod la altul. Analogia cu retelele Pentru a avea un numǎr mare de transferuri care se petrec deodatǎ, este necesar un numǎr mare de fire distincte Retelele sunt ca strǎzile: Link = stradǎ Switch = intersectie Distante (salturi = hops) = numǎrul de blocks (cvartaluri) parcurse Algoritm de rutare = plan de cǎlǎtorie Proprietǎti: Latenţǎ: cât ia parcursul între noduri în retea 185

186 Bandwidth (BW): ce cantitate de date poate fi deplasatǎ în unitatea de timp BW este limitatǎ de numǎrul de fire si de viteza la care fiecare fir poate accepta datele Caracteristicile unei retele Topologia (cum sunt conectate lucrurile) Crossbar, ring, tor 2D si 3D, hipercuburi, retele omega Algoritmul de rutare: Exemplu: totul est-vest apoi totul nord-sud (evitǎ blocajele) Strategia de comutare: Comutare de circuit: calea completǎ rezervatǎ pentru întregul mesaj, ca la telefon Comutare în pachete: mesajul spart în pachete rutate separat, ca la oficiul postal Controlul traficului (ce se întâmplǎ dacǎ se produce o congestie, un ambuteiaj): Opreste, depune datele temporar în buffere, re-ruteazǎ datele cǎtre alte noduri, spune nodului sursǎ sǎ se opreascǎ temporar, decarteazǎ etc. Proprietǎti ale unei retele: latenţǎ Diametru: maximul (pe toate perechile de noduri) celui mai scurt drum între o pereche de noduri Latenţǎ: întârzierea între momentele de trimitere si de primire Latenta tinde sǎ varieze larg cu arhitecturile Distribuitorii raporteazǎ adesea latenta hardware (timpul firelor) Programatorii de aplicatii se preocupǎ de latenta software (program utilizator la program utilizator) Observatii: Latentele hardware/software diferǎ adesea cu 1-2 ordine de mǎrime Latenta maximǎ hardware variazǎ cu diametrul, dar variatia în latenta software este uzual neglijabilǎ Latenta este importantǎ pentru programele cu multe mesaje de mici dimensiuni. Proprietǎtile unei retele: bandwidth (BW) O retea este partitionatǎ în douǎ sau mai multe subgrafuri disjuncte dacǎ unele noduri nu pot ajunge la altele. Lǎrgimea de bandǎ (BW) este o valoare link = w*1/t w este numǎrul de fire unidirectional sau bidirectional 186

187 t este timpul pe bit BW este tipic în Gigabytes (GB), adicǎ, 8*220 biti. BW efectivǎ este uzual mai jos decât BW a legǎturii fizice din cauza overheadului de pachet. BW este importantǎ pentru aplicatii în care cele mai multe mesaje sunt de mare dimensiune. Proprietǎti ale unei retele: BW la bisectie BW la bisectie: BW de-a curmezisul celei mai mici tǎieturi care divide reteaua în douǎ pǎrti egale. BW de-a curmezisul pǎrtii celei mai înguste a retelei. BW la bisectie este importantǎ pentru algoritmii în care toate procesoarele trebuie sǎ comunice cu toate celelalte. Topologia retelei În trecut, a existat o cercetare de volum considerabil în ceea ce priveste topologia retelelor si algoritmii de aplicare (mapping) pe topologie costul cheie de minimizat: numǎrul de hops între noduri (care fac store and forward ) retelele moderne ascund costul de hop (prin rutarea wormhole ), astfel cǎ topologia nu mai este un factor major în performanta algoritmului 187

188 Exemplu: pe un sistem IBM SP, latenta hardware variazǎ de la 0,5 µs la 1,5 µs, dar latenta transmiterii mesajelor la nivelul utilizatorului este, grosier vorbind, 36 µs. Este necesarǎ o bazǎ în topologia retelelor algoritmii pot avea o topologie a comunicǎrii topologia afecteazǎ BW la bisectie Topologii liniare si circulare Retea liniarǎ diametru = n 1; distanta medie ~n/3 BW la bisectie = 1 (unitǎtile sunt BW de link) Toruri sau cercuri Diametru = n/2; distanta medie n/4 BW la bisectie = 2 Naturalǎ pentru algoritmi care lucreazǎ cu masive 1D Site (meshes) si toruri Sita bidimensionalǎ Diametrul = 2*(sqrt(n) 1) BW la bisectie = sqrt(n) Toruri bidimensionale Diametrul = sqrt(n) BW la bisectie = 2*sqrt(n) 188

189 Se generalizeazǎ la dimensiuni mai mari (Cray T3D utilizeazǎ torul 3D). Naturale pentru algoritmi care lucreazǎ pe masive de date 2D si/sau 3D. Hipercuburi Numǎrul de noduri n = 2d, cu d dimensiunea Diametrul = d BW la bisectie = n/2 Popularǎ în masinile timpurii (Intel ipsc, NCUBE). Multi algoritmi inteligenti (clever) Vezi Notele la CS267 din 1996 Adresarea prin coduri Greycode. Fiecare nod conectat la alte d noduri cu un bit diferit 189

190 Arbori Diametru = logn BW la bisectie = 1 Asezare facilǎ ca un graf plan. Multi algoritmi arborescenti (de pildǎ însumarea) Arborii grasi (fat trees) evitǎ problema BW la bisectie: Mai multe (sau mai largi) legǎturi aproape de top Exemplu: Thinking Machines CM-5 Fluturi Diametru = logn BW la bisectie = n Cost: multe fire Utilizatǎ în BBN Butterfly un supercalculator dezvoltat de BBN Technologies, denumit dupǎ reteaua de comutare în trepte, de tip fluture, piesa centralǎ a constructiei. Poate avea pânǎ la 512 CPU conectate pentru a permite acesul fiecǎrei CPU la toate celelalte CPU, dar cu o latentǎ de circa 15 ori mai mare decât propria latentǎ. Modelele mai vechi GP-1000 foloseau

191 de procesoare Motorola 68020, modelele mai recente TC-2000 utilizeazǎ pânǎ la 512 procesoare Motorola Naturalǎ pentru FFT (Fast Fourier Transform). Topologii în masini reale Multe din acestea sunt aproximǎri: de pildǎ, masina Cray X1 este în realitate un hipercub cu pǎtrate rigidizate ( quad bristled hypecube ) si unii din arborii grasi nu sunt atât de grasi pe cât ar trebui la vârf. 191

192 Evolutia masinilor cu memorie distribuitǎ Conexiuni ale unor cozi speciale sunt înlocuite prin acces direct la memorie (DMA direct memory access). Procesorul împacheteazǎ sau copiazǎ mesajele Initializeazǎ transfer, merge mai departe cu calculul Bibliotecile de transfer de mesaje furnizeazǎ scheme store-and-forward: Pot trimite/receptiona între orice pereche de noduri, nu numai de-a lungul unui fir Timpul este proportional cu distanta deoarece fiecare procesor de pe o cale trebuie sǎ participe la transfer Rutarea wormhole în hardware Procesoare speciale de mesaje care nu întrerup procesoarele principale pe acea cale Trimiterile de mesaje sunt în stilul pipeline Procesoarele nu asteaptǎ pentru a isprǎvi un mesaj înainte de a înainta (forwarding) un altul Modele ale performantei PRAM Parallel Random Access Memory Toate operatiile de acces la memorie sunt complete într-o perioadǎ a ceasului conceptul de memorie ierarhizatǎ absent ( too good to be true ) OK pentru a întelege dacǎ un algoritm are suficient paralelism (at all) Strategia de proiectare a algoritmilor paraleli: mai întâi faci algoritmul PRAM, apoi te preocupi de timpul de memorie/comunicare (ceea ce uneori merge) Ceva mai realist: PRAM Concurrent Read Exclusive Write (CREW) Modelul latentei si BW Timpul de trimitere a unui mesaj de lungime n este, grosier vorbind: Timpul = latenta + n*costul_per_cuvânt (word) = latenta + n/bw Topologia este presupusǎ irelevantǎ. Adesea denumit modelul α β si scris ca Timpul = α + n*β Uzual, α >> β >> timpul per flop Un mesaj lung este mai ieftin decât mai multe scurte 192

193 α + n*β << n*( α + 1*β) Se pot face sute sau mii de flops în costul unui singur mesaj Lectie de retinut: e necesar un raport mare calcul-pe-comunicare pentru a fi eficient. Parametri α si β pe masini contemporane: α este în µs, β este în µs per Byte Aceste numere au fost obtinute empiric. Cât de bine prezice modelul Timpul = α + n*β performanta realǎ? Diagrame cu BW Date de la Mike Welcome NERSC 193

194 Model dimensiunea mesajului cu timp variabil & masini Timpul mesajului mǎsurat Parametrii logp: overhead & latentǎ 194

195 Costul fǎrǎ suprapunere Costul cu suprapunere Parametri logp: gap. The gap este intervalul între trimiterea de mesaje. The gap poate fi mai mare decât overhead-ul trimiterii NIC (Network Interface Card) poate fi ocupat cu finalizarea procesǎrii ultimului mesaj si nu poate accepta unul nou Controlul fluxului sau presiunea din spate pe retea poate preveni/opri NIC-ul sǎ accepte urmǎtorul mesaj de trimis The gap reprezintǎ inversul BW a retelei pentru trimiteri de mesaje mici. Rezultate: EEL si overheadul 195

196 Date de la Mike Welcome NERSC Limitǎri ale modelului logp Modelul logp are un cost fixat pentru fiecare mesaj. Aceasta-i utilǎ în a arǎta cum se iuteste difuzarea (broadcast) unui singur word Alte exemple si în articolele (despre) logp Pentru mesaje mai mari, existǎ o variatie loggp Doi parametri de gap, unul pentru mesaje mici, altul pentru mesaje mari Gap-ul pentru un mesaj mare este β din modelul anterior Nu se ia în considerare topologia (se ignorǎ limitele pentru BW de bisectie) Se presupune o retea complet conectatǎ Pentru unii algoritmi cu comunicare cu vecinul cel mai apropiat, dar cu comunicare toti-cu-toti aceasta se cere a fi rafinatǎ suplimentar Acesta este un model plat, adicǎ fiecare procesor este conectat la retea. Clusterele de SMP-uri nu sunt modele precise/potrivite Tendinte în masinile noi Latenţa cap la cap în timp Latenţa nu s-a îmbunǎtǎtit semnificativ în timp. T3E (memorie partajatǎ) era punctul cel mai de jos Federation în 2003 nu va atinge acel nivel 7 ani mai târziu! 196

197 Date de la Kathy Yelik, UCB si NERSC Overhead pentru trimitere în timp Overhead-ul nu s-a îmbunǎtǎtit semnificativ; T3D a fost cel mai bun Lipsǎ de integrare; lipsǎ de atentie în software Date de la Kathy Yelik, UCB si NERSC Implementarea transferului de mesaje sincron 197

198 Operatiile send complete dupǎ potrivirea lui receive si dupǎ ce datele sursǎ au fost trimise Operatiile receive complete dupǎ ce transferul de date este complet de la send pereche Exemplu: permutarea de date Schimbare de date între procesoarele 0 si 1, versiunea 1: ce merge rǎu? Procesorul 0 send(1, item0, 1, tag1) recv(1, item1, 1, tag2) Procesorul 1 send(0, item1, 1, tag2) recv(0, item0, 1, tag1) Blocare! Schimbare de date între procesoarele 0 si 1, versiunea 2: Procesorul 0 send(1, item0, 1, tag1) recv(1, item1, 1, tag2) Procesorul 1 recv(0, item0, 1, tag1) send(0, item1, 1, tag2) Dar ce se întâmplǎ la o permutare generalǎ, când procesorul j vrea sǎ trimitǎ la procesorul s(j), când s(1), s(2),, s(p) este o permutare de 1, 2,, P? Implementarea transmiterii de mesaje asincronǎ Protocolul optimist într-o singurǎ fazǎ presupune cǎ destinatia poate la cerere sǎ tinǎ datele într-un buffer 198

199 Transmitere de mesaje asincronǎ sigurǎ Uzeazǎ de un protocol în trei faze. Buffer de partea expeditorului. Variatii de completare a unui send Asteaptǎ pânǎ datele se copiazǎ de la utilizator în buffer-ul sistemului Nu astepta fǎ utilizatorul constient de modificarea datelor Exemplu reluat: permutarea de date Procesorul j trimite un item la procesorul s(j), unde s(1),, s(p) este o permutare a numerelor 1,, P Procesorul j 199

200 Send_asynch(s(j), item, 1, tag) Recv_block(ANY, item, 1, tag) Ce poate merge rǎu? E necesar a întelege semantica lui send si receive. Multe nuante la îndemânǎ. Alte operatii înafarǎ de send/receive Comunicatii colective (între mai mult de douǎ procesoare) Difuzarea generalǎ (broadcast) de la un proces la toate celelalte Bariere Reduceri (suma, produsul, max, min, boolean si #, ) unde # este orice operatie asociativǎ Împrǎstie/colecteazǎ Prefix paralel procesorul j detine x(j) si calculeazǎ y(j) = x(1) # x(2) # # x(i) Se poate aplica tuturor celorlalte procesoare sau unui subset definit de utilizator Cost = O(logP) utilizând un arbore Operatii de status Chestioneazǎ despre/asteaptǎ pentru încheierea de send/receives Câte procesoare existǎ? Care este numǎrul procesorului meu? Exemplu: sharks and fish N pesti pe P procesoare, N/P pesti per procesor La fiecare pas de timp, se calculeazǎ fortele pe pesti si acestia se deplaseazǎ E necesar a calcula interactiunea gravitationalǎ Într-un algoritm n2 uzual, fiecare peste depinde de oricare alt peste Fiecare peste trebuie sǎ viziteze fiecare procesor, chiar dacǎ el trǎieste numai pe unul Care este costul? Doi algoritmi pentru gravitatie: care sunt costurile lor Algoritmul 1 Copiazǎ masivul Fish local de lungime N/P în masivul Tmp for j = 1 to N for k = 1 to N/P, calculeazǎ forta lui Tmp(k) pe Fish(k) 200

201 Roteste Tmp cu 1 for k = 2 to N/P, Tmp(k) Tmp(k 1) recv(my_proc 1, Tmp(1)) send(my_proc + 1, Tmp(N/P)) Algortimul 2 Copiazǎ masivul Fish local de lungime N/P în masivul Tmp for j = 1 to P for k = 1 to N/P for m = 1 to N/P, calculeazǎ forta lui Tmp(k) pe Fish(m) Roteste Tmp cu N/P recv(my_proc 1, Tmp(1:N/P)) send(my_proc + 1, Tmp(1:N/P)) Ce ar putea merge anapoda? (grijǎ la scrierea peste în Tmp) Alti algoritmi pentru gravitatie Algoritmul 3 (în codul sharks and fish): Toate procesoarele trimit pestii lor la procesorul 1 Procesorul 1 difuzeazǎ toti pestii cǎtre toate procesoarele Algoritmi arborescenti: Barnes-Hut, Greengard-Rokhlin, Anderson O(NlogN) în loc de O(N2) Paralelizabili cu inteligentǎ Numai o aproximare, dar atât de precisǎ cât doriti (adesea sunt necesari numai câtiva digiti, asa cǎ de ce sǎ plǎtesti pentru mai multi) Aceeasi idee lucreazǎ pentru alte probleme unde efectele obiectelor la distantǎ devin netede sau compresibile Electrostaticǎ, turbulentǎ, Radiozitatea în graficǎ Orice fenomen care verificǎ ecuatia Poisson sau ceva de genul ei 201

202 SURSE DE PARALELISM Paralelism si localism în simulare Problemele din lumea realǎ au paralelism si localism: Multe obiecte opereazǎ independent de altele Obiectele depind adesea mai mult de obiectele apropiate decât de cele situate la distantǎ Dependenta de obiectele de la distantǎ poate fi adesea simplificatǎ Modelele stiintifice pot introduce paralelism în plus Când o problemǎ continuǎ este discretizatǎ, dependentele în domeniul temporal sunt în general limitate la pasi de timp adiacenti Efectele de câmp îndepǎrtat, în multe cazuri pot fi ignorate sau aproximate Multe probleme exhibǎ paralelism la niveluri multiple Exemplu: circuitele pot fi simulate la mai multe niveluri si în fiecare poate exista paralelism în sau între subcircuite Exemplu: simulare de circuite Circuitele sunt simulate la multe niveluri diferite 202

203 Tipurile de bazǎ ale simulǎrii Sisteme cu evenimente discrete: Exemple: Jocul vietii, simularea circuitelor la nivelul logicii Sisteme de particule: Exemple: biliardul, simularea dispozitivelor semiconductoare, galaxiile Variabile concentrate care depind de parametri continui: Ecuatiile diferentiale ordinare, exemple: simularea circuitelor (Spice), mecanica structurilor, cinetica chimicǎ Variabile continue (distribuite) care depind de variabile continue: Ecuatii cu derivate partiale, de pildǎ pentru cǎldurǎ, în elasticitate, în electrostaticǎ Un fenomen dat poate fi modelat la niveluri multiple. Multe simulǎri combinǎ mai multe dintre aceste tehnici. Idei generale (outline) Sistemele cu evenimente discrete timpul si spatiul discrete Sistemele de particule caz special important al sistemelor cu parametri concentrati (lectia precedentǎ) Ecuatii diferentiale ordinare (ODE Ordinary Differential Equations) sisteme cu parametri concentrati, locatia entitǎtilor este discretǎ timpul este continuu Ecuatii cu derivate partiale (PDE Partial Differential Equations) timpul si spatiul continue (lectia urmǎtoare) (de la discret sus la continuu jos) Revedere asupra sistemelor de particule În sistemele de particule existǎ Forte externe care sunt usor de paralelizat Fortele de câmp apropiat pot fi rezolvate cu comunicare limitatǎ Fortele de câmp îndepǎrtat sunt mai dificil de manipulat (cer multǎ comunicare) Algoritmii O(n2) cer ca toate particulele sǎ vorbeascǎ cu toate celelalte Calcul scump în calculul pe masini seriale Scumpete si în comunicare pe o masinǎ paralelǎ Algoritmii inteligenti si structurile de date inteligente pot ajuta Metodele retelelor de particule Metodele bazate pe arbori 203

204 Sisteme cu evenimente discrete Sistemele sunt reprezentate ca: Multimea de variabile de cardinal finit Multimea valorilor pe care le iau variabilele la un moment dat se numeste stare Fiecare variabilǎ este actualizatǎ prin evaluarea unei functii de tranzitie care depinde de alte variabile Sistemul poate fi: Sincron: la fiecare pas de timp discret evaluazǎ toate functiile de tranzitie; denumit si masinǎ de stare Asincron: functiile detranzitie sunt evaluate numai dacǎ intrǎrile se modificǎ pe baza unui eveniment dintr-o altǎ parte a sistemului; denumit si simulare condusǎ (driven) de evenimente Exemplu: Jocul vietii : Cunoscut si ca S&F #3: Spatiul divizat în celule, anumite reguli guverneazǎ continutul celulei la fiecare pas Simularea este sincronǎ Se utilizeazǎ douǎ copii ale grilei (veche si nouǎ) Valoarea fiecǎrei noi celule din grilǎ depinde numai de 9 celule (ea însǎsi si cele 8 vecine) din grila veche Simularea se face în pasi de timp fiecare celulǎ este actualizatǎ la fiecare pas Usor de paralelizat prin partitionarea domeniului fizic repetǎ calcul local pentru actualizarea sistemului local barierǎ() schimbǎ informatii privind starea cu celulele vecine pânǎ când se terminǎ simularea Localismul se obtine utilizând zone mari de ocean 204

205 Numai valorile de frontierǎ de la zonele vecine sunt necesare Simularea circuitelor sincronǎ Circuitul este un graf alcǎtuit din subcircuite conectate prin fire Simulǎrile componente trebuie sǎ interactioneze dacǎ ele au un fir comun Strucutura datelor este neregulatǎ graf de subcircuite Algoritmul paralel este mânat de timing sau sincron Evalueazǎ toate componentele la fiecare pas de timp (determinat de întârzierea circuitului cunoscutǎ) Partitionarea grafului atribuie subgrafuri procesoarelor (NP-complet) Determinǎ paralelismul si localismul Încercǎri de a distribui egal subgrafuri la noduri (echilibru de sarcinǎ) Încercǎri de a minimza traversarea de limite (minimizarea comunicǎrii) Traversǎri de limite: 6 în primul graf, 10 în al doilea. Simularea asincronǎ Simularea sincronǎ poate risipi timpul. Se face simulare chiar atunci când intrǎrile nu se schimbǎ Simulǎrile asincrone actualizeazǎ numai când se produce un eveniment provenit de la o altǎ componentǎ: Nu pasi de timp globali ci evenimente individuale care contin marca timpului Exemplu: Jocul vietii în pooluri slab conectate (nu simuleazǎ poolurile goale) Exemplu: simularea circuitelor cu întârzieri (evenimentele sunt schimbarea portilor) Exemplu: simularea traficului (evenimentele sunt vehicule care schimbǎ banda etc.) Simularea asincronǎ este mai eficientǎ dar mai greu de paralelizat 205

206 În MPI evenimentele sunt implementate natural ca mesaje, dar cum se poate sti când se executǎ un receive? Planificarea simulǎrii circuitelor asincron Conservativ: Simuleazǎ numai pânǎ la (inclusiv) marca de timp minimǎ a intrǎrilor Poate necesita detectia blocajelor dacǎ în graf existǎ cicluri, sau altfel mesaje null Exemplu: simulatorul de circuite Pthor in Splash1 de la Stanford Speculativ (sau optimist) Presupune cǎ nici un impuls nou nu va sosi si merge înainte cu simularea Poate necesita backup dacǎ presupunerea e gresitǎ Exemplu: Timewarp [D.Jefferson], Parswec [Wen, Yelik] Optimizarea echilibrului de sarcinǎ si localismului este dificilǎ: Localism înseamnǎ punerea unui subcircuit cuplat puternic pe un procesor Deoarece partea activǎ a circuitului este probabil a fi un subcircuit puternic cuplat, asta poate fi rǎu pentru echilibrarea de sarcinǎ de calcul Sumar despre simularea discretǎ Modelul lumii este discret, si în timp si în spatiu. Tratare: Se descompune domeniul, adicǎ într-un set de obiecte Se executǎ fiecare component înainte utilizând Sincronul: comunicare la fiecare sfârsit de pas al timpului Asincronul: comunicare la cerere Planificare conservativǎ asteptare pentru intrǎri Planificare speculativǎ se peresupun intrǎri inexistente, se revine dacǎ este necesar Sisteme cu parametri concentrati Sisteme cu variabile concentrate Multe sisteme sunt aproximate prin Sistem cu variabile concentrate (lumped) Fiecare depinde de parametri continuu (uzual timpul) Exemplu circuit: 206

207 Aproximat ca un graf Legǎturile sunt arce Noduri sunt conexiunile între 2 sau mai multe fire Fiecare arc are un rezistor, o capacitate, o inductantǎ sau o sursǎ de tensiune Sistemul este concentrat deoarece nu se calculeazǎ tensiunile sau curentii în fiecare punct al firului ci numai la capetele lui Variabilele sunt legate prin legea lui Ohm, legile lui Kirchhoff etc. Se formeazǎ un sistem de ecuatii diferentiale ordinare (ODE Ordinary Differential Equations). Derivatele sunt în raport cu timpul Exemplul unui circuit Starea sistemului este reprezentatǎ de tensiuni în noduri vn curentii în ramuri ib permanent tensiunile pe ramuri vb Ecuatiile includ A I Kirchhoff pentru curenti A 0 R I vn S Kirchhoff pentru tensiuni 0 0 I C d ib = 0 Ohm dt vb 0 capacitati d 0 inductante I 0 L dt Se scrie ca un singur sistem de ODE cuprinzǎtor (cu posibile restrictii) Exemplu de analizǎ structuralǎ Un alt exemplu este analiza structuralǎ fǎcutǎ de inginerii constructori Variabilele sunt deplasǎrile unor puncte într-o clǎdire Se aplicǎ legile lui Newton si ale lui Hook (elasticǎ) Modelarea staticǎ: se aplicǎ forte si se determinǎ deplasǎrile Modelarea dinamicǎ: se aplicǎ forte continue (ca la un cutremur de pǎmânt) Probleme de valori proprii: se potrivesc modurile rezonante ale clǎdirii cu un cutremur? 207

208 Proiectul OpenSees la CE de la Berkeley priveste aceastǎ sectiune de 880, între altele Rezolvarea ODE În aceste exemple si în multe altele matricile sunt rare: Adicǎ multe dintre elementele masivului sunt nule Nici memorare, nici calcule asupra acestor zerouri Fiind dat un set de ODE, apar douǎ tipuri de întrebǎri: Calculul valorilor variabilelor la un timp t Metode explicite Metode implicite Calculul modurilor de vibratie Probleme de valori proprii Rezolvarea de ODE: metode explicite Se admite cǎ ODE sunt x (t) = f(x) = A*x, cu A o matrice rarǎ Se calculeazǎ x(i*dt) = x[i] la i = 0, 1, 2, Se aproximeazǎ x (i*dt) ca x[i+1] = x[i] + dt*panta (cu panta în x[i]) 208

209 Metodele explicite, de pildǎ metoda Euler (înainte) Se aproximeazǎ x (t) = A*x prin (x[i+1] x[i])/dt = A*x[i] x[i+1] = x[i] + dt*a*x[i], adicǎ multiplicare de matrice rarǎ cu vector Concesii (tradeoffs): Algoritm simplu: multiplicare de matrice rarǎ cu vector Probleme de stabilitate: pot fi necesari pasi de timp foarte mici, în spacial dacǎ sistemul este stiff (se schimbǎ rapid) Rezolvarea ODE: metodele implicite Se admite cǎ ODE sunt x (t) = f(x) = A*x, cu A o matrice rarǎ Se calculeazǎ x(i*dt) = x[i] la i = 0, 1, 2, Se aproximeazǎ x (i*dt) ca x[i+1] = x[i] + dt*panta (cu panta în x[i+1]) Metoda implicitǎ, de pildǎ Euler înapoi rezolvǎ: Se aproximeazǎ x (t) = A*x prin (x[i+1] x[i])/dt = A*x[i+1] (I dt*a)*x[i+1] =x[i], adicǎ e necesarǎ rezolvarea unui sistem liniar de ecuatii algebrice 209

210 Compromisuri: Pasi de timp posibil mai mari: în sepcial pentru probleme rigide (stiff) Algoritm mai dificil: necesitǎ rezolvarea unui sistem rar la fiecare pas Rezolvarea ODE: valori proprii Calcularea modurilor de vibratie: determinarea valorilor proprii si vectorilor proprii Se cautǎ solutia ecuatiei x (t) = A*x de forma x(t) = sin(f*t)*x0, cu x0 un vector constant Se introduce (plug in) pentru a obtine f 2*x0 = A*x0, astfel încât f 2 este o valoare proprie si x0 este un vector propriu al lui A Schemele solutiei se reduc fie la multiplicarea de matrici rare sau la rezolvarea de sisteme liniare rare. ODE si matrici rare Toate acestea se reduc la probleme cu matrici rare: Explicit: multiplicare matrice rarǎ cu vector Implicit: rezolvarea unui sistem liniar rar Rezolvare directǎ (eliminarea Gauss) Rezolvare iterativǎ (utilizeazǎ multiplicare matrice rarǎ cu vector) Algoritmii pentru valori proprii/vectori proprii pot fi, de asemenea, expliciti sau impliciti Multiplicarea paralel matrice rarǎ vector y = A*x, cu A rarǎ (n n) Probleme: Care procesor memoreazǎ y[i], x[i] si A[i, j]? Care procesor calculeazǎ y[i] = sumǎ (de la 1 la n) A[i, j]*x[j] = (linia i a lui A)*x un produs punctual rar? 210

211 Partiţionarea Multimea de indici {1, 2,, n} se partitioneazǎ în N1, N2,, Np Pentru toti i din Nk, procesorul k memoreazǎ y[i], x[i] si linia i din A Pentru toti i din Nk, procesorul k face calculul (linia i din A)*x; cea mai problematicǎ operatie Regula proprietarul calculeazǎ : procesorul k face calculul propriilor y[i] Reordonarea matricilor prin partitionarea grafurilor Structura idealǎ a matricei pentru paralelism: bloc-diagonalǎ. p (numǎrul de procesoare) blocuri, tot calculul se poate face local Putinele valori nenule situate în afara acestor blocuri necesitǎ comunicare Se pot reordona liniile/coloanele pentru a avea o asemenea structurǎ? Scopurile reordonǎrii Scopuri care vizeazǎ perfomanta: Echilibrarea sarcinii (cum se mǎsoarǎ încǎrcarea?) Echilibrarea memoriei (cât memoreazǎ fiecare procesor?) Minimizarea comunicǎrii (cât se comunicǎ?) Unii algoritmi face reordonarea pentru alte motive: Reducerea numǎrului de valori nenule în rezultat (fill) Ameliorarea proprietǎtilor numerice. Partitionarea grafurilor si matricile rare Relatia dintre matrici si grafuri 211

212 O partitie bunǎ a unui graf are: Numǎr egal (ponderat) de noduri în fiecare parte (sarcinǎ si memorie balansate) Numǎr minim de muchii (arce) care leagǎ pǎrtile (minimizarea comunicǎrii) Se reordoneazǎ liniile/coloanele prin punerea laolaltǎ a tuturor nodurilor dintr-o parte a partitiei. Metode implicite si probleme de valori/vectori proprii Metode directe (eliminarea Gauss): Denumite descompuneri LU din cauza factorizǎrii A = L*U Lectiile viitoare vor lua în discutie ambele cazuri, dens si rar Mai complicatǎ decât multiplicarea matrice rarǎ vector Metode de rezolvare iterative: Vor fi discutate mai multe din ele mai încolo Jacobi, overrelaxarea succesivǎ (SOR Succesive OverRelaxation), gradientii conjugati (CG), multigrila, Multe au ca miez multiplicarea matrice rarǎ vector Probleme de valori/vectori proprii: Unele lectii viitoare se vor concentra si pe cazurile dense si pe cele rare Metodele directe depind de asemenea de multiplicarea matrice rarǎ vector. Ecuatii cu derivate partiale PDE Variabile continue, parametri continui Sisteme de acest gen: 212

213 Probleme parabolice (dependente de timp): Fluxul de cǎldurǎ: temperatura este functie de pozitie si de timp Difuzia: concentratia este functie de pozitie si de timp Probleme eliptice (stǎri stationare): Potentialul gravitational sau electrostatic: potentialul depinde de pozitie Probleme hiperbolice (unde): Mecanica cuanticǎ: functia de undǎ depinde de pozitie si de timp Multe probleme combinǎ aspectele de mai sus. Curgerea fluidelor: vitezǎ, presiune, densitate, toate sunt functii de pozitie si de timp Elasticitate: efortul, tensiunile mecanice sunt functii de pozitie si de timp Terminologie Termenii hiperbolic, parabolic, eliptic vin de la cazuri speciale ale formei generale a PDE de ordinul al doilea liniarǎ 2u 2u 2u u u a 2+b +c 2+ d +e + f = 0 x y x y x y unde y este timpul. Prin analogie cu solutiile ecuatiei pǎtratice generale ax 2 + bxy + cy 2 + dx + ey + f = 0 Exemplu: scrierea ecuatiei cǎldurii Se considerǎ o problemǎ simplǎ: O barǎ cilindricǎ de material omogen, izolatǎ cu exceptia capetelor Fie u(x, t) temperatura la pozitia x la timpul t Cǎldura circulǎ de la x h la x + h cu debitul proportional cu derivata a doua în coordonata x u ( x, t ) [u ( x h, t ) u ( x, t )] / h [u ( x, t ) u ( x + h, t )] / h = C t h Prin trecere la limitǎ, h 0, se obtine ecuatia u ( x, t ) 2 u ( x, t ) = C t x2 213

214 Detalii despre metoda explicitǎ pentru ecuatia cǎldurii Din observatii experimentale se obtine: u(x, t)/ t = [ u(x, t)/ x] (pentru simplitate, s-a considerat C = 1) Se discretizeazǎ timpul si spatiul si se utilizeazǎ tehnica explicitǎ de a aproxima derivatele (ca la ODE): [u ( x, t + dt ) u ( x, t )] / dt = [u ( x h, t ) 2u ( x, t ) + u ( x + h, t )] / h 2 u ( x, t + dt ) u ( x, t ) = ( dt / h 2 )[u ( x h, t ) 2u ( x, t ) + u ( x + h, t )] u ( x, t + dt ) = u ( x, t ) + (dt / h 2 )[u ( x h, t ) 2u ( x, t ) + u ( x + h, t )] Se pune z = dt/h2 u ( x, t + dt ) = zu ( x h, t ) + (1 2 z )u ( x, t ) + zu ( x + h, t )] Prin schimbarea de variabile x în j si y în i se obtine u[j,i+1] = z*u[j 1,i] + (1 2*z)*u[j,i] + z*u[j+1,i]. Solutia explicitǎ a ecuatiei cǎldurii Se utilizeazǎ diferentele finite cu u[j,i] ca temperatura la Timpul t = i*dt (i = 0, 1, 2, ) si pozitia x = j*h (j = 0, 1,, N=1/h) Conditiile initiale pe u[j, 0] Conditii pe frontierǎ la u[0, i] si u[n, i] La fiecare pas de timp, i = 0, 1, 2, for j=0 to N u[j,i+1] = z*u[j 1,i] + (1 2*z)*u[j,i] + z*u[j+1,i] cu z ca mai sus. 214

215 Aceasta corespunde la multiplicarea matrice vector, cu cei mai apropiati vecini pe grilǎ Vederea matricii din metoda explicitǎ la ecuatia cǎldurii Multiplicare cu o matrice tridiagonalǎ la fiecare pas z 1 2z z 1 2z z T= z 1 2z z z 1 2 z Graf si decupaj de 3 puncte Paralelismul în metoda explicitǎ pentru PDE Partitionarea spatiului (x) în p bucǎti, cele mai mari O echilibrare a sarcinii (presupunând numǎr mare de puncte relativ la p) Minimizarea comunicǎrii (numai p bucǎti) Se generalizeazǎ la: Dimensiuni multiple Grafuri arbitrare (= matrici rare arbitrare) Tratarea explicitǎ este utilizatǎ adesea pentru ecuatii hiperbolice. Probleme cu tratarea explicitǎ pentru ecautia cǎldurii (parabolicǎ): Instabilitate numericǎ Solutia explodeazǎ ulterior dacǎ z = dt/h2 > 0,5 Devine necesar a face pasii de timp foarte mici când h este mic: dt < 0,5*h2 Instabilitǎti în rezolvarea ecuatiei cǎldurii explicit 215

216 Solutia implicitǎ a ecuatiei cǎldurii Din observatii experimentale se obtine: u(x, t)/ t = [ u(x, t)/ x] (pentru simplitate, s-a considerat C = 1) Se discretizeazǎ timpul si spatiul si pentru aproximarea derivatei se utilzeazǎ varinta implicitǎ (Euler înapoi backward): [u ( x, t + dt ) u ( x, t )] / dt = [u ( x h, t + dt ) 2u ( x, t + dt ) + u ( x + h, t + dt )] / h 2 u ( x, t + dt ) = u ( x, t ) + (dt / h 2 )[u ( x h, t + dt ) 2u ( x, t + dt ) + u ( x + h, t + dt )] Se pune z = dt/h2 si se schimbǎ variabilele x în j si y în i. Se obtine: u[:,i] = (I z*l)*u[:,i+1] cu I matricea unitate si cu L laplaceanul L=

217 Discutia de mai sus se bazeazǎ pe aproximarea Euler înapoi, dar regula trapezelor are rezultate numerice mai bune. Asta se traduce prin rezolvarea ecuatiei [I + (z/2)*l]*u[:, i + 1] = [I (z/2)*l]*u[:, i] din nou cu I matricea unitate si cu L de aceeasi formǎ. Graf si decupaj de 3 puncte Aceasta este în esentǎ rezolvarea ecuatiei Poisson în spatiul 1D. Metoda implicitǎ pentru 2D Este similarǎ cazului 1D, dar matricea L este acum L= Decupaj de 5 5 puncte Cazul 3D este similar (cu decupaj de 7 7 puncte). Multiplicarea cu aceastǎ matrice (ca în cazul explicit) este simplu: un calcul pe vecinii cei mai apropiati pe o grilǎ 2D. 217

218 Pentru a rezolva acest sistem sunt tehnici multiple. Relatia ecuatiei Poisson cu gravitatia, cu electrostatica Ecuatia Poisson apare în multe probleme, de exemplu, forta exercitatǎ asupra unei particule situatǎ în pozitia (x, y, z) de o particulǎ situatǎ în origine se exprimǎ ca (x, y, z)/r3, cu r = sqrt(x2 + y2 + z2). Forta este totodatǎ gradientul potentialului V = 1/r (d/dx V, d/dy V, d/dz V) = grad V V satisface ecuatia lui Poisson (a se verifica) Algoritmi pentru ecuatia lui Poisson 2D (N variabile) PRAM este un model paralel idealizat cu costul comunicǎrii nul. Referiri: James Demmel, Applied Numerical Linear Algebra, SIAM, Privire generalǎ asupra algoritmilor Sortati în douǎ oridini (grosier) De la cei mai lenti la cei mai rapizi pe masini secventiale 218

219 De la cei mai generali (care lucreazǎ pe orice matrice) la cei mai specializati (care lucreazǎ pe matrici ca T tridiagonalǎ de mai sus) LU densǎ: eliminarea Gauss, lucreazǎ pe orice matrice N N. LU bandǎ: exploateazǎ faptul cǎ T are elemente nenule numai pe sqrt(n) diagonale cele mai apropiate de diagonala principalǎ. Jacobi: în esentǎ face o multiplicare matrice vector prin T într-o buclǎ interioarǎ a algoritmului. Inversa explicitǎ: presupune cǎ se doreste a se rezolva multe sisteme cu T, astfel ca se poate precalcula si memoriza T 1 fǎrǎ cheltuieli prea mari si numai prin multiplicarea cu ea însǎsi (dar încǎ scumpǎ). Gradientii conjugati: se utilizeazǎ multiplicarea matrice vector, ca la Jacobi, dar se exploateazǎ proprietǎtile matematice ale matricei T pe care metoda Jacobi nu le exploateazǎ. SOR rosu-negru (Succesive Over-Relaxation): variatie a metodei Jacobi care exploateazǎ totusi diferitele proprietǎti matematice ale matricei T. Utilizatǎ în schemele multigrilǎ. LU: eliminarea Gauss care exploateazǎ structura particularǎ de zerouri a matricei T. FFT (Fast Fourier Transform): lucreazǎ numai pe matrici foarte asemǎnǎtoare cu T. Multigrid: lucreazǎ de asemenea pe matrici de genul T care provin din PDE eliptice Lower Bound: serial (timp pentru a tipǎri rǎspunsul); paralel (timp pentru a combina N intrǎri) Detalii în notele de clasǎ si Mflop/s si timp de executie în practicǎ Problema: un solver iterativ pentru o problemǎ de convectie-difuzie; se executǎ pe o masinǎ cu 1024-CPU NCUBE-2 Referire: Shadid si Tuminaro, SIAM Parallel Processing Conference, March 1991 Care solver ar fi de ales? Sumar al metodelor de rezolvare a PDE 219

220 Ca si în cazul ODE, sunt posibile tratǎri explicite sau implicite. Explicit, multiplicarea matrice rarǎ vector Implicit, rezolvarea matricei rare la fiecare pas Rezolvarea directǎ este dificilǎ (mai mult, mai departe) Rezolvarea iterativǎ se traduce în multiplicare matrice rarǎ vector Corespondenta grilǎ si matrice rarǎ: Multiplicarea matrice rarǎ vector este medierea vecinilor cei mai apropiati pe grila/reteaua suport (underlying). Nu toate calculele cu vecinii cei mai apropiati au acceasi eficientǎ. Factorii sunt structura retelei (structurǎ non-zero) si numǎrul de flops per punct. Comentaiu asupra retelelor practice Retele regulate 1D, 2D, 3D Importante ca constructie de blocuri pentru retele mai complicate Retele (meshes) practice sunt adesea neregulate Retele compuse, care constau în retele regulate îndoite multiple reunite pe muchii Retele nestructurate, cu puncte de retea si conexiuni arbitrare Retele adaptive, care îsi schimbǎ rezolutia în timpul procesului de solutionare a problemelor pentru a pune efortul de calcul acolo unde este necesar Paralelism în retele regulate Calculul unui decupaj (stencil) într-o retea regulatǎ Necesitǎ a comunica punctele din apropierea frontierei între procesoare învecinate Adesea cu regiuni fantomǎ (ghost) Raportul suprafatǎ la volum tine comunicarea scǎzutǎ, dar Poate fi încǎ problematicǎ în practicǎ 220

221 Implementatǎ utilizând regiuni fantomǎ Adaugǎ un overhead de memorie Rafinarea adaptivǎ a retelelor (AMR Adaptive Mesh Refinement) Retea adaptivǎ înjurul unei explozii Rafinarea fǎcutǎ prin calcularea erorilor Paralelism Majoritar între benzi ( patches ), distribuite procesoarelor pentru sarcinǎ balansatǎ Se poate exploata ceva în interiorul unei benzi (patch) (SMP) Proiecte: Titanium ( Chombo (P.Colella, LBL), KeLP (S.Baden, UCSD), J.Bell, LBL Retele adaptive 221

222 Unde de soc în dinamica unui gaz utilizând AMR (Adaptive Mesh Refinement) A se vedea Retele compuse de la o structurǎ mecanicǎ 222

223 Convertirea unei retele într-o matrice 223

224 Efectele reordonǎrii asupra eliminǎrii Gauss Retele neregulate: profilul NASA în 2D 224

225 Retele neregulate: tubul îngustat (multigrid) Exemplu: retele Prometeu 225

Versionare - GIT ALIN ZAMFIROIU

Versionare - GIT ALIN ZAMFIROIU Versionare - GIT ALIN ZAMFIROIU Controlul versiunilor - necesitate Caracterul colaborativ al proiectelor; Backup pentru codul scris Istoricul modificarilor Terminologie și concepte VCS Version Control

More information

Metrici LPR interfatare cu Barix Barionet 50 -

Metrici LPR interfatare cu Barix Barionet 50 - Metrici LPR interfatare cu Barix Barionet 50 - Barionet 50 este un lan controller produs de Barix, care poate fi folosit in combinatie cu Metrici LPR, pentru a deschide bariera atunci cand un numar de

More information

Procesarea Imaginilor

Procesarea Imaginilor Procesarea Imaginilor Curs 11 Extragerea informańiei 3D prin stereoviziune Principiile Stereoviziunii Pentru observarea lumii reale avem nevoie de informańie 3D Într-o imagine avem doar două dimensiuni

More information

Titlul lucrării propuse pentru participarea la concursul pe tema securității informatice

Titlul lucrării propuse pentru participarea la concursul pe tema securității informatice Titlul lucrării propuse pentru participarea la concursul pe tema securității informatice "Îmbunătăţirea proceselor şi activităţilor educaţionale în cadrul programelor de licenţă şi masterat în domeniul

More information

Reflexia şi refracţia luminii. Aplicaţii. Valerica Baban

Reflexia şi refracţia luminii. Aplicaţii. Valerica Baban Reflexia şi refracţia luminii. Aplicaţii. Sumar 1. Indicele de refracţie al unui mediu 2. Reflexia şi refracţia luminii. Legi. 3. Reflexia totală 4. Oglinda plană 5. Reflexia şi refracţia luminii în natură

More information

Structura și Organizarea Calculatoarelor. Titular: BĂRBULESCU Lucian-Florentin

Structura și Organizarea Calculatoarelor. Titular: BĂRBULESCU Lucian-Florentin Structura și Organizarea Calculatoarelor Titular: BĂRBULESCU Lucian-Florentin Chapter 3 ADUNAREA ȘI SCĂDEREA NUMERELOR BINARE CU SEMN CONȚINUT Adunarea FXP în cod direct Sumator FXP în cod direct Scăderea

More information

Textul si imaginile din acest document sunt licentiate. Codul sursa din acest document este licentiat. Attribution-NonCommercial-NoDerivs CC BY-NC-ND

Textul si imaginile din acest document sunt licentiate. Codul sursa din acest document este licentiat. Attribution-NonCommercial-NoDerivs CC BY-NC-ND Textul si imaginile din acest document sunt licentiate Attribution-NonCommercial-NoDerivs CC BY-NC-ND Codul sursa din acest document este licentiat Public-Domain Esti liber sa distribui acest document

More information

Semnale şi sisteme. Facultatea de Electronică şi Telecomunicaţii Departamentul de Comunicaţii (TC)

Semnale şi sisteme. Facultatea de Electronică şi Telecomunicaţii Departamentul de Comunicaţii (TC) Semnale şi sisteme Facultatea de Electronică şi Telecomunicaţii Departamentul de Comunicaţii (TC) http://shannon.etc.upt.ro/teaching/ssist/ 1 OBIECTIVELE CURSULUI Disciplina îşi propune să familiarizeze

More information

Multicore Multiprocesoare Cluster-e

Multicore Multiprocesoare Cluster-e Multicore Multiprocesoare Cluster-e O mare perioadă de timp, creearea de calculatoare puternice conectarea mai multor calculatoare de putere mică. Trebuie creat software care să știe să lucreze cu un număr

More information

MS POWER POINT. s.l.dr.ing.ciprian-bogdan Chirila

MS POWER POINT. s.l.dr.ing.ciprian-bogdan Chirila MS POWER POINT s.l.dr.ing.ciprian-bogdan Chirila chirila@cs.upt.ro http://www.cs.upt.ro/~chirila Pornire PowerPoint Pentru accesarea programului PowerPoint se parcurg următorii paşi: Clic pe butonul de

More information

Tipuri și nivele de paralelism Clasificarea arhitecturilor paralele Arhitecturi vectoriale Arhitecturi SIMD Arhitecturi sistolice

Tipuri și nivele de paralelism Clasificarea arhitecturilor paralele Arhitecturi vectoriale Arhitecturi SIMD Arhitecturi sistolice Tipuri și nivele de paralelism Clasificarea arhitecturilor paralele Arhitecturi vectoriale Arhitecturi SIMD Arhitecturi sistolice Arhitecturi cu fire de execuție multiple 1 Arhitecturi cu memorie partajată

More information

Arhitectura sistemelor de calcul paralel

Arhitectura sistemelor de calcul paralel Arhitectura sistemelor de calcul paralel CURS 1 17.02.2014 Exemple de procese paralele si aplicatii Lumea reala un laborator gigactic de procese paralele Aplicatii Rezolvarea numerica a unor probleme care

More information

Modalitǎţi de clasificare a datelor cantitative

Modalitǎţi de clasificare a datelor cantitative Modalitǎţi de clasificare a datelor cantitative Modul de stabilire a claselor determinarea pragurilor minime şi maxime ale fiecǎrei clase - determinǎ modul în care sunt atribuite valorile fiecǎrei clase

More information

GHID DE TERMENI MEDIA

GHID DE TERMENI MEDIA GHID DE TERMENI MEDIA Definitii si explicatii 1. Target Group si Universe Target Group - grupul demografic care a fost identificat ca fiind grupul cheie de consumatori ai unui brand. Toate activitatile

More information

2. Setări configurare acces la o cameră web conectată într-un router ZTE H218N sau H298N

2. Setări configurare acces la o cameră web conectată într-un router ZTE H218N sau H298N Pentru a putea vizualiza imaginile unei camere web IP conectată într-un router ZTE H218N sau H298N, este necesară activarea serviciului Dinamic DNS oferit de RCS&RDS, precum și efectuarea unor setări pe

More information

Ghid identificare versiune AWP, instalare AWP şi verificare importare certificat în Store-ul de Windows

Ghid identificare versiune AWP, instalare AWP şi verificare importare certificat în Store-ul de Windows Ghid identificare versiune AWP, instalare AWP 4.5.4 şi verificare importare certificat în Store-ul de Windows Data: 28.11.14 Versiune: V1.1 Nume fişiser: Ghid identificare versiune AWP, instalare AWP 4-5-4

More information

La fereastra de autentificare trebuie executati urmatorii pasi: 1. Introduceti urmatoarele date: Utilizator: - <numarul dvs de carnet> (ex: "9",

La fereastra de autentificare trebuie executati urmatorii pasi: 1. Introduceti urmatoarele date: Utilizator: - <numarul dvs de carnet> (ex: 9, La fereastra de autentificare trebuie executati urmatorii pasi: 1. Introduceti urmatoarele date: Utilizator: - (ex: "9", "125", 1573" - se va scrie fara ghilimele) Parola: -

More information

Managementul Proiectelor Software Metode de dezvoltare

Managementul Proiectelor Software Metode de dezvoltare Platformă de e-learning și curriculă e-content pentru învățământul superior tehnic Managementul Proiectelor Software Metode de dezvoltare 2 Metode structurate (inclusiv metodele OO) O mulțime de pași și

More information

ARBORI AVL. (denumiti dupa Adelson-Velskii si Landis, 1962)

ARBORI AVL. (denumiti dupa Adelson-Velskii si Landis, 1962) ARBORI AVL (denumiti dupa Adelson-Velskii si Landis, 1962) Georgy Maximovich Adelson-Velsky (Russian: Гео ргий Макси мович Адельсо н- Ве льский; name is sometimes transliterated as Georgii Adelson-Velskii)

More information

Subiecte Clasa a VI-a

Subiecte Clasa a VI-a (40 de intrebari) Puteti folosi spatiile goale ca ciorna. Nu este de ajuns sa alegeti raspunsul corect pe brosura de subiecte, ele trebuie completate pe foaia de raspuns in dreptul numarului intrebarii

More information

Curs 1 17 Februarie Adrian Iftene

Curs 1 17 Februarie Adrian Iftene Curs 1 17 Februarie 2011 Adrian Iftene adiftene@info.uaic.ro 1 Limbajele calculatorului Compilate Interpretate Scripting P-cod Orientate pe aspect Orientate spre date 2 Cum lucrează? Orice program trebuie

More information

3. CLOUD COMPUTING Sisteme de calcul distribuite

3. CLOUD COMPUTING Sisteme de calcul distribuite 3. CLOUD COMPUTING Cloud Computing (CC) calcul în nori, în traducere mot a mot, sau, mai corect, calcul în Internet este un concept aflat în directă legătură cu transformările către se produc în domeniu

More information

9. Memoria. Procesorul are o memorie cu o arhitectură pe două niveluri pentru memoria de program și de date.

9. Memoria. Procesorul are o memorie cu o arhitectură pe două niveluri pentru memoria de program și de date. 9. Memoria Procesorul are o memorie cu o arhitectură pe două niveluri pentru memoria de program și de date. Primul nivel conține memorie de program cache (L1P) și memorie de date cache (L1D). Al doilea

More information

INSTRUMENTE DE MARKETING ÎN PRACTICĂ:

INSTRUMENTE DE MARKETING ÎN PRACTICĂ: INSTRUMENTE DE MARKETING ÎN PRACTICĂ: Marketing prin Google CUM VĂ AJUTĂ ACEST CURS? Este un curs util tuturor celor implicați în coordonarea sau dezvoltarea de campanii de marketingși comunicare online.

More information

Lucrarea Nr.1. Sisteme de operare. Generalitati

Lucrarea Nr.1. Sisteme de operare. Generalitati Lucrarea Nr.1 Sisteme de operare. Generalitati Scopul lucrarii Lucrarea îsi propune familiarizarea studentilor cu sistemele de operare disponibile în laborator, respectiv acele sisteme de operare cu ajutorul

More information

Ierarhia memoriilor Tipuri de memorii Memorii semiconductoare Memoria cu unități multiple. Memoria cache Memoria virtuală

Ierarhia memoriilor Tipuri de memorii Memorii semiconductoare Memoria cu unități multiple. Memoria cache Memoria virtuală Ierarhia memoriilor Tipuri de memorii Memorii semiconductoare Memoria cu unități multiple Memoria cache Memoria virtuală 1 Memorii RAM: datele sunt identificate cu ajutorul unor adrese unice Memorii asociative:

More information

Printesa fluture. Мобильный портал WAP версия: wap.altmaster.ru

Printesa fluture. Мобильный портал WAP версия: wap.altmaster.ru Мобильный портал WAP версия: wap.altmaster.ru Printesa fluture Love, romance and to repent of love. in romana comy90. Formular de noastre aici! Reduceri de pret la stickere pana la 70%. Stickerul Decorativ,

More information

Reţele Neuronale Artificiale în MATLAB

Reţele Neuronale Artificiale în MATLAB Reţele Neuronale Artificiale în MATLAB Programul MATLAB dispune de o colecţie de funcţii şi interfeţe grafice, destinate lucrului cu Reţele Neuronale Artificiale, grupate sub numele de Neural Network Toolbox.

More information

Mecanismul de decontare a cererilor de plata

Mecanismul de decontare a cererilor de plata Mecanismul de decontare a cererilor de plata Autoritatea de Management pentru Programul Operaţional Sectorial Creşterea Competitivităţii Economice (POS CCE) Ministerul Fondurilor Europene - Iunie - iulie

More information

Auditul financiar la IMM-uri: de la limitare la oportunitate

Auditul financiar la IMM-uri: de la limitare la oportunitate Auditul financiar la IMM-uri: de la limitare la oportunitate 3 noiembrie 2017 Clemente Kiss KPMG in Romania Agenda Ce este un audit la un IMM? Comparatie: audit/revizuire/compilare Diferente: audit/revizuire/compilare

More information

Transmiterea datelor prin reteaua electrica

Transmiterea datelor prin reteaua electrica PLC - Power Line Communications dr. ing. Eugen COCA Universitatea Stefan cel Mare din Suceava Facultatea de Inginerie Electrica PLC - Power Line Communications dr. ing. Eugen COCA Universitatea Stefan

More information

Olimpiad«Estonia, 2003

Olimpiad«Estonia, 2003 Problema s«pt«m nii 128 a) Dintr-o tabl«p«trat«(2n + 1) (2n + 1) se ndep«rteaz«p«tr«telul din centru. Pentru ce valori ale lui n se poate pava suprafata r«mas«cu dale L precum cele din figura de mai jos?

More information

3.2 Arhitectura setului de instrucţiuni ISA. Copyright Paul GASNER

3.2 Arhitectura setului de instrucţiuni ISA. Copyright Paul GASNER 3.2 Arhitectura setului de instrucţiuni ISA Copyright Paul GASNER Programarea CPU Programele scrise în limbaje de nivel înalt trebuie compilate pentru a obţine un program executabil Din punctul de vedere

More information

X-Fit S Manual de utilizare

X-Fit S Manual de utilizare X-Fit S Manual de utilizare Compatibilitate Acest produs este compatibil doar cu dispozitivele ce au următoarele specificații: ios: Versiune 7.0 sau mai nouă, Bluetooth 4.0 Android: Versiune 4.3 sau mai

More information

D în această ordine a.î. AB 4 cm, AC 10 cm, BD 15cm

D în această ordine a.î. AB 4 cm, AC 10 cm, BD 15cm Preparatory Problems 1Se dau punctele coliniare A, B, C, D în această ordine aî AB 4 cm, AC cm, BD 15cm a) calculați lungimile segmentelor BC, CD, AD b) determinați distanța dintre mijloacele segmentelor

More information

REVISTA NAŢIONALĂ DE INFORMATICĂ APLICATĂ INFO-PRACTIC

REVISTA NAŢIONALĂ DE INFORMATICĂ APLICATĂ INFO-PRACTIC REVISTA NAŢIONALĂ DE INFORMATICĂ APLICATĂ INFO-PRACTIC Anul II Nr. 7 aprilie 2013 ISSN 2285 6560 Referent ştiinţific Lector univ. dr. Claudiu Ionuţ Popîrlan Facultatea de Ştiinţe Exacte Universitatea din

More information

Propuneri pentru teme de licență

Propuneri pentru teme de licență Propuneri pentru teme de licență Departament Automatizări Eaton România Instalație de pompare cu rotire în funcție de timpul de funcționare Tablou electric cu 1 pompă pilot + 3 pompe mari, cu rotirea lor

More information

Update firmware aparat foto

Update firmware aparat foto Update firmware aparat foto Mulţumim că aţi ales un produs Nikon. Acest ghid descrie cum să efectuaţi acest update de firmware. Dacă nu aveţi încredere că puteţi realiza acest update cu succes, acesta

More information

ISBN-13:

ISBN-13: Regresii liniare 2.Liniarizarea expresiilor neliniare (Steven C. Chapra, Applied Numerical Methods with MATLAB for Engineers and Scientists, 3rd ed, ISBN-13:978-0-07-340110-2 ) Există cazuri în care aproximarea

More information

MANAGEMENTUL CALITĂȚII - MC. Proiect 5 Procedura documentată pentru procesul ales

MANAGEMENTUL CALITĂȚII - MC. Proiect 5 Procedura documentată pentru procesul ales MANAGEMENTUL CALITĂȚII - MC Proiect 5 Procedura documentată pentru procesul ales CUPRINS Procedura documentată Generalități Exemple de proceduri documentate Alegerea procesului pentru realizarea procedurii

More information

Mods euro truck simulator 2 harta romaniei by elyxir. Mods euro truck simulator 2 harta romaniei by elyxir.zip

Mods euro truck simulator 2 harta romaniei by elyxir. Mods euro truck simulator 2 harta romaniei by elyxir.zip Mods euro truck simulator 2 harta romaniei by elyxir Mods euro truck simulator 2 harta romaniei by elyxir.zip 26/07/2015 Download mods euro truck simulator 2 harta Harta Romaniei pentru Euro Truck Simulator

More information

Prelucrarea numerică a semnalelor

Prelucrarea numerică a semnalelor Prelucrarea numerică a semnalelor Assoc.Prof. Lăcrimioara GRAMA, Ph.D. http://sp.utcluj.ro/teaching_iiiea.html 27 februarie 2017 Lăcrimioara GRAMA (sp.utcluj.ro) Prelucrarea numerică a semnalelor 27 februarie

More information

Tema 1 - Transferuri de date DMA intr-o arhitectura de tip Cell

Tema 1 - Transferuri de date DMA intr-o arhitectura de tip Cell Tema 1 - Transferuri de date DMA intr-o arhitectura de tip Cell Termen de trimitere a temei: Luni, 31 martie 2008, ora 23:55 1. Specificatii functionale O arhitectura de tip Cell consta din urmatoarele

More information

Laborator 1. Programare declarativă. Programare logică. Prolog. SWI-Prolog

Laborator 1. Programare declarativă. Programare logică. Prolog. SWI-Prolog Laborator 1 Programare declarativă O paradigmă de programare în care controlul fluxului de execuție este lăsat la latitudinea implementării limbajului, spre deosebire de programarea imperativă în care

More information

COMUNICAȚII INFORMATIZARE

COMUNICAȚII INFORMATIZARE COMUNICAȚII INFORMATIZARE 120 Migrare servicii telefonie la Vodafone S-a asigurat suportul tehnic și s-a colaborat cu echipele Vodafone la portarea numerelor UPT și migrarea infrastructuri: 1200 linii

More information

Documentaţie Tehnică

Documentaţie Tehnică Documentaţie Tehnică Verificare TVA API Ultima actualizare: 27 Aprilie 2018 www.verificaretva.ro 021-310.67.91 / 92 info@verificaretva.ro Cuprins 1. Cum funcţionează?... 3 2. Fluxul de date... 3 3. Metoda

More information

Software Process and Life Cycle

Software Process and Life Cycle Software Process and Life Cycle Drd.ing. Flori Naghiu Murphy s Law: Left to themselves, things tend to go from bad to worse. Principiile de dezvoltare software Principiul Calitatii : asigurarea gasirii

More information

INFORMAȚII DESPRE PRODUS. FLEXIMARK Stainless steel FCC. Informații Included in FLEXIMARK sample bag (article no. M )

INFORMAȚII DESPRE PRODUS. FLEXIMARK Stainless steel FCC. Informații Included in FLEXIMARK sample bag (article no. M ) FLEXIMARK FCC din oțel inoxidabil este un sistem de marcare personalizată în relief pentru cabluri și componente, pentru medii dure, fiind rezistent la acizi și la coroziune. Informații Included in FLEXIMARK

More information

Excel Advanced. Curriculum. Școala Informală de IT. Educație Informală S.A.

Excel Advanced. Curriculum. Școala Informală de IT. Educație Informală S.A. Excel Advanced Curriculum Școala Informală de IT Tel: +4.0744.679.530 Web: www.scoalainformala.ro / www.informalschool.com E-mail: info@scoalainformala.ro Cuprins 1. Funcții Excel pentru avansați 2. Alte

More information

DECLARAȚIE DE PERFORMANȚĂ Nr. 101 conform Regulamentului produselor pentru construcții UE 305/2011/UE

DECLARAȚIE DE PERFORMANȚĂ Nr. 101 conform Regulamentului produselor pentru construcții UE 305/2011/UE S.C. SWING TRADE S.R.L. Sediu social: Sovata, str. Principala, nr. 72, judetul Mures C.U.I. RO 9866443 Nr.Reg.Com.: J 26/690/1997 Capital social: 460,200 lei DECLARAȚIE DE PERFORMANȚĂ Nr. 101 conform Regulamentului

More information

Metoda BACKTRACKING. prof. Jiduc Gabriel

Metoda BACKTRACKING. prof. Jiduc Gabriel Metoda BACKTRACKING prof. Jiduc Gabriel Un algoritm backtracking este un algoritm de căutare sistematică și exhausivă a tuturor soluțiilor posibile, dintre care se poate alege apoi soluția optimă. Problemele

More information

Dispozitive Electronice şi Electronică Analogică Suport curs 02 Metode de analiză a circuitelor electrice. Divizoare rezistive.

Dispozitive Electronice şi Electronică Analogică Suport curs 02 Metode de analiză a circuitelor electrice. Divizoare rezistive. . egimul de curent continuu de funcţionare al sistemelor electronice În acest regim de funcţionare, valorile mărimilor electrice ale sistemului electronic sunt constante în timp. Aşadar, funcţionarea sistemului

More information

Managementul referinţelor cu

Managementul referinţelor cu TUTORIALE DE CULTURA INFORMAŢIEI Citarea surselor de informare cu instrumente software Managementul referinţelor cu Bibliotecar Lenuţa Ursachi PE SCURT Este gratuit Poţi adăuga fişiere PDF Poţi organiza,

More information

Aspecte controversate în Procedura Insolvenţei şi posibile soluţii

Aspecte controversate în Procedura Insolvenţei şi posibile soluţii www.pwc.com/ro Aspecte controversate în Procedura Insolvenţei şi posibile soluţii 1 Perioada de observaţie - Vânzarea de stocuri aduse în garanţie, în cursul normal al activității - Tratamentul leasingului

More information

Evoluția pieței de capital din România. 09 iunie 2018

Evoluția pieței de capital din România. 09 iunie 2018 Evoluția pieței de capital din România 09 iunie 2018 Realizări recente Realizări recente IPO-uri realizate în 2017 și 2018 IPO în valoare de EUR 312.2 mn IPO pe Piața Principală, derulat în perioada 24

More information

NOTE PRIVIND MODELAREA MATEMETICĂ ÎN REGIM CVASI-DINAMIC A UNEI CLASE DE MICROTURBINE HIDRAULICE

NOTE PRIVIND MODELAREA MATEMETICĂ ÎN REGIM CVASI-DINAMIC A UNEI CLASE DE MICROTURBINE HIDRAULICE NOTE PRIVIND MODELAREA MATEMETICĂ ÎN REGIM CVASI-DINAMIC A UNEI CLASE DE MICROTURBINE HIDRAULICE Eugen DOBÂNDĂ NOTES ON THE MATHEMATICAL MODELING IN QUASI-DYNAMIC REGIME OF A CLASSES OF MICROHYDROTURBINE

More information

ARHITECTURA CALCULATOARELOR LABORATOR PROGRAMĂ ANALITICĂ OBIECTIVE CURS. Obiective educaţionale: Profesor Mihai ROMANCA

ARHITECTURA CALCULATOARELOR LABORATOR PROGRAMĂ ANALITICĂ OBIECTIVE CURS. Obiective educaţionale: Profesor Mihai ROMANCA ARHITECTURA CALCULATOARELOR Profesor Mihai ROMANCA Departamentul Automatică, Electronică şi Calculatoare email: romanca@unitbv.ro Web page curs: http://vega.unitbv.ro/~romanca/calc OBIECTIVE CURS Introducere

More information

Contact Center, un serviciu cri/c!

Contact Center, un serviciu cri/c! Contact Center, un serviciu cri/c! CASE STUDY: Apa Nova Cisco Unified Contact Center Enterprise Agenda Prezentării Ø Perspec/va de business Ø Despre noi Ø Cerinţe de business Ø Opţiunea Apa Nova Ø Beneficii

More information

MODELUL UNUI COMUTATOR STATIC DE SURSE DE ENERGIE ELECTRICĂ FĂRĂ ÎNTRERUPEREA ALIMENTĂRII SARCINII

MODELUL UNUI COMUTATOR STATIC DE SURSE DE ENERGIE ELECTRICĂ FĂRĂ ÎNTRERUPEREA ALIMENTĂRII SARCINII MODELUL UNUI COMUTATOR STATIC DE SURSE DE ENERGIE ELECTRICĂ FĂRĂ ÎNTRERUPEREA ALIMENTĂRII SARCINII Adrian Mugur SIMIONESCU MODEL OF A STATIC SWITCH FOR ELECTRICAL SOURCES WITHOUT INTERRUPTIONS IN LOAD

More information

Calculatoare Numerice II Interfaţarea unui dispozitiv de teleghidare radio cu portul paralel (MGSH Machine Guidance SHell) -proiect-

Calculatoare Numerice II Interfaţarea unui dispozitiv de teleghidare radio cu portul paralel (MGSH Machine Guidance SHell) -proiect- Universitatea Politehnica Bucureşti Facultatea de Automaticăşi Calculatoare Calculatoare Numerice II Interfaţarea unui dispozitiv de teleghidare radio cu portul paralel (MGSH Machine Guidance SHell) -proiect-

More information

ANTICOLLISION ALGORITHM FOR V2V AUTONOMUOS AGRICULTURAL MACHINES ALGORITM ANTICOLIZIUNE PENTRU MASINI AGRICOLE AUTONOME TIP V2V (VEHICLE-TO-VEHICLE)

ANTICOLLISION ALGORITHM FOR V2V AUTONOMUOS AGRICULTURAL MACHINES ALGORITM ANTICOLIZIUNE PENTRU MASINI AGRICOLE AUTONOME TIP V2V (VEHICLE-TO-VEHICLE) ANTICOLLISION ALGORITHM FOR VV AUTONOMUOS AGRICULTURAL MACHINES ALGORITM ANTICOLIZIUNE PENTRU MASINI AGRICOLE AUTONOME TIP VV (VEHICLE-TO-VEHICLE) 457 Florin MARIAŞIU*, T. EAC* *The Technical University

More information

Solutii avansate pentru testarea si diagnoza masinilor industriale.

Solutii avansate pentru testarea si diagnoza masinilor industriale. Solutii avansate pentru testarea si diagnoza masinilor industriale 15 ani de activitate in domeniul procesarii numerice a semnalelor Solutii de inalta acuratete pentru analiza sunetelor, vibratiilor si

More information

CAIETUL DE SARCINI Organizare evenimente. VS/2014/0442 Euro network supporting innovation for green jobs GREENET

CAIETUL DE SARCINI Organizare evenimente. VS/2014/0442 Euro network supporting innovation for green jobs GREENET CAIETUL DE SARCINI Organizare evenimente VS/2014/0442 Euro network supporting innovation for green jobs GREENET Str. Dem. I. Dobrescu, nr. 2-4, Sector 1, CAIET DE SARCINI Obiectul licitaţiei: Kick off,

More information

Baze de date distribuite și mobile

Baze de date distribuite și mobile Universitatea Constantin Brâncuşi din Târgu-Jiu Facultatea de Inginerie Departamentul de Automatică, Energie şi Mediu Baze de date distribuite și mobile Lect.dr. Adrian Runceanu Curs 3 Model fizic şi model

More information

Eurotax Automotive Business Intelligence. Eurotax Tendințe în stabilirea valorilor reziduale

Eurotax Automotive Business Intelligence. Eurotax Tendințe în stabilirea valorilor reziduale Eurotax Automotive Business Intelligence Eurotax Tendințe în stabilirea valorilor reziduale Conferinta Nationala ALB Romania Bucuresti, noiembrie 2016 Cristian Micu Agenda Despre Eurotax Produse si clienti

More information

METODE DE EVALUARE A IMPACTULUI ASUPRA MEDIULUI ŞI IMPLEMENTAREA SISTEMULUI DE MANAGEMENT DE MEDIU

METODE DE EVALUARE A IMPACTULUI ASUPRA MEDIULUI ŞI IMPLEMENTAREA SISTEMULUI DE MANAGEMENT DE MEDIU UNIVERSITATEA POLITEHNICA BUCUREŞTI FACULTATEA ENERGETICA Catedra de Producerea şi Utilizarea Energiei Master: DEZVOLTAREA DURABILĂ A SISTEMELOR DE ENERGIE Titular curs: Prof. dr. ing Tiberiu APOSTOL Fond

More information

CERERI SELECT PE O TABELA

CERERI SELECT PE O TABELA SQL - 1 CERERI SELECT PE O TABELA 1 STUD MATR NUME AN GRUPA DATAN LOC TUTOR PUNCTAJ CODS ---- ------- -- ------ --------- ---------- ----- ------- ---- 1456 GEORGE 4 1141A 12-MAR-82 BUCURESTI 2890 11 1325

More information

R O M Â N I A CURTEA CONSTITUŢIONALĂ

R O M Â N I A CURTEA CONSTITUŢIONALĂ R O M Â N I A CURTEA CONSTITUŢIONALĂ Palatul Parlamentului Calea 13 Septembrie nr. 2, Intrarea B1, Sectorul 5, 050725 Bucureşti, România Telefon: (+40-21) 312 34 84; 335 62 09 Fax: (+40-21) 312 43 59;

More information

Laborator 07. Procesorul MIPS versiune pe 16 biți, cu un ciclu de ceas pe instrucțiune

Laborator 07. Procesorul MIPS versiune pe 16 biți, cu un ciclu de ceas pe instrucțiune Laborator 07 Procesorul MIPS versiune pe 16 biți, cu un ciclu de ceas pe instrucțiune Unitatea de Instruction Execute EX / Unitatea de Memorie MEM / Unitatea Write-Back WB 0. Resurse minimale necesare!

More information

CHAMPIONS LEAGUE 2017 SPONSOR:

CHAMPIONS LEAGUE 2017 SPONSOR: NOUA STRUCTURĂ a Ch League Pe viitor numai fosta divizie A va purta numele Champions League. Fosta divizie B va purta numele Challenger League iar fosta divizie C se va numi Promotional League. CHAMPIONS

More information

Candlesticks. 14 Martie Lector : Alexandru Preda, CFTe

Candlesticks. 14 Martie Lector : Alexandru Preda, CFTe Candlesticks 14 Martie 2013 Lector : Alexandru Preda, CFTe Istorie Munehisa Homma - (1724-1803) Ojima Rice Market in Osaka 1710 devine si piata futures Parintele candlesticks Samurai In 1755 a scris The

More information

O alta abordare in calculul distribuit este memoria virtuală distribuită (Distributed Shared Memory DSM). Din nefericire maşinile paralele cu memorie

O alta abordare in calculul distribuit este memoria virtuală distribuită (Distributed Shared Memory DSM). Din nefericire maşinile paralele cu memorie DSM O alta abordare in calculul distribuit este memoria virtuală distribuită (Distributed Shared Memory DSM). Din nefericire maşinile paralele cu memorie comună fie au memoria fizică nescalabilă, fie lucrează

More information

Ce pot face pe hi5? Organizare si facilitati. Pagina de Home

Ce pot face pe hi5? Organizare si facilitati. Pagina de Home Ce este Hi5!? hi5 este un website social care, în decursul anului 2007, a fost unul din cele 25 cele mai vizitate site-uri de pe Internet. Compania a fost fondată în 2003 iar pana in anul 2007 a ajuns

More information

The driving force for your business.

The driving force for your business. Performanţă garantată The driving force for your business. Aveţi încredere în cea mai extinsă reţea de transport pentru livrarea mărfurilor în regim de grupaj. Din România către Spania în doar 5 zile!

More information

Lucrarea de laborator nr. 4

Lucrarea de laborator nr. 4 Metode merice - Lucrarea de laborator 4 Lucrarea de laborator nr. 4 I. Scopul lucrării Elemente de programare în MAPLE II. III. Conţinutul lucrării 1. Atribuirea. Decizia. Structuri repetitive. 2. Proceduri

More information

O abordare Data Mining pentru detectarea accesului neautorizat la baza de date.

O abordare Data Mining pentru detectarea accesului neautorizat la baza de date. O abordare Data Mining pentru detectarea accesului neautorizat la baza de date. 1. Introducere 2. Lucrări asemănătoare 3. Modelul de clasificare 4. Dependenţele intre date 4.1 Terminologia dependenţei

More information

O ALTERNATIVĂ MODERNĂ DE ÎNVĂŢARE

O ALTERNATIVĂ MODERNĂ DE ÎNVĂŢARE WebQuest O ALTERNATIVĂ MODERNĂ DE ÎNVĂŢARE Cuvinte cheie Internet WebQuest constructivism suport educational elemente motivationale activitati de grup investigatii individuale Introducere Impactul tehnologiilor

More information

Grafuri bipartite. Lecție de probă, informatică clasa a XI-a. Mihai Bărbulescu Facultatea de Automatică și Calculatoare, UPB

Grafuri bipartite. Lecție de probă, informatică clasa a XI-a. Mihai Bărbulescu Facultatea de Automatică și Calculatoare, UPB Grafuri bipartite Lecție de probă, informatică clasa a XI-a Mihai Bărbulescu b12mihai@gmail.com Facultatea de Automatică și Calculatoare, UPB Colegiul Național de Informatică Tudor Vianu București 27 februarie

More information

PACHETE DE PROMOVARE

PACHETE DE PROMOVARE PACHETE DE PROMOVARE Școala de Vară Neurodiab are drept scop creșterea informării despre neuropatie diabetică și picior diabetic în rândul tinerilor medici care sunt direct implicați în îngrijirea și tratamentul

More information

În continuare vom prezenta unele dintre problemele de calcul ale numerelor Fibonacci.

În continuare vom prezenta unele dintre problemele de calcul ale numerelor Fibonacci. O condiţie necesară şi suficientă ca un număr să fie număr Fibonacci Autor: prof. Staicu Ovidiu Ninel Colegiul Economic Petre S. Aurelian Slatina, jud. Olt 1. Introducere Propuse de Leonardo Pisa în 1202,

More information

Lucrarea nr. 7. Configurarea reţelelor în Linux

Lucrarea nr. 7. Configurarea reţelelor în Linux Lucrarea nr. 7 Configurarea reţelelor în Linux Scopul acestei lucrări este înţelegerea modului de configurare a reţelelor în sistemul de operare Linux precum şi înţelegerea funcţionării protocoalelor de

More information

A Compared Aproach: ASP versus PHP

A Compared Aproach: ASP versus PHP 22 A Compared Aproach: ASP versus PHP Asist.dr. Liana-Maria STANCA Catedra de Informatică Economică, Universitatea Babeş-Bolyai, Cluj-Napoca In the development process of electronic business theory, we

More information

Sisteme de operare 19. Gestiunea memoriei

Sisteme de operare 19. Gestiunea memoriei Platformăde e-learning și curriculăe-content pentru Sisteme de operare 19. Gestiunea memoriei Ierarhia memoriei 2 Memoria principală De obicei RAM (Random Access Memory) Menținerea mai multor procese Ce

More information

earning every day-ahead your trust stepping forward to the future opcom operatorul pie?ei de energie electricã și de gaze naturale din România Opcom

earning every day-ahead your trust stepping forward to the future opcom operatorul pie?ei de energie electricã și de gaze naturale din România Opcom earning every day-ahead your trust stepping forward to the future opcom operatorul pie?ei de energie electricã și de gaze naturale din România Opcom RAPORT DE PIA?Ã LUNAR MARTIE 218 Piaţa pentru Ziua Următoare

More information

Metoda de programare BACKTRACKING

Metoda de programare BACKTRACKING Metoda de programare BACKTRACKING Sumar 1. Competenţe............................................ 3 2. Descrierea generală a metodei............................. 4 3......................... 7 4. Probleme..............................................

More information

Updating the Nomographical Diagrams for Dimensioning the Concrete Slabs

Updating the Nomographical Diagrams for Dimensioning the Concrete Slabs Acta Technica Napocensis: Civil Engineering & Architecture Vol. 57, No. 1 (2014) Journal homepage: http://constructii.utcluj.ro/actacivileng Updating the Nomographical Diagrams for Dimensioning the Concrete

More information

Proiectarea Sistemelor Software Complexe

Proiectarea Sistemelor Software Complexe Proiectarea Sistemelor Software Complexe Curs 3 Principii de Proiectare Orientată pe Obiecte Principiile de proiectare orientată pe obiecte au fost formulate pentru a servi ca reguli pentru evitarea proiectării

More information

Class D Power Amplifiers

Class D Power Amplifiers Class D Power Amplifiers A Class D amplifier is a switching amplifier based on pulse-width modulation (PWM) techniques Purpose: high efficiency, 80% - 95%. The reduction of the power dissipated by the

More information

Eficiența energetică în industria românească

Eficiența energetică în industria românească Eficiența energetică în industria românească Creșterea EFICIENȚEI ENERGETICE în procesul de ardere prin utilizarea de aparate de analiză a gazelor de ardere București, 22.09.2015 Karsten Lempa Key Account

More information

Reţele de calculatoare

Reţele de calculatoare Reţele de calculatoare #2 Arhitectura reţelelor de calculatoare 2017 Adrian Runceanu www.runceanu.ro/adrian copyright@www.adrian.runceanu.ro Curs 2 Arhitectura reţelelor de calculatoare 27.02.2017 Reţele

More information

Relational and Object-Oriented Methodology in Data Bases Systems

Relational and Object-Oriented Methodology in Data Bases Systems Revista Informatica Economică nr.3(39)/2006 141 Relational and Object-Oriented Methodology in Data Bases Systems Marian CRISTESCU, Gabriel SOFONEA, Eugen COJOCARIU Economic Informatics Department Lucian

More information

Preţul mediu de închidere a pieţei [RON/MWh] Cota pieţei [%]

Preţul mediu de închidere a pieţei [RON/MWh] Cota pieţei [%] Piaţa pentru Ziua Următoare - mai 217 Participanţi înregistraţi la PZU: 356 Număr de participanţi activi [participanţi/lună]: 264 Număr mediu de participanţi activi [participanţi/zi]: 247 Preţ mediu [lei/mwh]:

More information

LIDER ÎN AMBALAJE EXPERT ÎN SISTEMUL BRAILLE

LIDER ÎN AMBALAJE EXPERT ÎN SISTEMUL BRAILLE LIDER ÎN AMBALAJE EXPERT ÎN SISTEMUL BRAILLE BOBST EXPERTFOLD 80 ACCUBRAILLE GT Utilajul ACCUBRAILLE GT Bobst Expertfold 80 Aplicarea codului Braille pe cutii a devenit mai rapidă, ușoară și mai eficientă

More information

M C I O H L BAZE DE CUNOŞTINŢE A H E O L N S I S T E M E D E R E P R E Z E N A R E Ş I P R O C E S A R E A A C U N O Ş T I N Ţ E L O R

M C I O H L BAZE DE CUNOŞTINŢE A H E O L N S I S T E M E D E R E P R E Z E N A R E Ş I P R O C E S A R E A A C U N O Ş T I N Ţ E L O R BAZE DE CUNOŞTINŢE S I S T E M E D E R E P R E Z E N A R E Ş I P R O C E S A R E A C U N O Ş T I N Ţ E L O R M C I O H L A H E O L N A TIPURI DE CUNOŞTINŢE Pentru a putea rezolva problemele complexe de

More information

SISTEME DE CALCUL. LIMBAJ DE ASAMBLARE. SIMULATORUL QTSPIM UAL DPE. Fig.1. Structura unui sistem de calcul

SISTEME DE CALCUL. LIMBAJ DE ASAMBLARE. SIMULATORUL QTSPIM UAL DPE. Fig.1. Structura unui sistem de calcul SISTEME DE CALCUL. LIMBAJ DE ASAMBLARE. SIMULATORUL QTSPIM I. Sisteme de calcul 1. Arhitectura generală a unui sistem de calcul DPI UCC MEM Canale I/E DPI/E, MEM externe UAL DPE UCP UC Fig.1. Structura

More information

SISTEME DE CALCUL. LIMBAJ DE ASAMBLARE. SIMULATORUL PCSPIM UAL DPE. Fig.1. Structura unui sistem de calcul

SISTEME DE CALCUL. LIMBAJ DE ASAMBLARE. SIMULATORUL PCSPIM UAL DPE. Fig.1. Structura unui sistem de calcul SISTEME DE CALCUL. LIMBAJ DE ASAMBLARE. SIMULATORUL PCSPIM I. Sisteme de calcul 1. Arhitectura generală a unui sistem de calcul DPI UCC MEM Canale I/E DPI/E, MEM externe UAL DPE UCP UC Fig.1. Structura

More information

Nume şi Apelativ prenume Adresa Număr telefon Tip cont Dobânda Monetar iniţial final

Nume şi Apelativ prenume Adresa Număr telefon  Tip cont Dobânda Monetar iniţial final Enunt si descriere aplicatie. Se presupune ca o organizatie (firma, banca, etc.) trebuie sa trimita scrisori prin posta unui numar (n=500, 900,...) foarte mare de clienti pe care sa -i informeze cu diverse

More information

Reţele de calculatoare

Reţele de calculatoare Universitatea Constatin Brâncuşi din Târgu-Jiu Facultatea de Inginerie Departamentul de Automatică, Energie şi Mediu Reţele de calculatoare Lector dr. Adrian Runceanu An universitar 2013-2014 Curs 1 Noţiuni

More information

Ghid de utilizare a Calculatorului valorii U

Ghid de utilizare a Calculatorului valorii U Ghid de utilizare a Calculatorului valorii U la Apelul de Propuneri de Proiecte Nr.3 pentru Instituțiile din Sectorul Public pentru investiții în Eficiență Energetică și Surse de Energie Regenerabilă Versiunea

More information

Mihai ROMANCA. Microprocesoare şi microcontrolere

Mihai ROMANCA. Microprocesoare şi microcontrolere Mihai ROMANCA Microprocesoare şi microcontrolere Universitatea Transilvania din Braşov 2015 Cuprins 1 CUPRINS Cuprins... 1 Cuvânt înainte... 3 1. INTRODUCERE ÎN ARHITECTURA MICROPROCESOARELOR... 5 1.1.

More information