Retea de Prelucrarea Distribuita a Imaginilor
Cuprins
INTRODUCERE
Procesul de informatizare se caracterizează prin apariția și dezvoltarea în interiorul diverselor organizații a unor rețele de calculatoare care, de cele mai multe ori, sunt sau devin eterogene. Diversitatea se manifestă fie la nivel hardware, fie al sistemului de operare, fie la ambele. Această evoluție nu trebuie să sperie, pentru că este un proces natural, care ține cont de evoluția explozivă a domeniului, dominată la momente succesive de timp de tehnologii diferite.
După ce prin crearea rețelei s-a reușit partajarea informației și comunicarea între utilizatori și programe, următoarea întrebare logică a oricărui proprietar sau administrator de rețea este dacă resursele instalate nu pot fi folosite eficient și la execuția aplicațiilor. Avem în vedere creșterea indicelui de utilizare, ca și a numărului de aplicații executate în unitatea de timp. De multe ori, observăm într-o organizație urmatoarea situație paradoxală: unele calculatoare sunt neutilizate, în timp ce altele nu fac față prelucrărilor de date. Evident, nu este vorba de acele aplicații, cum sunt bazele de date, care fac apel la anumite resurse dedicate. În interiorul unei firme, colectivul de contabilitate folosește calculatoarele numai un interval limitat de timp. În timp ce colectivul de proiectare a unui produs nou are nevoie de resurse puternice pâna la realizarea obiectivului. La fel, într-o universitate, un colectiv folosește mai puțin resursele sale de calcul, în timp ce altul își pune problema achiziționării unor resurse suplimentare.
Utilizarea resurselor este un aspect. Altul se referă la momentul deciderii cumpărării unor noi calculatoare. Orice evoluție naturală presupune întâi epuizarea posibilităților sistemelor instalate, cu eventuala amortizare a investiției, dupa care, apoi, se pune problema modernizării.
În fine, există profiluri diferite de utilizatori și de aplicații. Printr-o administrare inteligentă a acestora, se poate ajunge la un grad ridicat de satisfacere a cerințelor lor, simultan cu un indice apropiat de maximum pentru utilizarea resurselor de calcul.
Pentru administrarea eficientă a resurselor eterogene ale unui sistem distribuit, este necesar un software adecvat, care să pună în practica strategii de gestiune a resurselor, ținând cont, în același timp, de nivelele diferite de importanță și termene de execuție ale aplicațiilor din sistem. Eficiența soft-ului de administrare este dictată de cele două componente ale sale:
Resource tasking, care selectează lucrările ce urmează a fi lansate în execuție, decide asupra resurselor ce vor fi folosite și asupra procentului din resursele partajate care va fi alocat fiecărei lucrări;
Workload regulation, care decide alocarea de resurse, astfel încât resursele partajate să fie în concordanță cu obiectivele de administrare a resurselor aplicațiile cele mai importante, sau cu termenele cele mai apropiate vor obține un procent adecvat din resurse.
Componența de resource tasking utilizează importanța relativă a aplicațiilor ce candidează pentru execuție, corelează instanțe concurente ale acelorași utilizatori, aplicații și proiecte în vederea implementării eficiente a strategiilor de partajare a resurselor. Sistemele care nu au atributele prezentate mai sus, vor suferi pe mai multe planuri:
Aplicații importante/urgente pot fi întârziate sau "sufocate" din lipsa resurselor, în timp ce alte aplicații sunt inițiate și executate;
Utilizatori neautorizați pot domina resursele partajate și determina, în consecință, o scădere a productivității, prin lansarea în execuție a celei mai mari cantități de programe;
Un utilizator poate depăși în timp nivelul de utilizare al resurselor, pe care și 1-a propus.
Aceste efecte sunt contrare politicilor de utilizare a resurselor, care urmăresc maximalizarea beneficiului întregii comunități de utilizatori ai sistemului distribuit.
Pentru a rezolva problemele prezentate, multe organizații se bazează pe intervenția manuală, prin dedicarea resurselor unor funcții selectate, sau prin păstrarea unor rezerve în utilizarea resurselor, mai mari decât este necesar.
O altă problemă importantă este echilibrarea sarcinilor de lucru între resursele partajate, prin luarea unor decizii inteligente de alocare, atunci când lucrările sunt trimise pentru execuție. Practica curentă este de a folosi ca parametru încărcarea curentă a fiecărui calculator (de exemplu, numărul de procese aflate în coada proceselor gata de execuție, sau numărul de utilizatori conectați), fără a se ține cont de caracteristicile proceselor în execuție (priorități, urgent, utilizatori). Utilizarea exclusivă a incărcării calculatorului poate fi sursa unor decizii ineficiente de alocare a aplicațiilor la calculatoare, care determină dezechilibre între calculatoare și, în consecință, timpi de execupie mai mari. De exemplu, o aplicație urgentă poate fi alocată unui calculator mai slab ca performanță, doar pentru ca momentan acesta era slab utilizat. Sau, resursele de calcul cele mai putemice sunt ignorate pentru că performanțele lor practice sunt ignorate.
Inițial, o aplicație este alocată unui calculator dat, fără a se ține cont de evoluția sa dinamică și, posibil, imprevizibilă. Aceasta înseamnă că utilizarea resurselor poate să difere în mod semnificativ, după un interval de timp. De aceea, componenta de workload regulation este esențială pentru implementarea strategiilor necesare. Din păcate, cele mai multe sisteme au în vedere numai alocarea inițială, ignorând evoluția ulterioară a aplicației și a sistemului distribuit, în ansamblu.
Sistemele, care încearcă să trateze aspectul importanței relative sau urgenței unei aplicații, nu sunt eficiente deoarece folosesc strategii de lansare în execuție cu prioritate, fără a urmări în continuare regularizarea sarcinii de lucru.
Pentru a îmbunătăți gradul de utilizare al resurselor, se încearcă uneori modificarea manuală a priorităților lucrărilor. Această operație poate fi dificilă, pentru că presupune că operatorul a identificat poziția tuturor proceselor componente și poate executa modificările pe toate calculatoarele gazdă. Mai mult, după toate aceste modificări, este posibil ca efectul să nu fie cel scontat controlul prioritații nu are efecte previzibile și proporționale cu utilizarea resurselor.
Unele aplicații, mari consumatoare de resurse, sunt amânate pentru intervale de timp când nu există o încărcare mare a sistemului (noaptea, la sfarșit de săptămână), deși ele ar putea beneficia de perioadele de neutilizare din cadrul intervalului obișnuit de lucru.
1 ANALIZA PRINCIPIILOR DE ORGANIZARE A SISTEMELOR DISTRIBUITE
1.1 Sisteme distribuite
1.1.1 Procesarea distribuită
Pînă în prezent au avut loc o serie de schimbări importante în lumea informaticii. Una dintre ele a fost trecerea de pe mainframe-uri pe PC. Astăzi asistăm la o nouă schimbare majoră – impunerea rețelelor de calculatoare. Dar acest lucru înseamnă printre altele și procesare distribuită.
De-acum încolo putem afirma ca Internetul este o prezență zilnică în viața noastră. Când sosești dimineața la locul de muncă, în primul rînd verifici dacă ai primit scrisori electronice în cutia poștală. Or, nu mai este un secret pentru nimeni faptul că în acest proces intervine cel puțn un server și un client.
Dacă jocurile pe calculator implicau pînă acum existența unui nucleu grafic performant, în prezent iau amploare jocurile distribute care acceptă mai mulți participanți. Stînd în fața calculatorului de acasă te conectezi prin modem la un calculator gazdă pe care rulează respectivul joc. Pe ecranul tău cît și pe ecranul celorlalți jucători vor apărea pozițiile actualizate ale tuturor participanților. Ceea ce trebuie relevat în acest context este existența unui nucleu pentru susținerea comunicațiilor între modulele jocului (pe lînga nucleul de grafică). Raportîndu-ne la domeniul militar, aceste “jocuri distribuite” devin adevărate medii de simulare ale unor situații de luptă.
Tot un domeniu al procesării distribuite este și controlul proceselor – altfel spus controlul cu ajutorul calculatorului a modulelor instalațiilor industriale. Programe pentru controlul proceselor sunt utilizate în uzinele chimice, în rafinării, în complexele pentru producerea energiei nucleare și în alte situații cînd se cere urmărirea și organizarea unor procese complexe.
Bineînțeles că exemplele ar putea continua dar ne oprim aici pentru a trage cîteva concluzii referitoare la modul în care putem defini ceea ce reprezintă procesarea distribuită.
Un calculator avînd un singur procesor și care rulează un singur program reprezintă exemplul cel mai concludent pentru definirea unui sistem monoprocesor clasic. Este normal că, cel puțin intuitiv, în cazul unor arhitecturi complexe să avem de-a face cu sisteme care conțin mai multe procesoare, interconectate, care conlucrează la atingerea scopului final. În acest al doilea caz avem de-a face cu sisteme multiprocesor care se bazează în funcționare pe principiul paralelismului.
Dacă luăm în considerare sensul curent al cuvîntului paralelism, în cazul informaticii primul sens pe care 1-am putea atribui cuvîntului ar fi cel de desfășurare a unor activități în același timp – activități paralele. Practic nu ne-am situa prea departe de sensul real. Putem vorbi de paralelism chiar și la nivelul unui microprocesor. Mai exact existența mai multor regiștri acumulatori permite microprocesorului să execute mai multe instrucțiuni în același timp, în măsura în care una dintre instrucțiuni nu depinde de rezultatul celeilalte. Mergînd mai departe putem să ne referim la cazul în care avem de-a face cu un server de baze de date care la nivel logic este unul singur iar la nivel fizic este un program care rulează pe mai multe sisteme (lucru invizibil pentru utilizator). Fără a ne extinde prea mult trebuie spus aici că putem vorbi despre paralelism la nivel software și la nivel hardware. Apoi, din alt punct de vedere vorbim despre paralelism la nivel arhitectural și la nivel logic.
Astăzi este acceptată idea conform căreia în funcție de modul de raportare a elementelor de procesare la memoria disponibilă vorbim despre procesare paralelă sau despre procesare distribuită. Pentru a putea realiza o diferență netă între cele două tipuri de sisteme vom mai apela la cîteva aspecte teoretice.
Din punct de vedere conceptual, funcționarea unui sistem de calcul poate fi vazută ca un flux de instrucțiuni a căror execuție este inițiată de introducerea datelor de prelucrat și încheiată cu obținerea rezultatelor scontate. În raport cu acest punct de vedere, arhitecturile sistemelor de calcul pot fi caracterizate în funcție de fluxul instrucțiunilor executate de unitatea sau unitățile de calcul și de fluxul datelor reprezentînd secvența de date asupra căreia operează fluxul instrucțiunilor.
Sînt unanim recunoscute patru tipuri de sisteme de calcul: flux de instrucțiuni și flux de date unice (SISD – Single Instruction Single Data) sau altfel spus sisteme monoprocesor clasice; flux de instrucțiuni unic și fluxuri de date multiple (SIMD – Single Instruction Multiple Data), sisteme cu procesoare paralele; fluxuri de instrucțiuni multiple și flux de date unic (MISD -Multiple Instruction Single Data) sau sisteme cu procesoare pipeline; fluxuri de instrucțiuni și fluxuri de date multiple (MIMD – Multiple Instruction Multiple Data) sau sisteme cu arhitecturi multiprocesor și rețele de sisteme de calcul.
Sistemele de tip MIMD sunt constituite dintr-un ansamblu de elemente de prelucrare care au acces la o memorie centrală comună – în acest caz le numim sisteme cu interconectare strînsă.
Dacă elementele de prelucrare dispun de resurse proprii și comunicarea între ele se face doar pe baza unor mesaje spunem că avem de-a face cu sisteme cu interconectare slabă.
Încercînd să facem legatura cu noțiunile pe care dorim să le definim, sistemele cu interconectare strînsa reprezintă sistemele cu procesare paralelă iar sistemele cu interconectare sl conceptual, funcționarea unui sistem de calcul poate fi vazută ca un flux de instrucțiuni a căror execuție este inițiată de introducerea datelor de prelucrat și încheiată cu obținerea rezultatelor scontate. În raport cu acest punct de vedere, arhitecturile sistemelor de calcul pot fi caracterizate în funcție de fluxul instrucțiunilor executate de unitatea sau unitățile de calcul și de fluxul datelor reprezentînd secvența de date asupra căreia operează fluxul instrucțiunilor.
Sînt unanim recunoscute patru tipuri de sisteme de calcul: flux de instrucțiuni și flux de date unice (SISD – Single Instruction Single Data) sau altfel spus sisteme monoprocesor clasice; flux de instrucțiuni unic și fluxuri de date multiple (SIMD – Single Instruction Multiple Data), sisteme cu procesoare paralele; fluxuri de instrucțiuni multiple și flux de date unic (MISD -Multiple Instruction Single Data) sau sisteme cu procesoare pipeline; fluxuri de instrucțiuni și fluxuri de date multiple (MIMD – Multiple Instruction Multiple Data) sau sisteme cu arhitecturi multiprocesor și rețele de sisteme de calcul.
Sistemele de tip MIMD sunt constituite dintr-un ansamblu de elemente de prelucrare care au acces la o memorie centrală comună – în acest caz le numim sisteme cu interconectare strînsă.
Dacă elementele de prelucrare dispun de resurse proprii și comunicarea între ele se face doar pe baza unor mesaje spunem că avem de-a face cu sisteme cu interconectare slabă.
Încercînd să facem legatura cu noțiunile pe care dorim să le definim, sistemele cu interconectare strînsa reprezintă sistemele cu procesare paralelă iar sistemele cu interconectare slabă se numesc sisteme cu prelucrare distribuită. Ele reprezintă un ansamblu de elemente independente de calcul, interconectate care cooperează în mod transparent pentru realizarea funcțiilor de control și prelucrare.
Interacțiunile dintre procesele multiple, care acționează simultan într-un sistem cu prelucrare distribuită, îmbracă una din formele urmatoare: cooperare în scopul de a realiza în comun o sarcină; concurentă, rezultat al accesului mai multor procese la o resursă unică.
Coexistent proceselor paralele într-un sistem cu prelucrare distribuită, distribuirea și execuția lor dislribuită impun necesitatea controlului interacțiunii dintre acestea. În acest sens putem vorbi de control centralizat și control distribuit.
În cazul sistemelor secvențiale s-a beneficiat de experiența teoretică și practică de decenii. Altfel spus, s-a ajuns la o stabilitate relativă în privința elementelor de exprimare propuse de limbajele de programare: noțiunea de tip, natura principalelor instrucțiuni (atribuire, iterație, condiție, etc.), diferite moduri de abstractizare și modularizare (funcție, procedură, module, etc.). Există o serie de tehnologii pentru analiza și implementarea programelor, traducerea lor în cod mașină și nu în ultima instanță pentru testare. Practic vorbind există toate premisele pentru a vorbi despre “arta programării” sistemelor secvențiale.
Pentru sistemele de calcul care utilizează principiul paralelismului situația se schimbă. Cu alte cuvinte este nevoie de definirea unor concepte noi, specifice prelucrărilor paralele. Din acest punct de vedere noțiunea de proces este cea care vine să întregească, pe cît posibil, tabloul conceptelor procesării distribuite. Noțiunea de proces, ca entitate de bază în specificarea și structurarea sistemelor de calcul paralele trebuie să fie fundamentată și recunoscută cu aceleași drepturi ca entitațile de funcție, procedură, modul sau tip din cazul sistemelor secvențiale. Procesele sînt capabile în general să funcționeze independent unele de altele, acest lucru favorizînd evoluțiile în paralel în raport cu ansamblul sistemului. Bineînțeles că trebuie să se țină seama de toate implicațiile privind sincronizarea proceselor, simultaneitatea și nedeterminările inevitabile.
Procesul face apel în afara instrucțiunilor obișnuite, la instrucțiuni de comunicație a mesajelor. Instrucțiunile de transmisie și de recepție transportă mesaje de la proces la proces, devenind un nou mod de comunicare a informației dintr-un context în altul, diferit de tradiționalul transfer de parametri în cazul apelului de funcții sau proceduri în sistemele de calcul secvențiale. Noțiunea de procese comunicante este deja identificată, chiar dacă mai smt încă multe probleme deschise referitoare la semantica acestor entități și la mijioacele lingvistice necesare descrierii lor.
Cercetările și experimentările întreprinse în timp au condus la delimitarea problematicii sistemelor cu prelucrare distribuită, la fundamentarea conceptului de distribuire a prelucrării și a datelor. Cu toate ca în literatura de specialitate se întîlnesc numeroase definiții, mai mult sau mai puțin complete, există o accepțiune cvasi-unanimă în cercurile științiifice de specialitate ca apartenența unui sistem de calcul la o clasă sau alta de sisteme denumite în general “distribuite” trebuie apreciată prin prisma următoarelor criterii:
1. Multitudinea resurselor fizice și logice care să satisfacă cerințele de prelucrare ale sistemului.
2. Distribuirea fizică a componentelor sistemului.
3. Viziunea globală, unitară asupra sistemului.
4. Independența relativă (cooperantă) a componentelor sistemului.
5. Transparența structurii față de interfața de utilizare a acestuia.
Primul criteriu enunțat se referă la faptul că sistemul distribuit trebuie să posede un ansamblu de resurse care să coopereze la atingerea scopului declarat al sistemului. Un aspect foarte important se referă la modularizarea sistemului distribuit. Mai clar spus, reconfigurarea unor componente impusă la un moment dat de diverse condiții de funcționare, trebuie să aibă loc fără afectarea funcționalității celorlalte resurse.
În general resursele sistemului pot fi de ordin general sau resurse specializate. Caracterul general al resurselor poate conduce la o proiectare mai facilă a acestuia și la o flexibilitate mărită. Specializarea unor resurse impune introducerea unor mecanisme adecvate de partajare a acestora.
Criteriul al doilea impune existența unui suport de comunicație care să permită distribuirea fizică între componentele sistemului. Un lucru important de amintit în acest context privește faptul că nu se stabilesc limite stricte pentru aria geografică de interconectare dar, în unele cazuri, apar limitări din punct de vedere al vitezei de comunicare. Arhitecturile rezultate pe baza acestui criteriu se încadrează în categoria rețelelor locale.
Cel mai important aspect privitor la distribuirea fizică și intercomunicarea dintre componente îl constituie transferul explicit de mesaje, pe bază de protocoale de comunicație, unitatea de transfer fiind mesajul. O consecință importantă a acestei ipoteze o constituie caracterul variabil al întîrzierilor de transfer al mesajelor cu consecințe directe asupra observabilității cronologiei evenimentelor. Elementele de prelucrare au spații de prelucrare disjuncte, memoria partajată fiind exclusă ca mecanism de comunicație (memoria partajată nu este practică în sistemele distribuite).
Criteriul al treilea exprimă faptul ca sistemul distribuit trebuie să fie unitar din punct de vedere al prelucrării, componentele participînd la realizarea scopului propus. O astfel de strategie se poate materializa prin componente logice de control care la rîndul lor trebuie să dispună de informațiile de stare necesare. Informațiile de stare reprezintă în general evoluția sistemului în cursul tratării lucrărilor care îi sunt prezentate.
În momentul în care ne referim la informațiile de stare trebuie să avem la dispoziție și un model de reprezentare al evoluției sistemului în timp. Aceste modele se bazează pe ipoteza că este posibilă descrierea completă a stării în anumite momente determinate. În acest caz o stare mai poate fi referită și prin intermediul sintagmei “punct observabil” (evoluția sistemului se materializează prin parcurgerea punctelor observabile).
În cazul unui sistem cu elemente multiple de prelucrare, funcționînd de o manieră asincronă, nu există un ceas comun și în consecință secvența punctelor observabile este diferită de la element la element. Durata transmisiei unui mesaj între două procese care se execută pe componente de prelucrare diferite este mare în raport cu intervalul care separă două puncte observabile ale aceleiași componente. Aici intervine problema controlului sistemului distribuit. Se ajunge la concluzia că nu este foarte potrivit nici un control centralizat și nici un control distribuit (ultimul din cauza eterogenității componentelor sistemului). Practic se apelează la serviciile unui nucleu integrator distribuit. Nucleul integrator este replicat în fiecare componență, fără să fie impuse relații de tip master-slave între componentele fizice și/sau logice ale sistemului. Se apreciază ca descentralizarea controlului, realizată de sistemele cu prelucrare distribuită, reprezintă aspectul esențial care distinge aceste sisteme de arhitecturile clasice.
Criteriul al patrulea exprimă independența componentelor sistemului și, în același timp, interacțunea lor la nivel fizic și logic. Coexistent celor două noțiuni, relativ contradictorii, este asigurată de strategiile utilizate la proiectarea nucleului integrator.
Criteriul al cincilea privește interfața dintre utilizator și sistem presupunînd transparent structurii în raport cu cererile utilizatorului. Adică, identificarea componentei sau componentelor în satisfacerea unui anumit serviciu nu trebuie să între în competența utilizatorului solicitant. Acest criteriu presupune existența unei interfețe de acces la facilitățile sistemului care să facă posibilă abstractizarea de tip “procesor unic”.
Ca o concluzie a criteriilor prezentate putem spune că un sistem cu prelucrare distribuită se definește ca fiind un ansamblu de resurse fizice și logice de calcul autonome, interconectate care coopereaza în mod transparent pentru realizarea funcțiunilor de control și prelucrare.
Vom încerca să definim “paradigmele procesarii distribuite”, să precizăm mai clar sensul acestei expresii. Prin paradigmă se înțelege un cadru care ne ajută la realizarea unor experimente în vederea precizării cît mai clare a sensurilor multiple ale problemei studiate. Deci, cu alte euvinte, prin prezentarea unor exemple concludente încercăm să stabilim sensul exact al cît mai multor aspecte privind procesarea distribuită.
Practic, procesele sunt conduse prin intermediul unei bucle de feedback care ia naștere începînd cu senzorii. Aceștia transmit programelor de control date despre condițiile în care se desfașoară procesul. În continuare, programele de control acționează asupra parametrilor de intrare ai procesului (mai bine zis asupra aparatelor care au influență asupra parametrilor de intrare a procesului. Ca urmare a modificării parametrilor de intrare se schimbă și condițiile în care se desfașoară procesul. Cu alte cuvinte, se modifică datele citite de senzori. Programele de control calculează noile valori de reglare și așa mai departe. În practică există o serie de operatori umani, programele de control a proceselor fiind utilizate pentru asistarea lor. În cazul aplicațiilor critice, cum ar fi un reactor nuclear, considerațiile privind timpul (sincronizarea modulelor aplicației) reprezintă un plus de siguranță și o necesitate.
Dacă senzorii și dispozitivele care realizează modificarea condițiilor de desfășurare a proceselor sunt atașate unor procesoare conectate într-o rețea, aplicația de control a procesului devine o aplicație distribuită.
De exemplu să pornim de la necesitatea prelucrării imaginilor provenite de la aparate medicale. Imaginile se formează pe baza substanței radioactive injectate în corpul pacientului.
Mai bine zis radiațiile sunt detectate de o cameră gamma plasat sub patul pacientului. Practic se efectuează o fotografiere la o rată de 32 de cadre în funcție de electrocardiograma pacientului. Fiecare cadru este în realitate o imagine de 64×64 pixeli, pixelii avînd valori cuprinse între 0 si 255. Cînd aceste imagini sint rulate într-o succesiune rapidă există posibilitatea detectării de către medici a măririi inimii după un atac de cord, de exemplu.
Una dintre problemele care apar în acest caz privesc faptul că datorită radiațiilor gamma din mediul înconjurator, imaginile preluate de cameră sunt neclare. O soluție ar fi reducerea “zgomotului” prin filtrarea digitală a imaginilor. Imaginile pot fi filtrate spațial, acest lucru însemnînd că fiecare cadru este filtrat independent. Filtrarea se poate face și temporal – fiecare pixel este filtrat astfel încât trecerea de la un cadru la altul să fie cât mai fină.
Filtrarea imaginilor la cerere necesită o putere de prelucrare considerabilă. Una din căile posibile pentru a acumula puterea de calcul necesară este cuplarea câtorva stații de lucru într-o configurațile de tip pipeline.
Cum se poate rezolva problema pe baza procesării pipeline? Scriem un modul de filtrare spațială. Acest modul filtrează imaginea prin aplicarea unei măști și apoi returnează imaginea filtrată. Problema în cazul acestui modul apare din cauza mulțimii mari a calculelor în virgulă mobilă care trebuie efectuate. Aici intervine posibilitatea distribuirii procesării între mai multe procesoare. De exemplu, putem avea un modul care filtrează cadrele pare și alt modul care filtrează cadrele impare. Într-un caz extrem se poate apela la o configurație de 32 de mașini care filtrează cîte un cadru din succesiunea prezentată. Specializarea poate continua astfel încît putem scrie un modul care să realizeze eliminarea fondului prin atribuirea valorii zero tuturor pixelilor care se încadrează într-un anumit interval.
Am vorbit aici doar despre două paradigme dintre multele existente. Ele nu vin decît să întregească imaginea “teoretică” pe care o avem asupra procesării distribuite.
1.1.2 Sisteme de operare distribuite
Cu toate că și procesoarele “ieftine” au devenit destul de puternice, există încă probleme a căror rezolvare necesită o viteză de calcul superioară. Utilizarea unui procesor de 1000 de ori mai scump (care de regulă nici nu există) nu înseamnă o putere de calcul de 1000 de ori mai mare. Dar dacă se utilizează 1000 de procesoare? Dacă procesoarele sunt puse la lucru în mod inteligent poate că ne-am putea apropia de o creștere de 1000 ori a puterii de calcul. Există diferite tehnici de construire a unor sisteme de calcul care conțin mai multe procesoare. Dintre ele, mașinile paralele (sau multiprocesoare strâns cuplate) și sistemele distribuite (multiprocesoare slab cuplate) reprezintă două limite.
Utilizarea unui sistem distribuit nu este numai o soluțile pentru “bogați”, la fel de bine poate să fie văzută ca o soluțile pentru “săraci”. Partajarea unor resurse mai rar folosite sau mai scumpe (imprimante, unități de bandă, CD) de către utilizatori care lucrează la calculatoare diferite se poate rezolva dacă se interconectează calculatoarele. Pe de altă parte actualizarea sau consultarea unei baze de date comune devine absolut indispensabilă în cadrul fiecărui laborator/organizație. De asemenea existența unor stații de lucru individuale care dispun de o putere de calcul ce nu poate fi utilizată integral (24 de ore din 24) de către un singur utilizator reprezintă un alt motiv în sprijinul ideii de a utiliza o rețea de calculatoare în locul unui singur sistem de calcul.
În competiția mașini paralele împotriva sistemelor distribuite se pare că sistemele distribuite sunt învingatoare. Mașinile paralele de succes din ultima vreme sunt de fapt sisteme distribuite care folosesc o rețea de comutație foarte rapidă (de exemplu IBM SP2 – Scalable POWERparallel Systems 2). Avantajul major al unei astfel de soluții constă din faptul că se scalează foarte bine. Adică, adaugarea de noi procesoare nu conduce după o anumită limită la o degradare de performanțe.
Un sistem distribuit permite și folosirea mai eficientă a procesoarelor. E cunoscut faptul că un utilizator solicită calculatorul inegal în timp. Astfel în perioadele de editare calculatorul nu are prea multe de făcut, în timp ce la o compilare este solicitat intens. Utilizatorul nu are nevoie de întreaga putere de calcul atunci cand editează, în schimb ar dori mult mai mult la compilare. dacă am avea acces la un sistem distribuit, compilarea ar putea fi facută pe mai multe procesoare simultan, obținându-se o reducere substanțială a timpului de execuție.
Un ultim aspect este acela că sistemul poate fi modificat dinamic. De exemplu se pot înlocui unele dintre procesoare cu altele mai rapide. Sau se pot adăuga unele noi. Astfel de schimbări necesită investiții relativ mici. De asemenea bătaia de cap este mai mică decât în cazul schimbării unui sistem în totalitate. Din punct de vedere al aspectelor hardware sistemele distribuite sunt ușor de construit în contrast cu mașinile paralele. În schimb aspectele software sunt mult mai greu de tratat. Dezvoltarea de software pentru sisteme distribuite ridică probleme deosebite, lucru care nu se întâmpla într-un sistem centralizat sau chiar într-o mașină paralelă. Programarea aplicațiilor utilizând sisteme distribuite se poate face prin implicarea totală, parțială sau deloc a programatorilor în tratarea problemelor care țin de aspectele de tip comunicație, sincronizare, consistența informației etc.
Implicarea totală este exclusă. În afara unor aplicații foarte simple nu se poate realiza ceva serios. Împăcarea parțială corespunde utilizării unor biblioteci de funcții prin intermediul cărora se rezolvă aspectele respective. Este vorba de soluții de tip PVM sau MPI. În acest caz pe fiecare dintre calculatoare se execută versiunea proprie de sistem de operare care poate să fie diferită de la un calculator la altul. Sub sistemul de operare respectiv se execută niște procese de tip demon care “știu” să discute cu procese de același fel dar care rulează pe alte calculatoare. Programatorul trebuie să trateze explicit aspectele legate de comunicație și o parte din cele legate de sincronizare și care sunt specifice algoritmului implementat. El știe unde și când se va executa orice prelucrare.
În ultima abordare toate aceste aspecte sunt ascunse programatorului. Dacă un sistem de operare satisface cele două condiții: se execută pe o rețea de calculatoare și oferă utilizatorilor și programatorilor iluzia accesului la un singur calculator, atunci se spune că sistemul de operare este distribuit. Un astfel de sistem de operare trebuie să aibă un mecanism unic de comunicație între procese care să permită oricărui proces să discute cu orice alt proces din sistem (indiferent dacă este vorba de un proces local sau de un proces aflat la distanță), trebuie să existe o schemă unică de protecție pentru întreg sistemul. De asemenea gestiunea resurselor – procese, fișiere etc. trebuie să se facă la fel în întreg sistemul, astfel încât orice proces, orice fișier cu acces public să poată să fie văzut la fel oriunde s-ar afla.
Se consideră ca un sistem de operare distribuit este mai sigur decât un sistem centralizat. Pentru servicii critice, căderea unui procesor într-un sistem centralizat poate cauza căderea întregului sistem. Într-un sistem distribuit este posibilă existența simultană a mai multor servere cu aceeași destinație. Disparița unuia poate fi suplinită de ceilalți, de asemenea timpul de răspuns mediu scade prin satisfacerea simultană a cererilor provenite din mai multe surse pe servere diferite.
Un punct critic care ar putea apare însă în cazul sistemelor distribirite este siguranța rețelei de interconectare. Se pot de exemplu pierde mesaje, ceea ce conduce la obligativitatea tratării acestor aspecte într-o manieră transparentă pentru programator. De asemenea rețeaua poate deveni prea încărcată, lucru care ar putea conduce la anularea avantajelor legate de performanțe pentru sistemul distribuit.
Cu excepția sistemului Chorus care este un sistem de operare comercial, deocamdată sistemele de operare distribuite sunt încă în stadiu de prototipuri în medii academice. Faptul ca pentru Chorus sunt disponibile sursele, ceea ce reprezintă o invitație la explorarea posibilităților de modificare, indică faptul că încă autorii nu î1 consideră gata. De asemenea originea sa europeană constituie un important handicap în considerarea sa ca o soluție sigură.
În cele ce urmează voi prezenta scurt sistemul de operare Amoeba. Este unul dintre primele proiecte de sisteme de operare distribuite care după apariția sa a permis evaluarea a numeroase idei legate de sistemele de operare distribuite.
Sistemul de operare Amoeba a fost proiectat și creat la Vrije Universiteit Amsterdam de către o echipă condusă de profesorul Andrew S. Tanenbaum. Scopul urmărit a fost realizarea unui sistem de operare care să gestioneze mai multe calculatoare interconectate într-un mod transparent pentru utilizator, astfel încât acesta să aibă iluzia utilizării unui singur calculator. De asemenea, s-a urmărit crearea unei platforme pentru programarea distribuită, care a fost folosită de un alt colectiv din cadrul aceleiași universități, condus de Henri E. Bal, pentru dezvoltarea limbajului de programare distribuită bazat pe obiecte – Orca.
Transparent (ascunderea aspectelor “dificile” de programatorul obișnuit a reprezentat una dintre regulile de bază în proiectarea sistemului de operare Amoeba. De asemenea, s-a plecat de la ideea construirii unui sistem care să fie simplu de ințeles, utilizat, pentru care să se poată programa ușor. Uneori s-a renunțat la creșteri de performanță orientate pe optimizări legate de arhitectura particulară pe care se face implementarea în favoarea atingerii acestor obiective.
Privit din exterior, un sistem Amoeba este compus din masive de procesoare, la care sunt conectate un număr de terminale prin intermediul cărora se poate face acces la sistem și la o serie de servere pentru diferite servicii (fișiere, imprimantă etc.). Aceasta este o reprezentare simplistă, dar suficient de sugestivă. Din sistem pot face parte și stații de lucru, care pe lângă funcția de terminal pot să ofere și procesorul corespunzător pentru prelucrări.
Din punct de vedere al interconectării, sistemul poate fi conceput peste o rețea locală de procesoare la fel de bine ca și peste una de largă răspândire geografică. De asemenea, tipul interconectării poate varia. De exemplu, se poate utiliza o subrețea Ethernet conectată cu un Token Ring, deasupra cărora să se execute Amoeba.
Comunicarea în cadrul sistemului se face prin mesaje. Programarea bazată pe mesaje este foarte dificilă. Profesorul Andrew Tanenbaum spune că acest tip de programare este echivalentă cu programarea cu GOTO-uri (una din ereziile eradicate din programare). Din acest motiv în Amoeba se oferă programatorilor două mecanisme de comunicație care permit o programare ordonată: RPC (Remote Procedure Call) și comunicația de grup. RPC reprezintă apel de procedură la distanță și se efectuează prin transmiterea unui mesaj prin care se solicită unui server rularea unei proceduri. După transmiterea unui astfel de mesaj se produce blocarea execuției procesului care a făcut cererea până la primirea mesajului de răspuns. În acest mod programarea este foarte naturală, programatorul tratând (gândind) exact în același mod procedurile care se execută local ca și cele care sunt executate la distanță pe un alt procesor.
Comunicația de grup permite transmiterea unui mesaj “simultan” tuturor proceselor aparținând unui grup. Așa cum este ea implementată în Amoeba, asigură că mesajele vor fi primite de toți membrii grupului în aceeași ordine (este asigurată consistent secvențială). Grupul este închis, această însemnând că un proces din afara unui grup nu poate comunica cu procese din grupul respectiv decat prin RPC, nu prin comunicație de grup. Acest tip de mecanism permite implementarea simplă a unor obiecte replicate pe procesoarele care corespund proceselor din care este alcătuit grupul. Execuția unei operații asupra unui obiect este anunțată printr-un mesaj care se transmite spre toate procesele din grup, deci fiecare proces din grup va putea să execute operația respectivă asupra copiei locale. Datorită îndeplinirii implicite a condiției de consistență secvențială, se menține în mod simplu consistența copiilor obiectelor.
Un aspect complet diferit de cel al sistemelor de operare clasice este că în Amoeba procesoarele nu au proprietar. Ele pot fi destinate unor anumite grupuri de utilizatori prin mecanismul de drepturi existent în Amoeba. Utilizatorul însă nu are nici un fel de control asupra procesoarelor pe care îi vor fi rulate aplicațiile. Sistemul de operare ia decizia plasării unui proces pe un anumit procesor, în funcție de încărcarea lui, de memoria disponibilă, de puterea de calcul etc.
Anumite procesoare pot fi dedicate rulării unor servere care cer resurse mai multe și sunt importante (de exemplu serverele de fișiere). În acest mod tratarea cererilor se va face într-un timp mai scurt. Serverele pot rula la fel de bine și pe procesoare obișnuite, alături de alte procese, dar în felul acesta performanțele scad.
Amoeba prin suportul de comunicație oferit (RPC și comunicație de grup), oferă un suport foarte bun pentru programarea paralelă. Comunicația se bazează pe un protocol special proiectat pentru sistemele distribute – FLIP, care implementează aceste primitive de comunicație eficient.
Deși sistemul nu necesită existența unei memorii comune, prezența acesteia permite realizarea unor optimizări însemnate pentru schimbul de mesaje și implicit pentru primitivele de comunicație.
Sistemul de operare este bazat pe un microkernel, care rulează pe fiecare procesor în parte, deasupra căruia rulează servere care fumizează servicii. Microkernel-ul asigură gestiunea principalelor resurse ale sistemului. Acestea pot fi grupate în 4 categorii:
1. Gestiunea proceselor și firelor de execuție (thread-uri);
2. Gestiunea de nivel jos a memoriei;
3. Suportul pentru comunicație;
4. Gestiunea operațiilor de intrare/ieșire de nivel jos;
Procesele reprezintă mecanismul care asigură execuția în Amoeba. Un proces conține un singur spațiu de adrese, firele de execuție (thread-urile) sunt interne unui proces și au acces la spațiul de adrese al procesului, Rolui firelor de execuție este de a simplifica programarea și nu de a asigura paralelismul, care se asigură la nivelul proceselor.
Pentru sincronizarea firelor de execuție se pot utiliza trei mecanisme:
Semnale: Întreruperi asincrone, similare celor din UNIX, se pot utiliza însă numai între firele de execuție din cadrul aceluiași proces;
Mutex: Mecanism de tip zăvor utilizat pentru realizarea excluderii mutuale. Are doua stări: închis sau deschis. Un fir de execuție care solicită închiderea unui zăvor deschis își va continua execuția, zăvorul fiind trecut în starea închis, dacă zăvorul este închis, șirul de execuție se va bloca până când un alt fir de execuție comandă deschiderea zăvorului. La deschiderea unui astfel de zăvor, va fi deblocat pentru execuție un fir de execuție dintre cele blocate (dacă există) și care va închide din nou zăvorul.
Semafoare: Funcționează după regulile cunoscute. Prin modul de implementare este un mecanism mai lent decât cel oferit de mutex.
Gestiunea memoriei se face prin segmente cu lungime variabilă. Acestea sunt păstrate în totalitate în memorie și mai mult decât atât ele sunt stocate continuu în memorie. De asemenea nu se face swap cu ele. Datorită acestor proprietăți, gestiunea memoriei este simplă și în același timp foarte rapidă. Pe de altă parte această abordare conduce la necesitatea unei memorii mari (de ordinul zecilor de MB). A fost aleasă această soluție datorită faptului că una dintre premisele proiectării sistemului a fost “memoria este foarte ieftină”.
Segmentele de memorie pot să fie mapate în spațiul de adrese al mai multor procese care se execută pe același procesor. În felul acesta se creează memorie partajată. Dacă este nevoie de memorie partajată este totuși mai natural să se lucreze cu fire de execuție. Utilizarea de procese care se execută pe același procesor în loc de fire de execuție se face în cazul în care este necesară protecția (izolarea proceselor), dar în acest caz utilizarea unei memorii comune elimină tocmai ideea de protecție.
După cum s-a mai amintit comunicația între procese se bazează pe două tehnici: RPC și comunicație de grup. Ambele sunt utilizate pentru a realiza relații de tip client-server între procese.
Pentru o comunicație de tip RPC se utilizează trei primitive: o primitivă (trans) utilizată de client pentru a transmite o cerere către server și două utilizate de către server una prin care server-ul își anunță disponibilitatea (get_request) și cealaltă prin care server-ul comunică rezultatul unei cereri (put_reply).
În cazul comunicației de grup, grupul este cel care oferă servicii care pot fi solicitate de către un client din afara grupului prin RPC cu grupul (de fapt cu unul dintre procesele grupului, dar clientul nu știe neapărat care este procesul cu care comunică). Comunicația de grup are un set de primitive pentru gestionarea grupului (crearea unui grup, adăugarea unui proces la grup, părăsirea grupului de către un proces din grup și inițierea unei proceduri de refacere a grupului după caderea unor procese). De asemenea există primitive pentru transmiterea, respectiv recepționarea mesajelor la/(de la) grup.
Comunicația de grup asigură că toate procesele din grup primesc aceleași mesaje, iar recepționarea se face în aceeași ordine de către toate procesele. Pentru aceasta unul dintre procese va avea un rol special și va fi numit secvențiator. Acest proces îndeplinește două roluri – acordă numere de ordine mesajelor ce circulă în grup și păstrează o istorie a mesajelor, realizând eventual o retransmitere în situația în care există mesaje care nu au fost recepționate de toate procesele. Transmiterea unui mesaj către grup se face utilizând două tehnici în funcție de lungimea mesajului. Fie se transmite mesajul către secvențiator, care îi asociază un număr de secvență, după care secvențiatorul efectuează difuzarea mesajului către toate procesele, fie se anunță prin difuzare ca se dorește transmiterea unui mesaj, și secvențiatorul răspunde prin acordarea unui număr de secvență după care procesul care a dorit să transmită mesajul face difuzarea acestuia. În primul caz fiecare mesaj este transmis de două ori prin rețea, în schimb în al doilea caz se difuzează mai multe mesaje, fiecare procesor fiind întrerupt o dată pentru mesajul prin care se solicită numărul de secvență și a două oară pentru mesajul propriu-zis. Procesul care transmite mesajul se blochează până când primește și el mesajul (ca orice alt proces din grup). Secvențiatorul păstrează o istorie a mesajelor transmise. Procesele anunță numărul de secvență al ultimului mesaj recepționat de câte ori transmit un mesaj. În felul acesta secvențiatorul “află” cine ce mesaje a recepționat. De asemenea secvențiatorul poate să ceară explicit această informație de la un proces care nu a mai transmis nimic de multă vreme. Utilizând aceste informații secvențiatorul poate să își gestioneze în mod corespunzător istoria.
Operațiile de intrare/ieșire se efectuează prin intermediul driverelor. Pentru fiecare dispozitiv există un driver. Acestea aparțin microkernel-ului și nu pot să fie adăugate sau șterse dinamic. Comunicația driverelor cu restul sistemului se face prin RPC.
Tot ceea ce nu este făcut de kernel este făcut de procesele server. Deoarece s-a ales soluția microkernel, tot ce se putea face în afara kernel-ului a fost trecut în sarcina serverelor. Această soluție a condus la o flexibilitate crescută, pentru că serverele sunt în felul acesta ușor de modificat/înlocuit. Pentru același serviciu putem să avem mai multe servere rulând simultan. Câteva din serverele disponibile sunt: serverul de fișiere, de directoare, de execuție, boot, de generare a numerelor aleatoare, cron, mail etc.
Pentru principalele servere există apeluri de bibliotecă, cu ajutorul cărora un utilizator poate accesa obiecte, detaliile de implementare fiind ascunse utilizatorului. De asemenea pentru cei care vor să creeze servere există un compilator special pentru crearea unor astfel de biblioteci.
Toate resursele de orice fel sunt abstractizate în Amoeba prin obiecte. Un obiect este o încapsulare de date, care are asociate metode prin intermediul cărora se pot efectua operații asupra datelor respective. Obiectele sunt gestionate de servere prin intermediul capabilităților. La crearea unui obiect, serverul construiește o capabilitate protejată criptografic, pe care o asociază obiectului. Clientul primește această capabilitate, prin intermediul căreia va accesa obiectui respectiv.
Pentru a putea rula sistemul de operare distribuit Amoeba, este necesar un set de plăci de bază cu procesor interconectate între ele, fiecare având memorie locală. Procesoarele pot fi de tipuri diferite. Sistemul poate conține stații de lucru (deci și terminal, tastatură, hard-disk etc.) și/sau masive de procesoare (processor pool). Masivele de procesoare reprezintă exclusiv plăci cu câte un procesor și memorie locală interconectate între ele.
Și totuși, deși din Amoeba au rezultat foarte multe articole și comunicări științifice, nu s-a ajuns la realizarea unui produs comercial. Motivele sunt multe și de diferite naturi. Unul este legat de faptul că Amoeba este un produs al unui mediu universitar care nu are forța să impună produse de o asemenea anvergură. Altul este faptul că proiectarea sa a început totuși în anii '80. Și deși a fost o trambulină pentru numeroase concepte noi (reprezintă unul dintre primele sisteme de operare bazate pe microkernel, utilizează noțiunea de obiect pentru abstractizarea resurselor sistemului de operare, utilizează mecanismele de RPC și comunicația de grup etc.) nu a fost singurul. Între timp, și de fapt în paralel cu Amoeba, au fost dezvoltate numeroase alte soluții/ concepte.
Proiectui Glob are drept scop proiectarea și implementarea unui sistem care să permită construcția unor aplicații distribuite pe o arie largă. În acest sistem, din nou baza este reprezentată de obiecte care pot să fie locale sau distribuite.
În modelul Globe, un obiect este o entitate formată dintr-o colecție de valori (starea obiectului), o colecție de metode care permit inspectarea și modificarea stării obiectului și o colecție de interfețe, fiecare interfață utilizând un subset de metode. Invocarea unei metode se poate face numai prin intermediul unei interfețe. Un obiect are interfețele și starea distribuite în mai multe spații de adresă. O astfel de distribuție se realizează prin obiecte locale. Un obiect local este continuu în intregime (stare, metode, interfață) într-un singur spațiu de adrese. Un obiect distribuit este o colecție de obiecte locale care aparțin unor spații de adrese diferite. Părțile unui obiect (obiectele locale) comunică între ele pentru a menține o stare globală consistentă.
Evoluția Internet-ului a deschis în momentui de față noi posibilități și moduri de abordare ale unor probleme clasice. În fond întregul Internet nu este altceva decât un sistem distribuit. Ce ar însemna în acest caz un sistem de operare? Să considerăm, de exemplu, deja clasica relație client-server. Apariția soluțiilor de tip Java a adus elemente noi în modul în care este gândită această relație. Mai mult sau mai puțin clasic, un client transmite o cerere unui server sub formă de mesaj care descrie ce se cere. Serverul execută un program și transmite clientului un răspuns tot sub forma unui mesaj.
Ce prevăd soluțiile de tip Java? Clientul transmite serverului o cerere. Dar această cerere poate să fie un servlet (program scris în Java, sub formă de fișier obiect pentru mașina virtuala Java) care va funcționa ca un “plug-in” pentru programul executat de server. Deci clientul este cel care furnizează programul executat de către server (De ce nu se face prelucrarea pe calculatorul local? De exemplu, pentru că serverul este un calculator mult mai putemic, pentru că are acces local la o anumită bază de date sau la alt tip de resurse). Răspunsul oferit de server poate să fie la rândul lui un mesaj sau un applet (program scris în Java) pe care clientul îl execută.
Existența unor astfel de mecanisme nu poate să fie ignorată când se vorbește despre sisteme de operare distribuite. Dar în același timp ele ridică probleme deosebite, cum ar fi cele legate de securitate, care nu existau în abordările anterioare.
1.1.3 Sisteme distribuite eterogene
O constantă a evoluției științei și tehnologiei sistemelor de calcul este cererea continuă de performanțe tot mai mari, exprimate în primul rînd prin viteza de calcul, deci timp de execuție mai mic, dar și prin numărul de aplicații terminate în unitatea de timp. Există în permanent, pe piață, o ofertă generală, care satisface marea majoritate a utilizatorilor (de exemplu, PC-uri), dar și produse de mare performanță (cum ar fi stațiile grafice multi-procesor) pentru aplicații deosebite.
Un concept relativ nou, scalabilitatea, creează o perspectivă nouă asupra evaluarii calitative a sistemelor de calcul. Scalabilitatea înseamnă modificarea liniară a performanțelor unui sistem odată cu modificarea numărului sau calității resurselor instalate (număr de procesoare, capacitatea memoriei principale, număr de discuri de mare capacitate, procesoare mai rapide). Asigurarea scalabilității nu este o problemă simplă, ținîndu-se cont că performanțele unui sistem se aliniază la performanțele căii de date care este cea mai lentă (de exemplu cea stabilită pentru transferul datelor între memorie și unitățile de disc). Creșterea în timp a complexitații unei aplicații, sau creșterea dimensiunii ei nu mai constituie o problemă pentru programator, dacă sistemul pe care își execută aplicația este scalabil. Prin utilizarea mai multor procesoare, a unui spațiu agregat de memorie mai mare, a mai multor canale de I/E, timpul de execuție se poate menține sub o valoare dorită sau se modifică liniar, fără a interveni în cod. Acomodarea aplicației la noua configurație este realizată transparent, de către sistemul de operare, sau cu modificări minore în textul sursă.
Scalabititatea a fost propusă la început pentru compararea sistemelor paralele. Se știe că un calculator multi-procesor cu memorie comună asigură scalabilitatea pînă la un număr de circa 30 procesoare. dacă se instalează mai multe procesoare, performanțele se degradează datorită supra-încărcării căii de acces la memoria comună. Chiar dacă noile tehnologii permit instalarea unui numar mai mare de procesoare, fenomenul se păstreaza. Sistemele paralele cu memorie distribuită sunt scalabile și, în fapt, reprezintă un standard “de facto” pentru paralelism. Un exemplu este Message Passing Interface.
Sistemele de calcul paralel multi-procesor au suscitat un interes deosebit în anii ‘70 și '80, datorită performanțelor teoretice extrem de atractive, dar sumele investite și efortul de cercetare consumat nu au condus la rezultatele anticipate. Un număr de n procesoare nu execută o aplicație de n ori mai repede. Un rezultat bun se obține, de exemplu, atunci cînd 4 procesoare contribuie la reducerea timpului de execuție de 3 ori.
Raportul de vînzari supercalculatoare/PC este de 1/30.000 pe ultimii 5 ani. Proiectanții sistemelor de mare performanță au folosit ca soluție constructivă fie un număr mic de procesoare foarte puternice (de exemplu, CRAY Y-MP, Meiko Computing Surface), fie un număr foarte mare de procesoare mai lente (Connection Machine -1, -2, -3, nCube). În primul caz, procesorul folosit este produsul cel mai performant al producătorului respectiv, realizat cu tehnologia disponibilă și în condițiile impuse de arhitectura aleasă. Dacă un program nu poate fi paralelizat, procesorul elementar mai rapid termină oricum mai repede programul, dar dacă programul poate fi paralelizat, performanța creste simțitor.
S-a demonstrat practic că eficiența unei arhitecturi paralele particulare depinde de natura aplicației. Codurile care au prezentat un grad înalt de paralelism și care au putut tolera viteza relativ scăzută a procesoarelor individuate au putut fi executate eficient pe sisteme masiv paralele (MPP – Massively Parallel Systems). Azi, sistemele MPP sunt colecții mari de noduri din clasa stațiilor de lucru, interconectate cu o rețea dedicată, de mare viteză (de exemplu. Connection Machine 5, sau Intel Paragon). Un rol important îl poate juca rețeaua de interconectare, care poate corespunde sau nu modelului de comunicație al aplicației. Deoarece multe sisteme paralele nu asigură mecanismele pentru comunicații globale, interacțiunea proceselor este de multe ori limitată la cele aflate pe același procesor sau pe procesoare vecine. În loc ca programul dezvoltat de utilizator să reflecte soluția la o problemă, el este dominat de caracteristicile sistemului de calcul pentru care este dezvoltat. Dacă dimensiunea sistemului se modifică, este posibil să se impună modificări importante. Evident, comunicațiile ne-locale nu trebuie lăsate în grija programatorului, ci realizate de sistem. Ideal este ca nucleul sistemului de operare să includă și funcții de rutare, care să folosească o interfață valabilă pentru cît mai multe arhitecturi diferite (proiectul Esprit PUMA).
Slăbiciunile supercalculatoarelor de tip MPP sunt: durata mare a realizării, ceea ce conduce la o întîrziere de 1-2 ani pînă la comercializare, interval de timp suficient pentru apariția unor stații de lucru competitive; costul mare al componentelor (1MB DRAM costa 0.5$ pentru un PC și 600 $ pentru CRAY M90), ca și al operațiilor de upgrade; stilul de programare diferit, care nu poate fi asimilat cu ușurință; lipsa unor medii de dezvoltare stabile; lipsa portabilitații, mai ales între sisteme care implementează modele de calcul diferite (memorie comună, memorie distribuită etc.); ocupă o nișă prea mică, cel pupin deocamdată. Totuși, există și citeva avantaje certe, ce nu pot fi neglijate: timp de execuție redus, o calitate mai bună a rezultatelor, posibilitatea rezolvării unor probleme extrem de complexe, iar din punct de vedere al utilizării, o imagine globală oferită de către sistemul de operare asupra tuturor resurselor instalate.
Chiar dacă entuziasmul privind posibilitățile sistemelor paralele s-a mai micșorat, demonstrând poate și o maturizare a domeniului, numărul mare de sisteme instalate, ca și rezultatele excelente obținute pentru anumite aplicații impun căutarea unor soluții integratoare și nu abandonarea acestei căi.
Într-adevăr, cuvintul cheie este integrarea, deja realizată fizic, a sistemelor de mare performanță (masiv paralele, supercalculatoare, calculatoare vectoriale) în cadrul rețelelor de calculatoare. În felul acesta se creează rețele eterogene de dimensiuni foarte mari, în care rolul principal îl joacă stațiile de lucru. Într-o astfel de rețea, sistemele paralele reprezintă nuclee de calcul foarte puternice ce pot fi folosite pentru accelerarea execuției aplicațiilor complexe (fizica atomică, previziuni meteo, gestiunea bazelor de imagini etc.). Majoritatea sistemelor de calcul paralel sunt accesibile în rețea, dar ele pot fi folosite acum numai individual, prin intermediul unui calculator gazdă. Un utilizator se conectează la gazda sistemului paralel, dacă are un cont, execută aplicația, după care se deconectează. Prin soluția integratoare, utilizatorul își creeaza un domeniu de execuție, format din mai multe stații din rețea inclusiv sisteme de mare performanță. Domeniul de execuție, care reprezintă o mașină de calcul virtuală foarte puternică, are o evoluție dinamică: se pot introduce în domeniu sau elimina în orice moment stații de lucru, servere de baze de date, procesoare specializate etc. Domeniul de execuție este conceptul software, iar corespondentul său fizic este ciorchinele (clusterul) de calculatoare. Viteza de calcul a fiecărui procesor, întîrzierile de comunicație (latencies) între stațiile aceluiași cluster sau între clustere sunt factori de performanță importanți. Cînd se proiectează o aplicație distribuită, trebuie să se țină cont de acești parametri la definirea clusterului.
Domeniul de execuție al unei aplicații, format din unul sau mai mulți ciorchini este o parte a sistemului distribuit eterogen.
Mai multe stații de lucru formează un cluster care poate fi alocat unei singure aplicații sau mai multor aplicații. Aplicația, formată din mai multe taskuri concurente, este alocată unui domeniu de execuție a cărui configurație poate varia de la stația inițială pînă la zeci sau sute de stații de lucru. Domeniul include numai nodurile de calcul de interes. Pentru definirea domeniului de execuție se folosesc mai multe criterii:
• caracteristicile aplicației în termenii timpului de execuție, raport calcule/comunicații și necesarul de resurse;
• disponibilitatea resurselor și estimarea încărcării;
• o mapare posibilă a grafului de execuție al aplicației pe graful de comunicații al domeniului de execuție;
• condiții de performanță speciale, cum ar fi execuție în timp real, toleranța la defecte sau o precizie foarte mare.
Domeniile de execuție se pot suprapune. Dar, trebuie să se țină cont că simultan se execută mai multe aplicații, între care interferențele trebuie să fie minime, iar timpul de execuție al fiecăreia să fie semnificativ mai mic decît în varianta mono-procesor.
O stație de lucru din gama “top end” (ca Silicon Graphix Power Challenge) oferă acum 1/3 din performanța procesorului CRAY C90, pe care îl depășește însă în anumite privințe. Chiar și stațiile de lucru obișnuite, ca SUN 5 sau care folosesc microprocesorul Pentium, au performanțe din ce în ce mai mari. Deci, puterea de calcul accesibilă într-o rețea egalează sau depășește puterea de calcul a multor supercalculatoare. Ce este interesant este că studiile statistice demonstrează că o mare parte din timp, cele mai multe stații nu sunt folosite. S-a observat că în cele mai multe laboratoare universitare mai mult de 50% din stații sunt neutilizate chiar în timpul zilei. Avantajul principal al noului model de calcul propus, “rețeaua de stații de lucru” -Network of Workstations (NOW) – nu este posibilitatea execuției paralele, ci mai ales posibilitatea concentrării resurselor necesare unui program. De exemplu, spațiul agregat de memorie DRAM poate fi folosit ca un cache uriaș pentru discuri, deoarece timpul de acces la memoria instalată în rețea este cel puțin cu un ordin de mărime mai mic decât timpul de acces la disc. Cu creșterea performanțelor rețelelor de comunicație, această posibilitate devine și mai interesantă. Atunci cînd se vor putea identifica stații inactive, memoria lor va putea fi alocată aplicațiilor în execuție, care solicită un spațiu mai mare decît cel disponibil local. Date experimentale furnizate de grupul NOW de la Berkeley arată că execuția programelor este de 5 -10 ori mai rapidă decît dacă s-ar folosi discurile. De asemenea, memoria suplimentară poate fi folosită pentru preluarea rolului memorie cache a stațiilor server. Acest concept cunoscut cu numele de “cooperative caching”, implementat pe o rețea în care stabile foloseau o memorie de 16 MB, iar memoria cache a serverului era de 128 MB a condus la o reducere de două ori a numărului de citiri de pe disc.
Proiectanții NOW transferă conceptul RAID din hardware în software prin scrierea redundantă a datelor pe mai multe discuri din rețea. Programele paralele pot obține un spațiu de memorie pe disc agregat egal cu suma spațiilor din interiorul clusterului pe care se execută.
NOW permite abordarea aplicațlilor de mare performanță în cadrul unei structuri de calcul uzuale. În acest sens, se folosesc curent ca elemente structurale ethernet, PVM și un SGF secvențial. Partajarea rețelei ethernet de un număr mare de stații limitează performanțele. De aceea, trebuie să se facă trecerea la ATM. La fel, SGF-ul secvențial va fi înlocuit cu unul paralel.
Se pune întrebarea dacă NOW poate rezolva aplicații mari cu performanța sistemelor dedicate și aplicații mici cu interactivitatea unei stații de lucru dedicate. Pentru a investiga această posibilitate, colectivul de cercetare NOW de la Berkeley a simulat impactul job-urilor de pe stațiile de lucru asupra MPP și reciprocă. Încărcarea unui MPP cu 32 noduri poate fi preluată de un sistem NOW cu 64 stații, timpul de execuție fiind numai cu 10% mai mare.
Un proiect NOW, important prin obiectivele sale, este abordat de un colectiv de la Universitatea Berkeley, condus de Prof. David Patterson. Ideea generală fiind de a folosi cît mai mult din tehnologiile de vîrf disponibile, mediul Ethernet a fost înlocuit cu o rețea ATM Synanics. Din punctul de vedere al comunicațiilor, obiectivul proiectului NOW de la Berkeley este de a realiza comunicarea utilizator-utilizator în mai puțin de 10 ms pentru mesaje scurte, într-un sistem cu 100 utilizatori. Proiectanții se concentrează asupra interfeței procesorului la rețea și a interfeței cu sistemul de operare. În viziunea lor, utilizatorul trebuie să comunice direct cu rețeaua, fără intervenția sistemului de operare. Sistemul de operare va mapa datele și controlul accesului la interfața de rețea în spațiul de adrese al utilizatorului. Interfața de rețea va trebui să stabilească domeniile de protecție ale comunicațiilor, prin întroducerea în fiecare mesaj transmis și verificarea la recepție a unui identificator (ID) de proces de rețea. De asemenea, trebuie să asigure livrarea datelor și a notificărilor direct în procesul utilizator. Dacă mesajul are scopul de a trezi un proces, vor deriva alte aspecte ale mecanismului de notificare. S-a realizat un ciorchine experimental cu stații HP 9000/735, conectate cu o interfață de rețea FDDI Medusa (la magistrala grafică). Cu instrumentele Active Message timpul de overhead pentru un mesaj este de 8 ms. Prin construcția unor socluri deasupra acestui nivel, timpul necesar transmiterii unui mesaj este de aproximativ 25 ms, cu un ordin de mărime mai bun decît TCP, pe același hardware.
Al doilea element important este reprezentat de modul cum se gestionează efectiv resursele în cadrul proiectului NOW. Abordarea propusă este de asigurare a serviciilor globale prin “lipirea impreună” a sistemelor UNIX ce se execută pe fiecare static. Deasupra se plasează un strat global, GLUnix, care poate fi construit însă pentru orice sistem de operare (WINDOWS NT, DOS etc.). Versiunea experimentală s-a obținut, astfel, în numai trei luni.
Prin independența de sistemul de operare local se urmărește adaptarea la cele mai noi și performanțe sisteme de operare. Este dezirabil că modificarile făcute să fie minime și cu un impact semnificativ asupra performanțelor.
În timp ce alocarea resurselor se realizează la sistemele MPP cu ajutorul unui planificator central, la NOW Berkeley, planificarea este executată independent, în interiorul nucleului sistemului de operare local.
Pentru NOW Berkeley se propune realizarea unui nou sistem de gestiune a fișierelor în rețea, fără servere, denumit XFS. Preluînd rolul serverelor, stabile client cooperează în toate aspectele privind memorarea datelor, gestiunea meta-datelor și asigurarea protecției. Scopurile pentru XFS sunt performanța, asigurarea unui serviciu cu mare disponibilitate în rețea, scalabilitatea și costul redus. Pentru a ajunge obiectivele enumerate, XFS combină patru caracteristici originale:
• orice obiect poate migra între clienți și între nivelele de memorie; astfel, se simplifică echilibrarea încărcării și tratarea erorilor, orice client poate prelua sarcinile unui client căzut în pană;
• se folosește strategia de actualizare write-back;
• obiectele se memorează prin nivelul software RAID;
• modulele cache ale cliențlor formează un cache gigant.
Un alt proiect universitar este cel condus de Prof. A. Barak, de la Universitatea Hebrew din lerusalim. Spre deosebire de alte proiecte, acesta consideră stații de lucru eterogene, mai puțin procesorul care trebuie să execute aceleași coduri de instrucțiuni. Sistemul experimental este constitut din 16 stații Pentium, la care se pot atașa orice alte sisteme cu procesor Intel 80X86. Elortul de proiectare s-a concentrat pe realizarea sistemului de operare MOSIX, un upgrade a sistemului UNIX pentru NOW. El asigură transparența, distribuirea activităților și, extrem de important, echilibrarea încărcării stațiilor de lucru prin migrarea proceselor. Procesele sunt preemptibile, iar sistemul de gestiune a fișierelor este NFS.
Există și realizări mai apropiate de mediul comercial. Astfel, unii producători de stații de lucru au adoptat OSF/1. Această decizie este semnificativă, deoarece OSF/1 conține cel pupin trei componente care facilitează utilizarea rețelelor de stații de lucru ca un sistem paralel. Primul este OSF Distributed Computing Environment (DCE) care asigură distribuția activităților pe mai multe procesoare. Apoi, Andrew File System (AFS) reprezintă un sistem de gestiune a fișierelor în rețea. Spre deosebire de NFS (SUN) care transferă datele înregistrare cu înregistrare, AFS pastrează fișierele solicitate în memoria cache a sistemelor solicitante. A treia componentă este Distributed Management Environment (DME) care asigură administrarea sistemului la nivel de rețea. Administrarea configurației va trebui să asigure consistenta mediilor hardware și software pentru toate stațiile instalate. Deocamdată, instrumentele realizate se ocupă mai mult de distribuirea activităților și nu de gestiunea sistemului.
Modelul NOW este fezabil și reprezintă cea mai interesantă alternativă, din punct de vedere al raportului preț/performanță, la supercalculatoare. Eterogenitatea este acceptată, ceea ce permite o evoluție naturală, progresivă atît din punct de vedere hardware, cît și software. Impactul cel mai important este însă la nivelul indicelui de utilizare al resurselor de calcul instalate într-o organizație. Chiar dacă nu se poate cumpăra cea mai modernă stație de lucru, prin mobilizarea stațiilor instalate puterea de calcul potențial disponibilă devine competitivă. În acest mod durata de viață a parcului de calculatoare crește, eliberând oarecum utilizatorii de presiunea ofertelor din ce în ce mai tentante ca performanțe, dar și mai scumpe.
Credem ca soluția NOW este adecvată în mod special Republicii Moldova, care nu poate investi o sumă mare în tehnologia reprezentată de supercalculatoare, dar are un parc semnificativ de stații de lucru.
1.1.4 Limbaje pentru aplicații distribuite
Dacă ar fi să dăm crezare oamenilor de știință am putea afirma că dintr-un număr de treizeci de tehnologii de vîrf utilizate larg în deceniul trecut doar trei vor mai juca un rol important în continuare: tehnologiile legate de microprocesoare, inteligența artificială și procesarea distribuită.
Dacă se compară sistemele paralele cu cele distribuite, atît din punct de vedere hard cît și din punct de vedere soft, concluzia este clară. Construirea unui sistem distribuit este echivalentă cu construirea unei rețele, care sunt performanțele sau caracteristicile rețelei este o problemă care ține de performanțele echipamentelor. Soluțiile de interconectare sunt simple astfel încât adăugarea unor procesoare nu schimbă cu nimic problema. În schimb, construirea unui sistem paralel în care mai multe procesoare au acces la o memorie comună este o sarcină foarte dificilă, mai ales dacă se pune problema scalării soluției hardware. Din punct de vedere al programării, un calculator paralel oferă un model relativ simplu bazat pe memoria comună. Un astfel de model permite pentru sincronizarea și schimbul de informații între procese prin utilizarea unor mecanisme de tip semafoare și/sau monitoare. Asigurarea consistentei memoriei comune este o problemă care nu se pune fiind realizată în mod implicit prin modul de funcționare a acesteia. În schimb, programarea unui sistem distribuit poate să utilizeze la nivelul cel mai de jos numai schimbul de mesaje între procese. O programare care se realizează direct pe acest nivel este echivalentă cu o programare nestructurată (cu “go to”-uri) în programarea secvențială. Din acest motiv una dintre sarcinile limbajelor de programare pentru sisteme distribuite constă tocmai din ascunderea de programatori a acestui nivel.
Implicarea programatorului în tratarea problemelor relative la comunicația între procese, sincronizarea acestora sau realizarea consistentei memoriei se poate face; total, parțial sau deloc. În primul caz programatorul controleaza tot. În acest caz nu este necesară utilizarea unor facilități speciale de programare. Orice limbaj de programare care permite apelarea unor funcții de sistem corespunzătoare transmiterii sau primirii de mesaje poate să fie utilizat în acest caz. O astfel de abordare poate să producă, cu un efort deosebit, o soluție eficientă (în cazul în care programatorul cunoaște foarte bine și la un nivel de amănunt sistemul – atît din punct de vedere hardware cît și software). Ceea ce este sigur este ca aplicația nu este portabilă (pentru alt sistem de operare, de exemplu). Deci, cu excepția unor cazuri speciale, o astfel de abordare nu este recomandabilă. De fapt nivelul acesta corespunde cu cel al programării în limbaj de asamblare pentru programarea secvențială. Pentru o lungă perioadă de timp asigurarea eficienței, a accesului la anumite resurse ale sistemelor de calcul se putea obține numai programînd în limbaj de asamblare. Performanțele actuale ale compilatoarelor dar și ale procesoarelor precum și complexitatea acestora face ca utilizarea programării în limbaj de asamblare să reprezinte excepția și nu regula chiar și pentru programarea sistemelor de operare.
Implicarea parțială a programatorului presupune utilizarea unei interfețe care se adaugă unui limbaj de programare cum este C-ul sau FORTRAN-ul. O astfel de interfață este realizată pe baza unor biblioteci de funcții care oferă programatorului primitive specifice ca de exemplu: asigurarea comunicației de grup, sincronizarea sau realizarea unor operații paralele. Cele mai cunoscute și utilizate interfețe din această categorie sunt PVM (Parallel Virtual Machine) și MPI (Message Passing Interface). Faptul că pentru MPI a fost elaborat un standard elaborat de către Message Passing Interface Forum (un consorțiu format dintr-un număr important de reprezentanți din universități și industrie) face ca încet, încet MPI să înlocuiască toate celelalte soluții similare. Utilizarea unei astfel de interfețe produce aplicații portabile dar programatorul trebuie să trateze multe aspecte de un nivel foarte scăzut și care nu țin de fapt de aplicația implementată. Există însă și limbaje de programare pentru sisteme distribuite care ascund programatorului arhitectura reală. Utilizînd astfel de limbaje programatorul se poate concentra pe problema pe care trebuie să o rezolve, ignorînd aspectele de implementare. Deși se lucrează de relativ mulți ani în domeniu nu există încă un limbaj de programare care să fie considerat ca fiind “Limbajul” pentru programarea sistemelor distribuite. Pentru această situație există mai multe explicații posibile. Una dintre ele este faptul că deocamdată preocupările din domeniu sunt mai mult de nivel academic și deci fiecare universitate încearcă să impună propria soluție, industria ne participînd înca în mod serios la discuție. De asemenea, dacă ar exista un sistem de operare pentru sisteme distribuite unanim acceptat atunci desigur că soluția de limbaj de programare ar fi mai clară. Dar nici acest subiect nu este încă rezolvat.
Situația în care programatorul nu este deloc implicat în tratarea aspectelor care țin de paralelism sau comunicare nu este încă asigurată de limbajele de programare care se utilizează în prezent. Dacă se va ajunge la situația în care programatorii să scrie același cod indiferent dacă programul se va executa ca aplicație secvențială, paralelă sau distribuită asta este încă o intrebare deschisăa la care trebuie să raspundă proiectanții de limbaje, compilatoare și sisteme de operare. Deocamdată nu sîntem acolo, așa ca să vedem cam ce avem la dispoziție. În continuare voi prezenta cîteva exemple de limbaje pentru programarea aplicațiilor distribuite.
Fig.1 Tipurile de limbaje pentru aplicații
Composițional C++
Compositional C++ este o extensie a limbajului C++. Au fost adăugate mecanisme pentru exprimarea paralelismului (instrucțiunile par block, parfor și spawn, procesoare ca obiecte logice), sincronizare și comunicare (variabile sync, pointeri globali și funcții atomice). CC++ a fost proiectat pentru a fi utilizat atît pentru programarea paralelă cît și distribuită. Dezavantajul major al limbajului CC++ este faptul că programatorul trebuie să se ocupe de specificarea explicită a sincronizărilor.
Deoarece într-un sistem distribuit nu există memorie comună, modelul obișnuit pentru programarea secvențială, modelul care se bazează pe variabile sau obiecte aflate într-o memorie comună nu mat poate, aparent, să fie utilizat. Dar programatorii sunt obișnuiți să dezvolte algoritmi utilizând acest model. Atunci au fost proiectate limbaje de programare care să ofere programatorului un model mai apropiat de cel secvențal.
Linda
În clasa limbajelor de programare pentru aplicații distribuite Linda ocupă o poziție specială. A fost propus în anul 1985 de către profesorul David Gelenter (Umversitatea Yale, SUA). Modelul de memorie propus de către Linda este o memorie asociativă numită Tuple Space. În această memorie un proces poate să arunce sau poate să extragă obiecte de o formă specială numită tuplu. Comportarea TupleSpace-ului este de bag (o extindere a noțiunii de mulțime pentru care același element poate să apară de mai multe ori). Un tuplu poate să fie pasiv conținând numai date sau poate să fie activ. Un tuplu activ conține și codul corespunzător unei funcții care va fi evaluată de către un proces care se activează la aruncarea tuple-ului respectiv în memoria asociativă. Terminarea procesului va produce înlocuirea tuple-ului activ cu unul pasiv în care cîmpul corespunzător procesului este înlocuit cu un rezultat calculat de către funcție.
Tuple space-ul și primitivele sale se adaugă de fapt la facilitățile unui limbaj de bază. Astfel că poate să existe un C-Linda, un Lisp-Linda, un FORTRAN-Linda, etc.
Pentru Linda există o serie de implementări comerciale, dar Linda nu este foarte raspîndit ca soluție, în special datorită faptului ca încă există probleme de implementare pentru care nu există soluții eficiente pentru orice arhitectură distribuită. Faptul că modelul pe care se bazează este foarte deosebit de modelele secvențiale nu ajută desigur la răspindirea limbajului.
Orca
Limbajul Orca a fost proiectat de Henri Bal și Andrew Tanenbaum la Universitatea Liberă din Amsterdam. Proiectarea și implementarea acestui limbaj fac parte dintr-un proiect mai mare care a avut ca obiect sistemele de operare distribute. Inițial Orca a fost proiectat pentru a reprezenta limbajul de programare pentru Amoeba, ulterior însă limbajul a început să fie utilizat și în afara contextului Amoeba. Există implementări pentru mașini UNIX, pentru transputere, pentru CM5 (Connection Machine 5) și mai nou pentru Linux.
Ca elemente de bază Orca utilizează procesele. Între procese are loc comunicația pe baza obiectelor partajate. Descrierea unui obiect se face printr-un tip de date abstract utilizînd o specificare și o implementare. Partea de specificare descrie interfața prin care se poate accesa obiectul. Această parte este importată în toate modulele care utilizează obiecte de tipul respectiv. Implementarea conține declarațiile de date corespunzătoare cîmpurilor obiectului, codul care se execută pentru fiecare operație și o secvență de inițializare pentru obiect. După ce un astfel de tip a fost declarat pot să fie realizate instanțe ale acestuia declarînd variabile de tipul respectiv. Ca în orice abordare orientată pe obiecte accesul la cîmpurile obiectului se poate face numai prin intermediul operațiilor definite asupra acestora.
Obiectele sunt utilizate și pentru comunicația între procese. Și anume, dacă un obiect este declarat ca partajat între două procese (dintre care într-unul se instanțiază obiectul și se creează al doilea proces) comunicația între cele două procese se realizează prin operații asupra obiectului respectiv. Dacă un proces creează mai multe procese și transmite tuturor proceselor create ca parametru partajat același obiect atunci obiectul respectiv poate să fie utilizat pentru comunicația între toate procesele.
Execuția operațiilor asupra obiectelor este atomică adică dacă mai multe procese vor să execute cîte o operație asupra unui obiect efectul acestor operații este ca și cum operațiile ar fi fost apelate secvențial. Ordinea în care se execută aceste operații este arbitrară, dar toate procesele văd aceeași ordine în cadrul unei execuții. De fapt prin implementare unele operații se pot executa efectiv în paralel, ceea ce este important este faptul ca efectul execuției operațiilor respectă condițiile consistenței secvențiale a accesului la obiectele partajate.
Limbajul nu admite execuția unor operații indivizibile asupra unei colecții de obiecte. Această decizie poate să creeze probleme în implementarea anumitor aplicații, pe de altă parte reprezintă o simplificare importantă pentru implementare. Dacă este neaparată nevoie să se utilizeze o operație atomică care să implice mai multe obiecte este posibil să se combine aceste obiecte într-un nou obiect care să reunească structurile de date și operațiile corespunzătoare fiecărui obiect. Dezavantajul unei astfel de abordări constă în faptul că se ajunge la combinații nenaturale de obiecte și se reduce paralelismul posibil deoarece se vor secvențializa datorită excluderii mutuale operații care de fapt nu interferă.
Prin modul în care au fost definite obiectele și operațiile asupra lor este asigurată excluderea mutuală. Dar excluderea mutuală este numai o formă de sincronizare necesară în aplicații distribuite sau paralele. O altă formă este ceea de blocare condiționată în așteptarea unui eveniment. Pentru a realiza acest mecanism se utilizează gărzi în cadrul operațiilor.
Să considerăm de exemplu cum se poate descrie în Orca o coadă de job-uri. Un astfel de obiect este util într-o aplicație în care se utilizează modelul de programare replicated worker (în acest model există o colecție de procese echivalente care preiau job-uri de prelucrat dintr-o mulțime. De cîte ori un proces termină execuția unui Job verifică dacă nu există job-uri disponibile, caz în care preia un nou job pe care să îl execute). Să presupunem că orice proces poate să producă un job nou și că descrierea efectivă a job-ului este facută cu ajutorul unor alte obiecte.
Să trecem puțin în revista modul în care sunt tratate în Orca principalele aspecte referitoare la programarea paralelă și distribuită. În primul rând Orca utilizează modelul obiectelor partajate. Pornind de la acest element trebuie discutate toate celelalte elemente:
•aspectele care țin de sincronizarea proceselor se rezolvă prin intermediul obiectelor partajate. Accesul la acestea se face în condițiile excluderii mutuale. Operațiile care se execută asupra obiectelor partajate sunt serializate. Toate procesele văd toate operațille de scriere asupra obiectelor partajate în aceeași ordine (care poate să fie diferită pentru diferite execuții pentru același program).
•aspectele care țin de comunicație se rezolvă de asemenea prin intermediul operațiilor asupra obiectelor. Orice operație de scriere asupra unui obiect ascunde în spate o operație de difuzare de mesaje.
Modelul oferit de Orca se bazează pe faptul că toate operațiile asupra obiectelor sunt atomice. Deoarece modelul este foarte simplu, raționamentele asupra programelor se fac ușor. Modelul se poate implementa simplu și foarte eficient utilizând diferite strategii pentru replicarea obiectelor corespunzator succesiunilor de operații posibile asupra obiectelor și raportului dintre numărul de operații de scriere și citire.
Probleme de implementare
Faptul ca aspectele de nivel scăzut sunt ascunse programatorului nu înseamnă că aceste aspecte au dispărut. Ele au fost pur și simplu mutate în partea de run-time. Indiferent ce mecanism vede programatorul acesta este implementat într-un sistem distribuit pe baza unui schimb de mesaje între procesoare.
Implementarea unei memorii distribuite nu este o sarcină simplă dacă eficiența implementării este importantă. Principala problema este asigurarea consistentei datelor. Consistenta datelor poate să fie interpretată ca un contract între programe și memorie. Dacă programele respectă anumite condiții de acces la memorie aceasta va funcționa corect. Cel mai restrictiv model este cel corespunzător funcționării memoriei “obișnuite”. Este vorba de consistenta stricta. În acest caz orice citire din memorie va avea ca rezultat ultima valoare scrisă. Definiția pare foarte naturală, dar ce înseamnă într-un sistem distribuit ultima valoare, mai ales dacă este vorba de un obiect care are cîte o copie pe fiecare procesor. Pentru limbaje cum este Orca care utilizează un model bazat pe obiecte partajate implementarea se bazează atît pe comunicația punct la punct cît și pe comunicația de grup. Comunicația punct la punct se utilizează dacă obiectele nu sunt replicate în timp ce comunicația de grup este utilizată în cazul în care fiecare proces care face parte din grup deține o copie a obiectului partajat. Execuția unei operații însemnă de fapt transmiterea unui mesaj către procesorul-procesoarele care trebuie să execute operația. Corespunzător, protocoalele de comunicație utilizate trebuie să asigure modelul de consistentă al datelor presupus de către semantica limbajului. Cel mai cunoscut model de consistentă utilizat în sisteme distribuite este cel secvențial care presupune că toate operațiile asupra obiectelor partajate sunt văzute de toate procesele în aceeași ordine (ordinea relativă a operațiilor provenite din aceeași sursă fiind pastrată, dar ordinea operațiilor provenite de la procese diferite poate să fie oricare) care poate să fie însă diferită la diferite execuții ale aceluiași program. În literatură sunt prezentate numeroase exemple de modele de consistentă a memoriei. Aceste modele asigură diferite nivele de relaxare a condițiilor relative la ordinea în care procesele văd operațiile executate în sistem. Problema dificilă aici este de a ascunde cît se poate programatorului aceste aspecte obținînd în același timp soluții eficiente.
Modelul de obiect partajat care utilizează o copie unică sau presupune existența cîte unei copiii pe fiecare procesor poate să fie extinsă la modelul de obiect partajat partiționat. Un astfel de obiect este compus din mai multe partiții care sunt memorate pe procesoare diferite. Fiecare partiție aparține unui procesor. Datele care sunt conținute într-o partiție sunt sigur valide pe procesorul proprietar al partiției. Asupra obiectelor se pot executa operații secvențiale sau paralele. O operație secvențială este executată de către un singur procesor, operațiile paralele presupun că fiecare procesor execută o prelucrare pe partiția pe care o deține. Dacă are nevoie de datele din altă partiție, un procesor le va obține de la posesorul ei. Avantajul major al acestui model este reducerea overhead-ului datorat comunicației.
Abordarea corespunzatoare compilării dinamice nu este o idee nouă și a fost utilizată pentru a realiza adaptarea codului generat la caracteristicile mașinii pe care se face execuția. O abordare similară presupune generarea codului în timpul execuției pentru acele secvențe pentru care arhitectura mașinii pe care se face execuția este critică.
1.2 Sisteme și arhitecturi paralele
1.2.1 Sisteme paralele
Creșterea continuă a complexității aplicațiilor executate de sistemele de calcul a impus căutarea unor soluții adecvate pentru asigurarea unor performanțe corespunzătoare. Reducerea timpului de execuție s-ar putea realiza prin folosirea unei tehnologii mai rapide, a unei arhitecturi paralele, a unor algoritmi mai performanți (paraleli) sau o combinație a tuturor acestor elemente. Limitele tehnologiei sunt puse în evidență de observația că pe parcursul a 25 ani, dintr-un factor de creștere a performanțelor de 106, contribuția tehnologiei este de numai 160 (luând ca referință supercalculatorul CRAY-1).
Conceptul de paralelism aplicat la un sistem de calcul se referă la execuția a cât mai multor operații în același timp. Inițial implementat la nivel aritmetic, prin execuția operațiilor aritmetice cu toți biții operanzilor simultan, paralelismul s-a extins continuu. O primă etapă a fost marcată de întroducerea paralelismului funcțional, prin apariția coprocesoarelor (de I/E, de calcul în virgulă mobilă etc.). La nivel aritmetic, paralelismul a fost extins prin proiectarea unităților de calcul pipeline, câte una pentru fiecare operație aritmetică elementară. Conceptul de prelucrare pipeline a fost aplicat și pentru accelerarea fazelor de extragere, decodificare și execuție a instrucțiunilor. Următorul nivel de paralelism a fost atins prin multiplicarea unor procesoare elementare, fie simple unități RALU bit-slice, fie unități centrale complete care cooperează la rezolvarea aceleași probleme.
Se poate afirma că, din punct de vedere al mașinii de calcul, progresele realizate în special în ultimul deceniu au condus la o diversitate de soluții. Clasificarea acestora se realizează preponderent pe baza definirii noțiunilor de flux de instrucțiuni și flux de date. Prin discernerea tuturor posibilităților, s-au definit patru clase de sisteme de calcul, din care practic nu au corespondent real decât trei:
Fig.2 Tipurile de sisteme paralele
(I) Sisteme de calcul cu flux de instrucțiuni și flux de date unice (SISD – Single Instruction Single Data) în care un flux unic de instrucțiuni operează asupra unui singur flux de date. Acest tip de arhitectură este reprezentat de sistemele de calcul monoprocesor clasice. Totuși, ele nu exclud paralelismul în totalitate (organizările de tip look-ahead, pipeline sau în blocuri funcționale ale microprocesoarelor moderne).
(II) Sisteme de calcul cu flux de instrucțiuni unic și fluxuri de date multiple (SIMD -Single Instruction Multiple Data) în care un singur flux de instrucțiuni operează asupra mai multor fluxuri de date. În această clasă se pot încadra atât calculatoarele vectoriale, cât și masivele de procesoare. Un masiv de procesoare (MPP, CM-2, ICL DAP etc.) este format dintr-o unitate de control care decodifica instrucțiunile și lansează semnale de control către procesoare (PE – processing elements), care operează asupra datelor locale. Sistemul mai include scheme de mascare ce autorizează funcționarea unor submulțimi de procesoare și funcții de rutare realizate pe rețeaua de interconectare a procesoarelor.
(Ill) Sisteme de calcul cu fluxuri de instrucțiuni multiple și flux de date unic (MISD -Multiple Instruction Single Data) în care mai multe fluxuri de instrucțiuni operează asupra aceluiași flux de date. Această clasă pare a fi vidă, cu toate că în ea ar putea fi cuprinse structuri specializate de procesare. Execuția simultană a mai multor operații asupra aceleiași date este dificil de definit: poate fi stabilită o ordine de execuție a operațiilor dar va fi greu de spus care este rezultatul final.
(IV) Sisteme cu fluxuri de instrucțiuni și fluxuri de date multiple (MIMD – Multiple Instruction Multiple Data) în care mai multe fluxuri de instrucțiuni operează simultan asupra mai multor fluxuri de date. Această clasă include toate formele de configurații multiprocesor, de la rețelele de calcul de uz general până la masivele de procesoare.
Această clasificare suferă datorită generalității ei, conducând la introducerea tuturor calculatoarelor paralele în clasa SIMD. Excepție fac doar multiprocesoarele, care se încadrează în clasa MIMD.
Noțiunea de flux de instrucțiuni presupune în mod implicit existența unui procesor care funcționează conform principiilor enunțate de John von Neumann (este un procesor von Newmann). Astfel, nu se ia în considerare o serie de mașini paralele care funcționează după alte principii. Este cazul sistemelor proiectate ca suport pentru execuția limbajelor funcționale (mașini data-flow, Prolog, etc.). Această observație ne permite să distingem mai clar între soluțiile diferite reprezentate de sisteme de calcul ce aparțin aceleiași clase generice a calculatoarelor paralele. Pe de o parte, există sistemele de calcul funcționale, sistolice sau logice, iar pe de alta cele reprezentate de sisteme a căror procesor elementar este de tip von Neumann. Oferta comercială actuală de sisteme de calcul paralel este limitată numai la a doua categorie.
La rândul lor, sistemele paralele cu procesor von Neumann și fluxuri multiple de instrucțiuni (ceea ce în clasificarea lui Flynn apare ca MIMD) se împart în două clase: cea a sistemelor cu memorie comună, cunoscute și sub denumirea de sisteme strâns conectate, și cea a sistemelor cu memorie distribuită (cu transfer de mesaje), sau a sistemelor slab conectate. În primul caz, procesoarele comunică prin intermediul unei memorii comune, la care sunt conectate prin intermediul unei rețele. Fiecare procesor poate avea și memorie locală, folosită de multe ori ca memorie cache. Rețeaua de conectare a procesoarelor la memoria comună poate fi de simplitatea unei magistrale comune, sau la extrema cealaltă, de complexitatea unei rețele cu accesuri incrucișate. De multe ori sunt preferate rețelele multi-nivel, care reprezintă un compromis convenabil din punct de vedere al raportului cost/performanțe.
Sistemele cu memorie distribuită constau în mai multe perechi procesor-memorie, numite noduri, interconectate printr-o rețea de transfer a mesajelor. Rețeaua de transfer a mesajelor asigură conexiuni statice sau dinamice, punct la punct între noduri. Toate memoriile locale sunt accesibile numai procesoarelor locale. Sistemele paralele cu transfer de mesaje nu au memorie comuna. Din această cauză, ele au mai fost numite și de tip NORMA (no remote memory access).
Principala proprietate a sistemelor cu memorie distribuită, care le avantajează în raport cu sistemele cu memorie comună, este scalabilitatea. Deoarece nu există nici un element care ar putea determina strangularea comunicațiilor, cum este memoria comună, sistemele cu memorie distribuită pot avea, în principiu, un număr nelimitat de procesoare. Cu atât mai important devine rolul rețelelor de interconectare care trebuie să asigure că fiecare mesaj va ajunge la destinație, într-un timp finit.
Motivele comunicării (sincronizare, schimb de rezultate parțiale) și intensitatea comunicațiilor vor depinde de aplicație, algoritm, model de calcul și limbajul utilizat. Principalele criterii de performanță de care se ține cont în proiectarea unei rețele de interconectare sunt:
Întârzierea – timpul de transmitere pentru un singur mesaj;
lărgimea de bandă – ce trafic de mesaje poate suporta rețaua în unitatea de timp;
conectivitatea – câți vecini direct are fiecare nod, parametru cunoscut ca gradul nodului;
costul hardware – ce fracție din costul total al hard-ului reprezintă costul rețelei;
fiabilitatea – asigurarea unor căi redundante etc;
funcționalitatea – posibilitatea asigurării unor funcții suplimentare de către rețea, cum ar fi combinarea mesajelor și arbitrarea.
În legatură cu rutarea mesajelor prin rețea va trebui să se asigure respectarea urmatoarelor cerințe:
• nici un mesaj nu trebuie sa fie pierdut;
• strategia de rutare trebuie să asigure protecția la interblocare;
• toate mesajele trebuie să-și atingă destinația într-un interval de timp finit;
• strategia de rutare trebuie să fie independentă de topologie și de mărimea rețelei. Proiectantul unor astfel de rețele de interconectare va avea de ales :
1. topologia, statică sau dinamică;
2. modul de operare, sincron sau asincron;
3. metoda de comutare;
4. strategia de control, centralizat sau distribuit
Topologiile statice se pretează la rezolvarea problemelor care se pot diviza în componente ce au comunicații predictibile și clare, constând în schimburi între procesoarele vecine. Cele mai raspândite sunt de tip plasă, inel, arbore, stea și hipercub.
În conexiunea stea un singur nod central este conectat cu toate celelalte. Dacă rețeaua este cu N noduri, nodul central are gradul n-1, iar celelalte gradul 1. Configurațiile mari sunt impracticabile, în arborele binar, nodurile interioare au gradul 3, frunzele au gradul 1, iar rădăcina gradul 2.
La rețelele cu accesuri încrucișate, forma foarte puternică de conectare, fiecare nod este direct conectat cu toate celelalte noduri, Pentru N noduri vom avea gradul fiecărui nod N-1 și un număr total de fire N(N-1)/2. Deoarece această rețea se poate implementa numai pentru valori mici ale lui N, servește deseori ca etalon pentru compararea cu alte topologii.
Hipercuburile sunt de mare interes în mod curent. Câteva companii incluzând Intel, NCUBE și FPS studiază activ mașini cu această topologie. În hipercubul k-dimensional există N= 2k noduri, fiecare de grad k. Dacă tratăm fiecare etichetă a nodurilor ca o valoare binară, nodurile conectate direct diferă printr-o singură coordonată i. e. (a.0.b) este conectat cu (a.l.b) pentru orice șiruri binare a și b, sau echivalent vecinii vor diferi printr-o putere a lui 2. Pentru dimensiuni mai mari diagrama devine dificilă, dar ideea este aceeași.
La ciclurile conectate în cub se inlocuiește fiecare nod al cubului k-dimensional cu un inel (ciclu) de k noduri obținând k x 2 noduri în total. Inelele se etichetează de la 0 la 2k ca în cazul hipercuburilor, iar nodurile din inele de la 0 la k-1. Dacă două inele au etichete ce diferă prin 2i, se leagă nodul i de acest inel. Astfel k conexiuni ale fiecărui nod în hipercubul original au fost distribuite nodurilor k din inelul care înlocuiește nodul. Fiecare nod are gradul 3, independent de k.
Apariția procesoarelor de tip transputer, produse de Inmos Ltd., cu facilități de prelucrare paralelă și transfer de mesaje pe canale DMA incluse în capsulă, a condus la proliferarea arhitecturilor cu transfer de mesaje.
Multiprocesoarele moderne utilizează rutere pentru transferul mesajelor. Fiecare nod are atașat un ruter. Ruterele marginale pot fi conectate la dispozitive de I/O. Transferul mesajelor între oricare două noduri implică parcurgerea, în secvență, de rutere și canale. La sistemele heterogene, mai multe tipuri de noduri sunt instalate în sistem, acestea trebuind să aibă reprezentările de date și protocoale de comunicație compatibile.
O altă clasificare a sistemelor MIMD, cunoscută și ca taxonomia lui Bell (propusă de G. Bell în 1992), este prezentată în continuare. Acesta a considerat multiprocesoarele cu memorie partajată ca având un spațiu unic de adresare. Multiprocesoarele scalabile trebuie să utilizeze o memorie distribuită. Multiprocesoarele nescalabile utilizează memorie partajată.
Se consideră că acum multiprocesoarele se află la a treia generație. Acestea sunt:
• Prima generație (1983-1987) este marcată de arhitecturi de tip hipercub și comutarea mesajelor controlată software. Exemple reprezentative sunt Caltech Cosmic si Intel iPSC/1.
• A doua generație (1988-1992) este bazată pe arhitecturi conectate prin topologii plasă, rutarea mesajelor controlată hardware și având medii software pentru calcul distribuit cu granulație medie. Exemplele cele mai cunoscute sunt Intel Paragon și Parsys SuperNode 1000.
• A treia generație (din 1993) de la care se așteaptă multiprocesoare având granulație fină, cum ar fi MIT J-Machine și Caltech Mosaic, care integrează procesarea și comunicațiile în același chip.
1.2.2 Modele de calcul paralel
Sistemele de calcul secvențial sunt toate implementări ale unui singur model de calcul, cel propus de John von Neumann. Din păcate, arhitecturile paralele care au proliferat sunt extrem de diferite și nu pot fi incluse în același model. Pe de altă parte, proiectarea algoritmilor de calcul, a limbajelor și a sistemelor de operare fac apel la modelul sistemului. De aici necesitatea utilizării unor modele cât mai apropiate de sistemul fizic.
Sarcina proiectantului unui sistem de calcul paralel este mult mai dificilă decât cea a unui realizator de sistem secvențial. El are de-a face cu un model complex, ce prezintă cel puțin patru nivele. Acestea corespund etapelor parcurse în rezolvarea unei aplicații;
• nivelul algoritmului;
• nivelul limbajului de nivel înalt;
• nivelul sistemului de operare;
• nivelul mașinii propriu-zise.
Eficiența de ansamblu depinde de corespondent între aceste nivele (modele), de cât de bine reprezintă un model de calcul, la un anumit nivel, acțiunile vecinilor. În plus, proiectantul trebuie să stabilească momentul la care sunt precizate toate detaliile de implementare, de la toate nivelele, urmat de verificarea consistenței lor.
Pentru a exploata în mod practic paralelismul inerent unor aplicații, odată cu cel al sistemului de calcul, trebuie parcurse urmatoarele etape:
1. Identificarea și exprimarea în cadrul algoritmului a paralelismului potențial al aplicației;
2. Partiționarea programului în task-uri (procese) concurente;
3. Distribuirea task-urilor pe procesoare.
Această ultima operație este un proces dificil datorită schimbărilor frecvente de context, necesare pentru sincronizare, ca și a operațiilor de migrare a task-urilor, necesare pentru echilibrarea încărcării.
Strategia prezentată mai sus este valabilă atunci când se proiectează o aplicație pentru un sistem de calcul paralel. Totuși, se remarcă un efort de cercetare considerabil pentru paralelizarea unor aplicații secvențiale, în special scrise în FORTRAN și C. Acest efort se justifică datorită complexității unor programe frecvent folosite, unde ponderea unor secvențe de instrucțiuni ce pot fi ușor paralelizate (în special bucle DO) în timpul total de calcul este mare (regula 10-90). Un alt aspect important este gradul de adecvare între modelul algoritmului paralel și arhitectura mașinii de calcul. De cele mai multe ori, aplicațile paralele sunt proiectate pentru o arhitectură specifică de sistem.
În continuare voi prezenta trei modele propuse de Kai Hwang pentru caracterizarea sistemelor paralele cu memorie comună:
• modelul cu acces uniform la memorie – UMA (uniform memory access);
• modelul cu acces neuniform la memorie – NUMA (nonuniform memory access);
• modelul cu arhitectura memoriei de tip cache – COMA (cache only memory access).
• Aceste modele diferă prin modul cum sunt partajate sau distribuite memoria și perifericele.
Modelul UMA. La acest model memoria fizică este uniform partajată de toate procesoarele. Timpul de acces este același pentru toate locațiile de memorie și toate procesoarele, din această cauză numindu-se cu acces uniform. Fiecare procesor poate utiliza o memorie cache proprie. Perifericele sunt utilizate în aceeași manieră.
Când toate procesoarele au timp egal de acces la toate perifericele, sistemul este numit multiprocesor simetric. Orice procesor din sistem poate rula programe executive, cum ar fi sisteme de operare și rutine de servire I/O. Într-un multiprocesor asimetric, numai unul, sau o submulțime de procesoare, este capabil de a rula executive. Un procesor executiv, sau procesor master, poate executa sistemul de operare și rutine I/O. Restul de procesoare nu au capabilități I/O și de aceea sunt numite procesoare atașate (attached processors – AP). Aceste procesoare execută codul utilizator.
Modelul NUMA. Acesta modelează un sistem cu memorie partajată în care timpul de acces variază cu locațiile de memorie.
Memoria partajată este fizic distribuită la toate procesoarele și este numită memorie locală. Toate memoriile locale formează însă un spațiu de adresare global, accesibil pentru toate procesoarele. Accesul de la un procesor la memoria sa locală este rapid, dar la o memorie îndepartată este lent, datorită întârzierilor suplimentare prin rețeaua de comunicație.
Modelul COMA. Este de fapt un caz special de model NUMA, în care memoria principală distribuită este convertită la memorie cache. Nu există, nici o ierarhie de memorie la fiecare nod procesor. Toate memoriile cache formează un spațiu unic de adresare, iar accesul la memoria cache este asistat de directoare.
Fortune si Wyllie au stabilit o altă corespondență sistem – model: sistemelor cu memorie comună le corespunde modelul P-RAM (Parallel Random Access Machine). Un P-procesor P-RAM sau P-RAM de dimensiunea P este definit de un număr de P programe inalterabile, o memorie comună și P procesoare, ce pot avea și memorie locală. Un procesor, memoria sa locală și programul pe care îl execută formează un RAM.
Un P-procesor RAM execută P instrucțiuni într-un pas, câte una din fiecare program. Acest model corespunde clasei MIMD, cu diferența că P-RAM este un model sincron.
O distincție importantă între diversele variante P-RAM se realizează pe baza existenței sau nu a posibilității de a se efectua accesuri simultane, în scriere sau citire, la aceeași locație de memorie. În cadrul modelului original s-a adoptat un protocol readers/writers standard, în care o locație poate fi citită de mai multe fluxuri de instrucțiuni simultan, dar scrierea o execută un singur flux (mașina CREW – Concurrent Read Exclusive Write). Modelul cel mai restrictiv este CRCW P-RAM. Pe de altă parte, CRCW P-RAM permite orice tip de acces. Oricum, supoziția ca o operație cu o locație din memoria comună consumă un timp constant (un ciclu) este nerealistă.
Modelul P-RAM introduce presupunerea nerealistă suplimentară că timpul necesar unei operații este independent de P, dimensiunea sistemului.
Pentru sistemele cu transfer de mesaje s-a definit modelul MP-RAM (Message Passing RAM). Acesta este constituit din P programe inalterabile, P memorii, P procesoare și o rețea de interconectare. Fiecare RAM este plasat într-un nod al grafului care modelează rețeaua de interconectare – RAM-urile care comunică direct se numesc vecini. Gradul unui nod este egal cu numărul de vecini, iar gradul unei rețele se determină pe baza evaluării funcței max(grad noduri). În setul de instrucțiuni se adaugă SENDNeighbor și RECEIVENeighbor. O pereche de noduri vecine comunică prin intermediul unui canal bi-directional.
Modelele P-RAM CREW, CRCW și MP-RAM sunt frecvent folosite la analiza algoritmilor paraleli.
1.2.3 Parametrii sistemelor paralele
Definirea și utilizarea unor parametri cantitativi permit compararea, la un prim nivel, a unor sisteme de calcul diferite. Accepțiunea generală este ca un sistem de calcul este mai rapid decât altul, dacă timpul de execuție al unui program (aplicație) este mai mic pe acel calculator în raport cu celălalt.
Performanța unui sistem de calcul este caracterizată, de cele mai multe ori, fie în termenii timpului de răspuns pentru o aplicație dată (definit prin diferența între momentul încheierii acesteia și cel al lansării în execuție), fie că număr de aplicații terminate într-un interval de timp dat (throughput). Cele două definiții diferite corespund perspectivei programatorului, respectiv celei a managerului sistemului de calcul, interesat de utilizarea cât mai eficientă a calculatorului.
Deoarece un sistem paralel cu memorie distribuită este constituit din sisteme de tip RAM, vom considera, pentru început, cazul unui sistem de calcul von Neumann. Datorită modului de lucru în multi-tasking, în timp ce unitatea centrală lucrează pentru un task, pentru alt task se pot executa operații de I/E. Prin urmare, este dificil de estimat timpul efectiv consumat pentru execuția unui task. De aceea, s-a adoptat ca referință timpul UC consumat efectiv pentru task-ul respectiv. Acesta poate fi împățit la rândul lui în timpul consumat pentru program (timpul UC utilizator) și cel consumat de sistemul de operare, ce execută funcții solicitate de program (timpul UC sistem). Deci, chiar în cazul unui sistem von Neumann, se face distincție între performanța sistemului ce se referă la timpul de execuție pentru un sistem neincărcat și performanța UC care se referă la timpul UC utilizator.
Pentru compararea cât mai obiectivă a două sisteme de calcul, se folosesc cele mai frecvent executate n programe. Dacă cele n programe se execută de un număr egal de ori, se poate calcula un timp de execuție generic ca media aritmetică a celor n valori măsurate:
unde Ti este timpul de execuție măsurat pentru programul i.
Dacă programele considerate au frecvențe diferite de execuție, se pot folosi ponderi, wi:
O altă soluție constă în normalizarea timpului de execuție față de un sistem de referință calcularea, apoi, a mediei timpilor de execuție normalizată. Media poate fi cea aritmetică, sau cea geometrică:
O analiză obiectivă trebuie să evidențieze, pe cât posibil, și influența compilatoarelor, ce diferă de la un sistem de calcul la altul, și a sistemelor de operare.
Continuând discuția în domeniul sistemelor de calcul paralel, menționăm existența a trei parametri care caracterizează cantitativ aceste sisteme.
Accelerarea, notată cu Sp, este definită ca raportul între timpul de execuție al unui program pe un calculator secvențial și timpul de execuție al aceluiași program pe un calculator paralel. Dacă se notează cu tp timpul de execuție al programului pe un calculator secvențial, iar cu tp timpul de execuție corespunzător variantei paralele a programului, executată pe un sistem paralel, atunci:
Indicele p este utilizat pentru a semnala numărul de procesoare al sistemului paralel. În condiții ideale, când procesul de calcul paralel este distribuit egal celor p procesoare și nu există operații de comunicare și sincronizare,
iar Sp = p. Dar, chiar și în aceste condiții, apelurile funcțiilor sistem fac ca accelerarea să fie mai mică.
Deci,
1Sp<p
Timpul de execuție al programului paralel este o sumă între o componenta ce corespunde secvențelor de instrucțiuni din program care nu pot fi paralelizate (secvențială), și o componentă paralelă executată de p procesoare:
iar timpul de execuție secvențial poate fi considerat ca fiind:
Deci,
ceea ce înseamnă că oricare ar fi p, accelerarea este inferioară proporției de cod secvențial. De exemplu, dacă partea secvențială corespunde la 10% din timpul de execuție și sistemul paralel are 10 procesoare, Sp = 5,26. Acest rezultat este cunoscut ca legea lui Amdahl, care stabilește, deci, că accelerarea este marginită superior de o valoare independentă de numărul de procesoare și arhitectura mașinii. Lee a extins rezultatul anterior, considerând că odată cu variația parametrului i, care ia valori în domeniul [1,p], se modifică și proporția din program, qi, care poate fi executată de i procesoare. În consecință,
Daca qi=1/p, se obține că
Ep=Sp/p
Eficiența, E, este accelerarea împărțită la p: și se observă că valoarea sa este întotdeauna inferioară lui 1. Acest parametru permite evaluarea modului de utilizare a procesoarelor instalate în sistem. Deci, reprezintă o masură relativă ce exprimă penalitatea plătită pentru nivelul de performanță atins.
Costul se definește ca produsul între timpul de calcul și numărul de procesoare. Această definiție pleacă de la presupunerea că toate procesoarele execută același număr de instrucțiuni.
O aplicație paralelă este optimă din punct de vedere al costului, dacă valoarea acestuia este egală cu timpul de execuție a variantei secvențiale cea mai bună. Această definiție este justificată de faptul că orice aplicație paralelă poate fi simulată pe un sistem secvențial.
Un parametru important ce caracterizează calitativ sistemele paralele este granularitatea. Granularitatea se definește ca dimensiunea medie a unei unități secvențiale dintr-un program, exprimată în număr de instrucțiuni. Prin precizarea că unitatea este secvențială se înțelege că, în cadrul ei, nu se execută operații de sincronizare sau de comunicare cu alte procesoare. Pentru un sistem paralel dat, există o valoare minimă a granularității programului, sub care performanța scade în mod semnificativ. Această valoare de prag este cunoscută ca granularitatea sistemului respectiv. Este de dorit ca un calculator paralel să aibă o granularitate mică, astfel încât să poată executa eficient o gamă largă de programe. Pe de altă parte, este dezirabil ca programele paralele să fie caracterizate de o granularitate mare, astfel încât să poată fi executate eficient de o diversitate de sisteme.
O proprietate importantă a sistemelor paralele este scalabilitatea. Aceasta se referă la posibilitatea de a asigura o creștere liniară a accelerarii odată cu creșterea numărului de procesoare, pornind de la ipoteza că programul executat prezintă un volum suficient de paralelism și o granularitate suficient de mare. De obicei, proprietatea de scalabilitate este asigurată până la atingerea unui număr de procesoare egal cu Pmax.
Între granularitate și scalabilitate există o relație de interdependență. Valoarea lui Pmax poate fi mărită prin creșterea granularitații. Sistemele cu memorie comună au o granularitate mică și, ca o consecință, Pmax are valori mici (nu depășește de regulă valoarea de 30).
Dimensiunile sistemelor multiprocesor, numărul componentelor fizice și logice și interacțiunea dintre acestea necesită concepte adecvate care să permită stăpânirea complexității, elaborarea și analiza acestor sisteme. Noțiunea de proces ca entitate de programare independentă și unitate de distribuire și execuție cu contextul propriu, permite o abordare sistemică a problemelor legate de concepția, elaborarea și evaluarea performanțelor unui sistem multiprocesor.
Optimizarea performanțelor și îmbunătățirea calității unui sistem multiprocesor se bazează pe exploatarea paralelismului la nivelul proceselor care alcătuiesc aplicațiile și însuși sistemul de programe de bază.
Creșterea performanțelor în arhitecturile de tip multiprocesor este subliniară ceea ce înseamnă că prin utilizarea unui sistem multiprocesor corespunzător cu n elemente de prelucrare, câștigul nu poate atinge de n ori performanța sistemului monoprocesor corespunzător. Dintre motivele principale care determină abaterea de la liniaritate a performanțelor se pot aminti: creșterea numărului de comunicații, planificarea task-urilor pe procesor etc.
Analizând situația actuală a sistemelor paralele, se remarcă un avans al realizărilor hardware față de software, atât de bază cât și de aplicații. Efortul cel mai important de cercetare se consumă, în momentul actual, pentru proiectarea sistemelor de operare, eventual asistate de mecanisme hardware, ce pot permite utilizarea deplină a posibilităților mașinilor paralele.
Dacă acceptăm că viitorul este al sistemelor cu memorie distribuită, singura problemă este cea a mediilor de programare și dezvoltare ce vor putea fi folosite.
1.2.4 Limitele de paralelism
Optimizatoarele de cod (schedulere) destinate arhitecturilor avansate de microprocesoare reușesc performanțe medii de 1- 2 instrucțiuni / tact, încă modeste având în vedere forța hardware a acestor mașini. Unde ar trebui acționat în viitor pentru apropierea realului de idealul posibil?
Vom încerca să răspundem la o problemă, fundamentală, și anume: dacă mai putem spera la rezultate spectaculoase de la acest domeniu al exploatării paralelismului la nivel de instrucțiuni în cadrul hard-soft al microprocesoarelor avansate (ILP- Instruction Level Parallelism).
În ultimii ani, se manifestă un interes deosebit pe plan mondial în dezvoltarea unor metode și algoritmi de scheduling static global pentru arhitecturile MEM (Mașini cu Execuții Multiple ale instrucțiunilor mașină). Aceste schedulere – unele chiar integrate în compilatoare – asamblează în așa-numite grupuri, instrucțiuni independente din program, în scopul execuției simultane a instrucțiunilor aparținând aceluiași grup. Această investigație realizată de un grup de arhitecturi avansate, se bazează pe arhitectura HSA (Hatfield Superscalar Arhitecture). Arhitectura HSA reprezintă o arhitectură microprocesor superscalară – VLIW ( Very Long Instruction Word) hibridă, care aduce anticipat din cache-ul de instrucțiuni (I-CACHE), instrucțiuni multiple într-un buffer de prefech. În fiecare tact, logica de decodificare trimite In-Order spre execuție, din bufferul de prefech, cât mai multe instrucțiuni independente pentru a fi executate în paralel. Optimizarea programelor se face static, după compilare, printr-un scheduler special conceput, deosebit de complex – conține cca. 65.000 linii sursă de C.
Scopul acestei cercetări este de a măsura gradul de ILP existent în benckmark-urile Stanford, compilate special pentru arhitectura HSA utilizând compilatorul GNU CC de sub Unix. Aceste 8 benchmark-uri au fost scrise în C și propuse cu scopul de a constitui numitorul comun în evaluarea performanțelor arhitecturilor ILP. Ele sunt considerate deosebit de reprezentative pentru aplicațiile de uz general (non-numerice) și realizează aplicații generate precum: sortări (bench-urile bubble, tree și sort, aplicații puternic recursive (bench-urile: perm, puzzle, tower-problema turnurilor din Hanoi), și alte aplicații clasice (matrix- procesări de matrici, queens -problema de șah a celor 8 regine). În urma compilării acestor benchmark-uri C, s-au obținut programe asamblare HSA.
Principiul metodei utilizate în investigare se bazează pe implementarea unui simulator TDS (Trace Driven Simulator), care să lucreze pe trace-urile HSA ale bench-urilor Stanford. Aceste trace-uri, reprezentând în principiu toate instrucțiunile mașină HSA dintr-un program, scrise în ordinea execuției lor și memorate într-un fișier, s-au obținut pe baza simulatorului HSA dezvoltat anterior. Acest simulator proceseaza benchmark-urile Stanford gata asamblate și generează parametrii compleți aferenți procesării, precum și trace-urile în diverse forme. De precizat că trace-urile utilizate conțin între circa 200.000 și 900.000 de instrucțiuni mașină HSA.
În principiu, TDS analizează secvențial toate instrucțiunile dintr-un anumit trace HSA. Fiecărei instrucțiuni i se asociază un parametru numit PIT (Parallel Instruction Time), semnificând numărul impulsului de tact în care instrucțiunea respectivă poate fi lansată în execuția propriu-zisa. Aceasta înseamnă că în acel moment, operanzii sursă aferentă instrucțiunii respective sunt disponibili. Dacă o instrucțiune următoare este dependentă RAW (Read After Write) printr-un registru sau printr-o variabilă de memorie de instrucțiunea curentă, atunci ei i se va aloca un nou PIT dat de relația:
PITnou = PITvechi + L,
unde: L = latența instrucțiunii curente
Acest proces de alocare PIT continuă în mod similar până la finele trace-ului.
Instrucțiuni arbitrar plasate în trace pot avea același PIT, semnificând deci faptul că teoretic cel puțin pot fi executate în paralel.
Se consideră că arhitectura are resurse (unități funcționale, regiștri, etc.) infinite, astfel încât, oricât de multe instrucțiuni independente pot fi executate în paralel la un moment dat. De asemenea, se ignoră hazardurile false de tip WAR (Write After Read) și WAW (Write After Write), considerându-se deci un renaming perfect, analiza anti-alias perfectă a adreselor instrucțiunilor Load/ Store și o predicție perfectă a branch-urilor (model ORACLE). În final se obține gradul teoretic de paralelism disponibil: IRteoretic = N/PITmax, unde N = numărul total de instrucțiuni din trace. De remarcat ca dacă un asemenea model idealizat ar deține mecanisme de forwarding prin implementarea unor algoritmi de tip Tomasulo, s-ar reduce la maximum posibil citirile din seturile de regiștri. Astfel, s-ar diminua deci hazardurile structurale la regiștri.
Acest indicator este esențial întrucât va lămuri dacă există suficient paralelism în programele de uz general care să justifice în continuare cercetările în scheduling. Întrucât realizările actuale cele mai performante comunică rate de procesare de până la 1.2-2.4 instr./tact, pe procesoare capabile teoretic la 6-8 instr./tact. O altă problemă, implicată de cele prezentate până acum, este următoarea: de ce nu se obține IRteoretic în practică? Răspunsul este: datorită unor limitări fundamentale, obiective, dar și datorită unor limitări artificiale. O limitare fundamentală se referă la chiar conceptul de scheduling static. Acesta este nevoit să fie uneori, inevitabil, conservator, datorită informațiilor necunoscute în momentul compilării programului. Dintre celelalte limitări fundamentale amintim: hazardurile structurale, de date și de control.
Limitările artificiale sunt date de conservatorismul, teoretic evitabil, al schedulerelor actuale și după cum vom arăta, limitează serios performanța acestora.
De exemplu, buclele (loops) constituie o astfel de limitare. Multe schedulere forțează execuția serială a iterațiilor unei bucle de program, deși ar fi posibilă paralelizarea acestor iterații prin tehnici deja cunoscute precum cele de loop unrolling sau software pipelining. De asemenea, majoritatea schedulerelor actuale nu permit execuția instrucțiunilor dintr-o buclă până când toate instrucțiunile precedente buclei nu s-au executat. Analog, la ieșirea din buclă. O limitare similară cu cea introdusă de bucle o introduc procedurile.
Un alt exemplu îl constituie reorganizarea statica (execubia Out of Order) a instrucțiunilor LOAD/STORE. Schedulerele actuale nu permit sau permit în limite foarte strînse acest lucru, întrucât problema dezambiguizării (analiza antialias) referințelor la memorie nu este încă pe deplin rezolvată. Această problemă constă în determinarea adreselor de acces aferente instrucțiunilor LOAD/ STORE, înaintea execuției lor. Dacă, de exemplu, s-ar ști că adresa unui LOAD diferă întotdeauna de cea a unui STORE, ele s-ar putea executa în afara ordinii normale, cu mari beneficii asupra timpului global de execuție al programului respectiv. Din păcate un scheduler pur static nu poate distinge întotdeauna dacă două referințe la memorie sunt permanent diferite pe timpul execuției programului.
În fine, o altă limitare de acest tip o constituie latența mare a unor instrucțiuni sau memorii care se așteaptă să fie reduse în viitor prin progrese arhitecturale sau/și tehnologice.
În cele ce urmează, se vor cuantifica pierderile de performanță introduse prin aceste limitări, demonstrând totodată că există suficient potențial în acest domeniu, în care cercetările sunt doar la început.
Din păcate, concluziile obținute nu concordă între ele datorită unor metodologii de lucru foarte diferite. Astfel, de exemplu, Wall consideră că rata maximă de procesare pe un procesor superscalar nu poate depăși 7 instr./tact. Acest lucru se datorează faptului că, în modelul său, schedulingul este exclusiv dinamic, realizându-se de fapt exclusiv prin hardware. Având în vedere capacitatea limitată a bufferului de prefetch, rezultatul obținut este absolut normal. Alții, pe modele mai agresive și prin scheduling static comunică potențiale mult mai optimiste cuprinse între 90 și 158 instr./tact.
Se examinează aportul cantitativ asupra gradului ILP adus de trei tehnici: execuția speculativă cu predicție a instrucțiunilor de ramificație, analiza dependențelor impuse de ramificații și respectiv multithreading-ul.
Execuția speculativă se referă la execuția în paralel cu instrucțiunea de salt, sau chiar anterior acesteia, a unei instrucțiuni situată în program după instrucțiunea de salt. O tehnică relativ uzuală constă în execuția speculativă a instrucțiunilor situate pe calea cea mai probabilă (trace-ul cel mai probabil) în a fi executată. Fetch-ul speculativ al instrucțiunilor poate mări de asemenea considerabil gradul de paralelism. Desigur, în cazul predicțiilor eronate ale instrucțiunilor de salt, efectele instrucțiunilor executate speculativ trebuie înlăturat.
Analiza dependențelor ramificațiilor se referă la faptul că toate instrucțiunile executate speculativ în cazul unei ramificații greșit predicționate, se anulează. Această constrângere este uneori redundantă, conducând la acțiuni inutile, consumatoare de timp. De exemplu în cazul următor, asignarea c=2; nu depinde de salt și ca urmare poate fi executată speculativ în orice caz (saltul se face ori nu).
if(a<0)
b=l;
c=2;
Chiar dacă prin hardware este mai dificil, totuși compilatorul (scheduler-ul) ar putea detecta aceaste independențe de control și ca urmare, elimina această ineficiență. În caz contrar, efectul asignării c=2 trebuie anulat, ceea ce e evident inutil, în cazul proastei predicții a saltului condiționat (if). Mai mult, printr-o analiză serioasă, execuția speculativă în acest caz s-ar putea face peste mai multe ramificații.
Multithreading-ul se referă la capacitatea unei mașini de a executa în paralel fluxuri distincte, independențe, de instrucțiuni (procese) din cadrul unei aplicații. Să considerăm secvența:
for (i=0; i<100; i++)
if(A[i];0)fluxl();
flux2();
Într-un uniprocesor MEM va fi dificil și oarecum impropriu de exploatat la maximum paralelismul buclei fluxl() împreună cu a procesului flux2(), chiar dacă cele 2 procese sunt independente de date. Acest lucru s-ar putea preta perfect însă pe o mașină MIMD (multiprocesor) unde s-ar putea crea 2 perechi independente de tip procesor- proces.
În continuare, vom evalua gradul de paralelism disponibil în programele de uz general pe baza unei metodologii tipice, de tip trace driven simulation. Evaluările se fac pe mai multe mașini abstracte, dintre care amintim următoarele tipuri reprezentative:
BASE – mașina MEM convențională, caracterizată de faptul că o instrucțiune nu se execută până când ramificația care o precede nu s-a încheiat. Instrucțiunile de salt se vor executa secvențial, câte una pe ciclu (tact).
CD (Control Dependence) – caracterizată prin aceea că o instrucțiune nu se execută până când ramificația de care depinde nu s-a încheiat.
CD+MF (MultiPlow) – CD + că se pot executa multiple salturi în paralel și “out of order” (În afara ordinii lor secvențiale din program).
SP (Speculation) – o instrucțiune nu se execută până când ramificația prost predicționată care o precede în trace nu s-a rezolvat. Cu alte cuvinte, aici salturile predicționate corect, ar permite execuția speculativă.
Pentru exemplificare, în figură secvența de program și trace-ul aferent se prezintă o secvență de program cu 7 instrucțiuni independente de date, precum și trace-ul aferent execuției. Instrucțiunile 1, 2, și 5 sunt ramificații (BR- Branch). Se presupune ca ramificațiile 2b și 5c din trace sunt predicționate greșit în trace, deci acestea nu ar permite execuții speculative.
Dacă pe modelul BASE, execuția trace-ului s-ar face în 8 tacte, pe modelul CD+MF se face în 5 tacte iar pe modelul SP în doar 3 tacte.
Modelul ORACLE este unul perfect, în care singurele restricții sunt date de dependențele de date de tip Read After Write între instrucțiuni (în rest, se consideră predicție perfectă a salturilor, resurse hardware infinite, banda de fetch oricât de mare, etc.).
Concluzia ar fi că există un semantic între performanțele reale la ora actuală (1-2 instr./tact și cele teoretic posibile. Vina este doar a schedulerelor actuale, extrem de conservatoare în privința instrucțiunilor de ramificație. Progresele în acest domeniu, care țin doar de inspirația celor care se ocupă de aceste optimizări, nu vor fi în zadar pentru că, se pare, potențial există.
În continuare se prezintă o investigare cantitativă asupra potențialului de DLP existent în aplicațiile uzuale.
S-a considerat un procesor HSA cu resurse infinite, predictor de branch-uri perfect, renaming perfect al regiștrilor și dezambiguizare perfectă (model ORACLE). Așadar, timpul de execuție este restricționat doar de către dependențele reale de date (RAW), singurele care impun execuția serializată. Latența tuturor instrucțiunilor este de un tact, cu excepția celor de tip DIV care este 32 tacte și respectiv MUL, 3 tacte.
Așadar, pe un model hibrid superscalar – VLIW idealizat, media armonică a ratelor de procesare (IR – Issue Rates) este de 19.45 instr./tact (media aritmetică ar fi de 55 instr./tact, mai optimistă). Toate raportările ulterioare se vor face relativ la acest model de bază.
Se cunoaște că s-a reușit proiectarea și implementarea în tehnologie CMOS a unor unități ALU complexe cu 3 intrări și care nu impun mărirea perioadei de tact a procesorului comparativ cu o imitate ALU clasică, având 2 intrări. Acest fapt a condus la ideea unor instrucțiuni ALU combinate care să conțină trei operanzi sursă în loc de doar doi. Așadar, ar cădea în sarcina schedulerului să combine 2 instrucțiuni ALU dependente RAW într-una singura combinată. Mai precis, o secvență de 2 instrucțiuni dependente RAW printr-un registru (Rl), ca mai jos:
ADD R1, R2, R3
ADD R5, R1, R9
va fi transformată de către scheduler într-o instrucțiune combinată, care va avea același timp de execuție: ADD R5, R2, R3, R9.
Această tehnică, posibil de aplicat atât prin hardware (combinarea instrucțiunilor în bufferul de prefetch), cât și prin software (scheduling), ar putea fi deosebit de agresivă întrucât ar acționa asupra unei limitări considerate până acum fundamentală și deci imposibil de depășit: dependența de date RAW.
Se prezintă în continuare câteva evaluări cantitative ale acestei tehnici noi, pe arhitectura HSA și trace-urile Stanford. Modelarea s-a bazat pe atribuirea aceluiași PIT pentru 2 instrucțiuni dependente RAW din trace și care se pot combina conform unor reguli predefinite.
După cum era de așteptat, instrucțiunile combinate generează o creștere semnificativă a performanței, mai precis cu 60% față de modelul precedent, obținându-se o medie armonică de 31.27 instr./tact. Consider acest câștig ca fiind suficient de ridicat, încât ideea instrucțiunilor combinate, implementabilă atât prin scheduler static, cât și prin hardware, să prindă teren în viitor.
2 MIJLOACE DE PARALELIZARE A CALCULELOR
2.1 Parallel Virtual Machine
În domeniul calculului paralel și distribuit apar adesea probleme în realizarea și testarea algoritmilor, pe de o parte din cauza prețului (modificării) unei anumite arhitecturi sau a efortului de programare cerut pentru a asigura comunicația între procese. De aceea s-au propus diferite instrumente care să elimine aceste neajunsuri. O astfel de soluție este PVM, care permite folosirea într-o maniera flexibilă a unei configurații deja existente (deci fără cheltuieli suplimentare) și asigură suportul pentru comunicația între procese. Posibilitatea de obținere gratuită a acestui instrument software împreună cu facilitațile și ușurința de folosire au condus la o foarte largă răspindire a PVM în întreaga lume.
PVM este un pachet software pentru programare paralelă care permite folosirea unei rețele eterogene de mașini UNIX ca o singură mașină paralelă. Astfel, se poate folosi puterea de calcul reunită a mai multor mașini pentru rezolvarea unor probleme care necesită resurse de calcul deosebite.
Dezvoltarea PVM a început în vara lui 1989 la Oak Ridge National Laboratory (ORNL) iar în prezent constituie un proiect de cercetare în care sînt implicate mai multe universități americane. Acest pachet de programe este distribuit gratuit celor interesați, putînd fi procurat și prin FTP de pe diferite site-uri din Internet.
Folosind PVM, un set de mașini fizice (paralele sau secvențiale) pot fi reunite astfel încât să formeze o mașină virtuală unică cu memorie distribuită. Mașinile fizice (numite host-uri) implicate în descrierea mașinii virtuale pot fi de diferite arhitecturi, de la calculatoare personale (secvențiale) pîna la adevaratele calculatoare paralele.
Mașina virtuală este alcatuită la nivel abstract dintr-un număr de procesoare virtuale, fiecare putînd fi repartizat pe un nod fizic (host) PVM oferă interfața necesară pentru lansarea task-urilor și un mecanism de comunicație și sincronizare între ele. Un task PVM reprezintă o imitație computațională PVM similară unui proces UNIX. De regulă există o identitate între un task PVM și un proces UNIX, dar există posibilitatea ca un task PVM să fie descris prin intermediul mai multor procese UNIX cooperante.
Un task este un program scris în C sau FORTRAN a carui execuție poate fi paralelizată prin intermediul unor primitive de comunicație prin mesaje, tipice oricărei mașini MIMD cu memorie distribuită. În acest fel, prin schimb de mesaje, mai multe task-uri pot coopera pentru rezolvarea paralelă a unei probleme.
PVM asigură eterogenitatea la nivel de aplicație, mașină și rețea, adică permite task-urilor aplicație să exploateze optim arhitectura disponibilă. De asemenea, asigură conversiile necesare comunicației între mașini cu reprezentări diferite ale numerelor și permite interconectarea mașinilor prin diferite tipuri de rețele.
Acest pachet de programe are două componente. Prima este demonul PVM, un fișier executabil, numit pvmd3 sau pvmd, care trebuie lansat pe fiecare procesor fizic participant la mașina virtuală. Denumirea demon vine de la faptul că respectivul program este lansat în background (în fundal) și ramîne în așteptarea unei solicitări la care să raspundă. El este astfel conceput încît orice utilizator care are un cont valid să îl poată lansa în execuție dacă dorește lansarea unei aplicații PVM.
A doua componentă este biblioteca PVM care conține setul de funcții prin intermediul cărora o aplicație PVM poate folosi mecanismele de schimb de mesaje, sincronizare între procese, de creare de noi procese sau de modificare a mașinii virtuale oferite de PVM. Deoarece PVM suportă programe scrise în limbajele C și FORTRAN, vor exista de fapt două biblioteci, una pentru C (Ubpvm3.a) și alta pentru FORTRAN (libfpvm3.a).
Pentru a evita conflictul cu alte funcții de bibliotecă, numele fiecărei funcții PVM începe cu pvm_ în limbajul C și cu pvmf în FORTRAN. Funcțiile primesc un numar specific de parametri și returnează diferite valori semnificative pentru PVM.
Cînd un proces își anunță dorința de a deveni task PVM, va primi automat un identificator tntreg, (task identifier – tid) care va trebui să fie unic în cadrul respectivei mașini virtuale. Această unicitate este asigurată de demonul PVM iar dorința unui proces de a se integra sistemului PVM este transmisă către demon la primul apel de funcție de bibliotecă PVM facut de un proces. În variantele anterioare taskurile erau identificate mai puțin eficient, folosind nume asociate. Acest mod mai este folosit în cazul grupurilor de task-uri PVM,
PVM oferă facilitați pentru controlul proceselor, permițînd unui proces să devina task PVM sau unui task PVM să redevină proces normal. De asemenea există rutine pentru a modifica numărul de host-uri din mașina virtuală, de a lansa / termina task-uri PVM, de a afia informații despre mașina virtuală și diferitele task-uri active. Mai sunt disponibile planificatoare avansate pentru prelucrari pe loturi (batch processing) sau depanatoare sofisticate pentru programe PVM.
În cazul în care un host din mașina virtuală nu mai e funcțional, PVM poate detecta acest lucru și elimina respectivul host din configurație. Este responsabilitatea programatorului să creeze aplicații tolerante la defecte. PVM nu face nici o încercare de a recupera task-urile terminate forțat la defectarea unei mașini.
Se pot crea dinamic grupuri de procese. Un proces poate face parte din mai multe grupuri, iar aceste grupuri se pot modifica dinamic, prin adăugarea, respectiv eliminarea de task-uri. Sînt disponibile funcții pentru difuzare de mesaje, sincronizare între componentele unui grup, respectiv pentru aflarea de informații despre membrii unui grup.
Task-urile PVM pot folosi două tipuri de semnale: cele normale UNIX și cele legate de producerea unui eveniment. Evenimente pot fi terminarea unui task, eliminarea (voită sau nu) a unei mașini fizice, adăugarea unei mașini fizice la mașina virtuală.
Modelul de comunicație PVM presupune că orice task poate trimite mesaje către orice alt task, fără a exista vreo limită în ceea ce priveste dimensiunea, respectiv numărul mesajelor. Desigur, marimea buffer-ului în care se memorează un mesaj este dependentă de mașină dar, pentru a generaliza, PVM presupune că nu există nici un fel de limitare de acest fel. Sînt oferite funcții pentru emisie asincronă, recepție sincronă și asincronă de mesaje. În cazul recepției de mesaje fără blocare, dacă mesajul este disponibil la momentul apelului el se va recepționa, altfel funcția va seta un steag care va indica faptul că mesajul nu a sosit.
O facilitate importantă oferita de PVM este comunicația multidestinație care permite trimiterea de mesaje către o mulțime oarecare de task-uri (multicast) respectiv către un anume grup (broadcast). Evident, trimiterea unui mesaj prin multicast este mai performantă decît trimiterea aceluiași mesaj, într-o buclă, spre toate destinațiile (atît din punct de vedere al utilizării memoriei cît și al vitezei).
O noutate introdusă de PVM 3 este relaxarea folosirii exclusive a TCP/IP pentru comunicație, cu orientarea spre mijloacele native disponibile pe fiecare arhitectură paralelă, acest lucru ducînd la îmbunătățirea performanțelor sistemului.
PVM a fost astfel conceput încît să nu necesite drepturi speciale pentru a putea fi utilizat. Mai mult, dacă un utilizator a instalat produsul pe o anumită mașină, toți ceilalți utilizatori vor putea să-1 folosească. Pentru a funcționa, trebuie să fie definite variabilele de mediu PVM_ROOT și PVM_ARCH care semnifică respectiv calea către directorul care conține demonul PVM și arhitectura mașinii respective, arhitectura care poate fi determinată automat sau preluata dintr-un tabel. De asemenea, fiecare utilizator trebuie să-și creeze o anumită structură de directoare, în conformitate cu convențiile PVM, deoarece PVM caută fișierele executabile în directorul $HOME/pvm3/bin/PVM_ARCH. Directorul de lucru al unui task PVM este $HOME, dar aceste valori implicite pot fi modificate cu ajutorul fișierului hostfile.
Consola PVM este un task PVM special, numit pvm, care permite utilizatorului să pornească, să modifice și să interogheze mașina virtuală. El poate fi pornit și oprit de mai multe ori, de pe oricare din componentele fizice ale mașmii virtuale, fără a afecta alte procese în rulare. La fiecare pornire se verifică dacă demonul PVM este lansat, iar dacă nu este, îl lansează. Apoi, la promptul pvm> oferit se pot introduce comenzi care vor fi executate imediat. Există un set bogat de comenzi disponibile, principalele facilitați oferite fiind:
modificarea numărului de host-uri ce compun mașina virtuală
modificarea numărului de task-uri active
obtinerea de informații despre starea mașinii virtuale
terminarea execuției, cu sau fără terminarea demonului PVM
Consola PVM se poate configura folosind fișierul $HOME/.pvmrc, în care se poate trece o succesiune de comenzi de inițializare.
Configuratia inițială a mașinii virtuale poate fi transmisa prin intermediul fișierului hostfile, fișier text, care conține numele unei mașini pe fiecare linie. Liniile vide sunt ignorate, iar cele care încep cu ‘#’ se consideră a fi comentarii. Pentru fiecare mașină pot fi specificate anumite opțiuni, cele mai importante fiind:
numele contului utilizatorului pe mașina respectivă și dacă se va cere parola directoarele în care PVM va căuta programele care trebuiesc lansate, implicit se folosește calea $HOME/pvm3/birT/PVM_ARCH
calea către depănător, implicit pvm3/lib/debugger
directorul de lucru, implicit $HOME
Pentru a indica setări identice pe mai multe mașini, acestea vor fi precedate de o linie cu toate opțiunile dorite, avînd ca nume de mașină '*'.
Dacă demonul PVM nu pornește trebuie făcute anumite verificări în ceea ce privește setarea corectă a variabilelor de mediu cerute de PVM, funcționarea corectă a apelurilor rsh și rexec folosite de PVM.
Pentru a lansa o aplicație PVM, trebuie lansat în prealabil demonul PVM, eventual prin intermediul consolei PVM. Apoi se pot lansa aplicații de la promptul UNIX; de pe oricare din componentele mașinii virtuale. Pentru task-urile lansate manual, fișierele standard de ieșire și eroare vor fi pe ecran, iar pentru toate celelalte task-uri, ieșirile vor apare în fișierul /tmp/pvml.<uid>, unde <uid> este identificatorul utilizatorului în cadrul sistemului UNIX.
Pentru scrierea unei aplicații PVM utilizatorul dispune de o serie de rutine de bibliotecă a căror clasificare după rolul îndeplinit este prezentată în continuare. Este important de subliniat faptul ca există un set restrîns de funcții de bază cu care se pot scrie majoritatea aplicațiilor. Toate rutinele PVM returnează o valoare; fie rezultatul funcției, fie modul de terminare al funcției: 0 (zero) pentru terminare cu succes, un cod negativ de eroare altfel. Tipurile de apeluri furnizate de PVM smt următoarele:
2.1.1 Funcții pentru controlul task-urilor
Aceste funcții permit în principal crearea dinamică de task-uri și terminarea task-urilor. Ele sînt importante deoarece asigură aderarea proceselor UNIX la PVM, respectiv părăsirea “civilizată” a PVM de către task-uri. Pentru a crea dinamic task-uri PVM se folosește apelul următor, în care se precizează numele fișierului executabil folosit și numărul de task-uri dorite. Trebuie pregătit de asemenea un vector de întregi pentru identificarea noilor task-uri.
int nr_proc==10, nr_lans, tids[10];
nr_lans=pvmspawn(“slave2”, (char**)0, PvmTaskDefault, “”, nr_proc, tids);
Task-urile lansate în execuție se preiau din directorul (implicit) $HOME/pvm3/bin/$ARCH și pot primi argumente în linia de comandă. Se poate specifica și mașina sau arhitectura pe care să ruleze acestea. Dacă nu se pot lansa toate task-urile cerute se returnează un cod individual de eroare pentru fiecare eșec. La creare fiecare task primește un număr unic de identificare, alegerea lui se face (de demonul PVM) în așa fel încît să poarte cît mai multă informație. Funcții pentru obținerea unor informați
Sînt folosite pentru a afla diverse informații despre mașina virtuală: număr de host-uri, task-uri active, identificatori de task-uri, etc.
Configurarea dinamică a mașinii virtuale
Permit adăugarea la mașina virtuală, respectiv eliminarea din aceasta a unui set de host-uri. Returnează numărul de host-uri operație cu succes.
Funcții pentru gestiunea semnalelor
Servesc pentru trimiterea unor semnale, legate sau nu de producerea unor evenimente importante pentru mașina virtuală.
Funcții pentru modificarea / aflarea unor opțiuni
Gestionează diverse opțuni PVM (afișarea automată a mesajelor de eroare, nivelul de depănare, metodele de comunicație folosite, etc.).
Controlul mesajelor
La un moment dat, fiecare task PVM are un singur buffer activ de emisie și un singur buffer activ de recepție în care sînt păstrate mesaje implicate în transfer. Utilizatorul își poate crea oricîte buffere și poate comută între acestea pentru a le folosi la trimiterea / recepția de mesaje. După utilizarea lor aceste buffer-e pot fi eliberate. Comutarea buffer-ului de recepție în buffer de emisie este o tehnică inteligentă care permite retrimiterea datelor fără o prealabilă despachetare / împachetare.
Rutine de impachetare a datelor
Asigură conversia datelor de trimis într-o reprezentare “universala”, care să nu depindă de arhitecturile implicate în transfer. Există funcții de împachetat diferite tipuri de intregi, cu sau fără semn, există funcții pentru numere reale sau complexe și pentru șiruri de caractere. Structurile se vor împacheta componentă cu componentă. Fiecare rutină are ca parametri un pointer spre prima unitale de împachetat (adresa de început a vectorului), numarul de unități, dimensiunea unei unități. Excepție face rutina care împachetează string-uri, deoarece acestea se termină cu NULL. Împachetarea unui vector de numere reale se face cu funcția
int info=pvm_pkfloat (float* fp, int nu, int lu);
Rutine pentru despachetarea datelor
Asigură conversia inversă, din reprezentarea universală în cea folosită intern pe fiecare arhitectură. Trebuie folosite în aceeași ordine în care au fost apelate funcțiile pereche de împachetare. Un vector de întregi fără semn se despachetează cu funcția int info=pvm_upkuint (unsigned int* np, int nu, int lu);
Funcții pentru schimbul de mesaje
Trimiterea unui mesaj PVM presupune trei etape:
alocarea unui buffer, folosind pvm_initsend() sail pvm_mkbuf();
împachetarea datelor în acest buffer, folosind setul de funcții pvm_pk*();
trimiterea conținutului buffer-ului, folosind pvm_send() pentru cazul destinației unice, respectiv pvm_mcast() dacă destinația e multiplă. În ambele cazuri mesajul trimis are asociat un tip (o etichetă); emițătorul nu va primi copie după mesaj.
Secvența de apeluri care asigură trimiterea a două valori întregi cu semn p și q de la un task către task-ul părinte al său este următoarea:
Pvm_initsend(PvmDataDefaul);
pvm_pkint(&q, 1, 1);
pvm_pkint(&p, 1, 1);
rez=pvm_send(pvm_parent(), MY_TAG);
Întotdeauna trebuie testată valoarea întoarsă de funcția de trimitere a mesajului, pentru a depista eventualele erori ce pot apare.
Recepția unui mesaj constă din apelul unei funcții de recepție, cu sau fără blocare, urmată de despachetarea datelor conținute în mesaj. Funcția de recepție poate să filtreze mesajele, fiind sensibilă doar la o anumita sursă, la o anumită etichetă a mesajelor sau la combinații ale acestora (se admite ca wildcard valoarea -1). Există trei apeluri disponibile pentru recepția de mesaje: cu blocare indefinita în așteptarea unui mesaj, cu așteptarea unui interval de limp bine precizat și fără blocare, caz în care se preia mesajul doar dacă acesta a sosit. Se mai poate testa dacă un anumit mesaj a sosit, fără a-l citi.
Funcția cea mai flexibilă este cea cu timeout, modalitatea de folosire fiind prezentată în continuare. Este obligatorie testarea valorii întoarse, pentru a se decide dacă mesajul este disponibil sau nu pentru despachetare.
struct timeval tmout;
tmout.tv_sec=10; tmout,tv_usec=0;
rez==pvm_trecv(prev, RUNTAG, &tmout);
if(rez>0) { pvm_upkint(&np, 1, 1); pvm_upkint(&nq, 1, 1); }
Trimiterea unui mesaj poate fi facut într-o singură etapă dacă se folosește rutina pvm_psend(), care folosește un buffer propriu și poate trimite doar vectori de un singur tip de date. Funcția blocantă pvm_precv() este similară perechii sale de la emisie, nefiind însă obligatorie folosirea ambelor funcții. Mai precis, orice funcție de emisie va putea lucra cu orice funcție de recepție.
2.1.2 Gestiunea grupurilor dinamice de procese
Funcțiile care implementează acest mecanism se găsesc într-o biblioteca separată, libgpvm3.a, care trebuie link-editată manual. Nu este sarcina demonului PVM să administreze aceste grupuri, existînd un server de grup, care va fi pornit automat la apelul primei funcții referitoare la grupuri. Funcțiile de grup sînt proiectate la un nivel general, eficiența lor nefiind maximă. Orice task PVM se poate atașa unui grup sau îl poate părăsi, fără a informa alt task din grupul respectiv. Cu excepția cîtorva funcții destinate exclusiv grupurilor, orice task PVM poate apela orice funcție legată de grupuri. Principalele acțiuni oferite se referă la aderarea unui task la un grup existent sau nu, parasirea unui grup, difuzarea de mesaje pentru membrii unui grup, sincronizarea membrilor unui grup și efectuarea unor operații globale (adunare, înmulțire, aflarea valorii maxime și minime).
Din punctul de vedere al aplicațiilor, PVM este o resursă de calcul care folosește schimbul de mesaje și poate fi accesată la diferite nivele. Primul nivel, în care maparea task-urilor pe mașinile existente este făcuta de PVM, în funcție de încărcarea acestora. Al doilea nivel presupune că utilizatorul indică arhitectura pe care să ruleze un task. Al treilea nivel cere utilizatorului să specifice exact host-ul pe care va lucra aplicația. Această ierarhizare permite exploatarea particularităților anumitor sisteme. Nu există nici un fel de restricții în ceea ce privește relațiile între procese, oricare task fiind liber să comunice sau să se sincronizeze cu oricare altul. Aceasta permite realizarea unei mașini generale MIMD, deși în practică se folosesc de obicei variantele SPMD, în care toate procesele sint identice și Master-Slave, în care un grup de procese execută calculele cerute de unul sau mai multe alte procese.
2.1.3 Considerații generale despre performanțe
Deși nu există nici o limitare în ceea ce privește paradigmele ce se pot implementa folosind PVM, un programator trebuie să țină seama de caracteristicile specifice unui sistem bazat pe schimb de mesaje. În primul rînd trebuie să se țină cont de granularitatea task-urilor, măsurată ca raportul între numărul de octeți recepționați și numărul de operații în virgulă mobilă executate de același task. Apoi numărul de mesaje emise, deoarece se pot trimite aceleași date în multe mesaje mici sau în cîteva mesaje mai mari. Deși pare mai rentabilă folosirea unui număr mic de mesaje (dispare overhead-ul cu pregătirea acestora), acest lucru nu este adevarat în orice situație, uneori putîndu-se combina folosirea de mesaje mici cu alte calcule. Mai trebuie ales tipul de paralelism care e cel mai potrivit pentru aplicație: paralelism funcțional sau paralelismul datelor. Primul tip presupune că diferitele componente ale mașinii virtuale execută operații diferite, pe cînd al doilea presupune ca datele sînt distribuite tuturor mașinilor componente, operațiile executate putînd fi aceleași. Evident, aceste două tipuri de paralelism pot fi utilizate simultan, pentru o eficiență sporită.
Considerații în cazul unei rețele de calculatoare
Dacă mașina virtuala PVM se bazează pe o rețea formată din diferite calculatoare, atunci apar alte probleme care trebuie studiate. dacă două mașini cu puteri de calcul diferite vor colabora la execuția aceleiași probleme, viteza mașinii rezultate va fi dictată de cea mai mica dintre vitezele celor două mașini. De aceea nu se recomandă realizarea de dependențe între mașini rapide și lente deoarece aceasta ar duce la degradarea performanțetor primelor. Alt aspect se referă la latența mesajelor în rețea, latența ce poate fi provocată pe de o parte de distanța fizică dintre mașini iar pe de altă parte de anumite conflicte pentru acapararea mediului de transmisie (cazul Ethernet, în fine, încărcarea rețelei la un moment dat afectează performanțele aplicației, acestea putînd varia de la foarte bune la foarte rele, pe aceleași date, la momente de timp apropiate.
Considerații asupra încărcării echilibrate
Cel mai simplu mod de abordare este folosirea metodei statice, în care task-urile sînt asociate procesoarelor o singură dată, la început. Metoda dinamică poate fi folosită dacă încărcarea computațională variază. Astfel, un proces master trebuie să mapeze task-urile pe procesoarele disponibile la un moment dat, folosindu-se pentru aceasta de o structură de tip FIFO pentru task-uri. Dacă existența unui proces master nu e justificată atunci se poate folosi a treia metodă care presupune că la anumite momente task-urile trebuie să reexamineze încarcărea și să-și redistribuie munca. Evident, această reexaminare ar putea degrada performanțele, de aceea se folosesc variante optimizate: dialogul se poartă doar cu vecinii, sau el apare doar dacă un task semnalează că încarcărea sa a depășit un prag.
Fiind vorba despre depănarea unor programe paralele, această operație este mai laborioasă decît depănarea unor programe secvențiale, pentru că atît mediul cît și comunicația pot cauza erori în programe corect scrise. Pentru depănare se recomandă trecerea de la variantă secvențală la cea paralelă, prin respectarea urmatorilor pași:
depănarea variantei secvențiale, pentru a rezolva erorile care nu sînt egate de paralelism;
lansarea unei aplicații cu un număr redus de procese pe aceeași mașină, pentru a “prinde” erorile legate de logica comunicației;
reluarea pasului anterior, folosind mai multe mașini, pentru eliminarea erorilor cauzate de rețea;
urmărirea în permanență a codurilor de eroare întoarse de funcțile PVM;
Varianta PVM 3 a fost realizată urmărindu-se următoarele objective:
mașina virtuală să fie scalabilă, suportînd sute de calculatoare și mii de task-uri; pentru aceasta era nevoie de un mecanism eficient de schimb de mesaje, care să evite apariția punctelor de gîtuire;
sistemul obținut să fie portabil pe orice mașină UNIX și chiar pe mașini care nu rulează UNIX (ex. MPP); pentru aceasta s-a evitat folosirea anumitor particularități ale unor sisteme de operare sau limbaje de programare; de asemenea nu se permite suprapunerea operațiilor de I/O cu calcule în task-uri;
caderea unui host sau a rețelei să nu afecteze prea mult funcționarea aplicației. Se face presupunerea că e disponibil mecanismul de comunicație folosind socket-i, fiecare host putîndu-se conecta, folosind protocoalele TCP sau UDP, la oricare alt host.
2.1.4 Demonul PVM
Un demon PVM, pvmd, rulează pe fiecare host din mașina virtuală și e astfel construit încît să coopereze cu ceilalți demoni. Fiecare utilizator va avea propriile lui instanțe pvmd care nu vor interacționa cu cele ale altor utilizatori, din motive de securitate. Un demon PVM nu realizează nici un fel de calcule, el servește drept router și controlor de mesaje, fiind un punct de contact pe fiecare calculator, atît din interior, cît și din exterior. Dacă un pvmd nu face nimic o anumită perioadă, va începe să emită cereri de contactare a celorlalți demoni existenți, dacă unul dintre demonii contactați nu raspunde, el va fi marcat ca exclus din mașina virtuală.
Primul pvmd, pornit manual, va activa ca master și va lansa ceilalți demoni, care îi vor fi subordonați. De cele mai multe ori aceste procese sînt echivalente din punct de vedere al acțiunilor pe care le pot executa, dar există anumite operații accesibile doar primului pvmd. Doar pvmd-ul master poate crea noi demoni; o cerere de reconfigurare inițiată pe un pvmd slave va fi trimisă spre rezolvare demonului principal, doar master-ul este abilitat să elimine calculatoare din mașina virtuală. Dacă master-ul pierde contactul cu unul dintre subordonați îl va marca terminal și îl va elimina din configurare. Dacă un subordonat pierde contactul cu master-ul, el se va termina format, impiedicînd astfel partiționarea mașinii virtuale în componente independente. Aceasta afectează însă toleranța la defecte, întrucît demonul master nu are voie să cadă niciodată.
Configurația sistemului este memorată în tabelele de host-uri și de task-uri, avînd asociate cozi de mesaje și pachete și contexte de așteptare. Un demon se configurează inițial ca master sau slave, în funcție de argumentele din linia de comandă. Apoi se creează socket-i pentru comunicația cu task-uri și alți demoni, se inițializează tabelele, se deschide fișierul în care se vor afișa mesajele apărute. Linia de comandă a demonului master poate include un fișier hostfile din care să se preia anumiți parametri, în timp ce un slave își primește parametri în linia de comandă și apoi retrimite un mesaj programului care 1-a lansat, pentru a fi inclus în tabela. Dacă pvmd master primește o listă de mașini care formează configurația inițială, și va trimite lui însuși mesaje care cer adăugarea acestor mașini, astfel încît configurația statică a mașinii apare că o variantă de configurare dinamică.
După configurare se intră în buclă principală a programului, work(), unde se apelează select() pentru a aștepta o posibilă cerere, locală sau prin rețea. Mesajele recepționate sînt dirijate spre destinațiile lor; dacă ele sînt pentru pvmd se vor trimite spre unul din punctele de intrare speciale.
Pentru a nu necesita intervenția administratorului de sistem, pvmd folosește pentru lansarea unui proces procedurile rsh, respectiv rexec(). Prima procedură nu necesită introducerea unei parole, în schimb presupune existența unui fișier .rhosts. Deoarece acest fișier poate periclita securitatea sistemului, de cele mai multe ori rsh este dezactivat sau fișierele .rhosts sînt șterse automat. Procedura rexec() aparține PVM și necesită parolă; aceasta poate fi evitată dacă există un fișier .netrc cu parole, lucru total nerecomandat. Mai există și posibilitatea lansării manuale a demonilor, sub controlul utilizatorului.
Deoarece stabilirea unei conexiuni ar putea dura minute, master-ul lansează o copie a sa, numită pvdm’, care se va ocupa de rezolvarea acestor acțiuni pe baza parametrilor primiți de la pvmd. Pvmd' va lansa procesele slave, transmițîndu-le parametrii de start, așteptînd ca răspuns anumite informații de identificare, pe baza cărora să se poată realiza actualizarea tabelei.
Tabela host-urilor descrie configurația curentă a mașinii virtuale. Fiecare demon posedă propria tabelă, care trebuie sincronizată permanent cu tabelele celorlalți demoni. Dacă un demon obține eroare de timeout la încercarea de a comunica cu un altul, acesta din urmă va fi scos din tabela primului. De asemenea, dacă un pvmd slave își dă seama că se va întîmpla ceva grav, (testînd valorile întoarse de funcțiile PVM) își va înștiința partenerii de dialog, pentru ca aceștia să nu fie nevoiți să aștepte timeout-ul, Master-ul pvmd poate trimite mesaje care să ceară eliminarea anumitor calculatoare din mașina virtuală. Operația de adăugare a unui calculator se face în trei pași, pentru a asigura disponibilitatea globală a acestuia. După ce copia pvmd' a master-ului a creat noul demon, master-ul anunță prin broadcast toate procesele pvmd slave asupra acestui lucru, apoi așteaptă confirmare de la fiecare. În continuare anunță procesul care a inițiat cererea asupra satisfacerii ei și trimite prin broadcast un mesaj pentru ca fiecare slave să știe că noua tabelă, actualizată, devine valabilă. Aceste operații pot fi executate în paralel, timpul necesar nefiind mult diferit de cel necesar adăugării unei singure mașini.
Fiecare pvmd menține o tabelă a task-urilor pe care le gestionează. Fiecare task mai e membru al unei liste sortate după TID, și uneori al unei liste sortate după PID. Ambele liste încep cu o intrare fictivă, spre așa numitul task local. Deoarece se efectuează numeroase căutari, aceste liste sînt memorate ca arbori echilibrați.
Contextele de așteptare se folosesc atunci cînd o secvență de acțiuni trebuie întreruptă pentru a executa concurent o acțiune. Spre exemplu, atunci cînd un pvmd primește o cerere sistem de la un task, el poate avea nevoie să interacționeze cu alt pvmd. Deoarece servește ca ruter de mesaje, nu se poate bloca așteptînd răspunsul. Așa că va salva informațiile legate de respectivul apel într-un context de așteptare și va reveni în bucia work(). În momentul în care răspunsul sosește, pe baza informațiilor din contextul de așteptare se trimite răspunsul task-ului solicitant. Fiecare context de așteptare are asociat un număr pentru identificare. Se pot folosi contexte imbricate.
2.2 Message Passing Interface
MPI, Message Passing Interface, este o încercare de a standardiza un set de rutine pentru schimbul de mesaje, rutine care să fie folosite de un spectru larg de aplicații și care să se poată implementa eficient pe o gamă largă de sisteme paralele sau distribuite eterogene. Efortul de standardizare a început în aprilie 1992 și a fost finalizat în mai 1994, cu o modificare (versiunea 1.1) în iunie 1995. Pentru a asigura viabilitatea standardului, la elaborarea acestuia au participat numeroase firme producatoare de calculatoare (Convex, Cray Research, IBM, Intel, Meiko , Parasoft, Thinking Machines Corporation), universități din SUA (Cornell, Edinburgh Parallel Computing Center, Mississippi State University, Rice University, University of Tennessee, Yale University) și organizații guvernamentale (Argonne National Laboratory, Lawrence Livermore National Laboratory, NASA Ames Research Center, National Science Foundation, Oak Ridge National Laboratory, Supercomputing Research Center). O altă cauză a succesului acestui standard este maturitatea, realizată prin înglobarea de caracteristici existente în bibliotecile de schimb de mesaje existente la ora elaborării standardului (PVM, P4, Zipcode, PARMACS, TCGMSG, Express). MPI a fost creat pentru promovarea sistemelor distribuite oferind:
portabilitate și ușurință în folosire
un set de funcții de referință pentru proiectanții de hardware
o bibliotecă de funcții standard pentru industria software
Standardul MPI definește o interfață de programare prin schimb explicit de mesaje, interfața de programare ce poate fi utilizată pentru scrierea de aplicații pe sisteme de tip MIMD (Multiple Instruction Stream, Multiple Data Stream, adică programe independente care se execută asupra unor date independente) cu memorie distribuită. Este important de ințeles că MPI este o bibliotecă de funcții, nu un limbaj. MPI definește nume de funcții, secvențe de apel și rezultatele pentru un set de funcții care pot fi apelate în programe C sau Fortran 77 (sunt în faza de elaborare și convențiile pentru programe C++ și Fortran 90). Compilarea programelor care folosesc MPI se face cu un compilator standard C sau Fortran iar în faza de editare a legăturilor este introdusă și biblioteca MPI. Aceste două faze sunt de obicei ascunse programatorului, căruia i se oferă un pseudo-compiler (de exemplu mpicc, care ascunde faza de editare de legături). Principalele facilități pe care le oferă MPI sunt:
comunicație punct-la-punct în medii eterogene;
rutine pentru lucrul cu grupuri de procese;
comunicație colectivă și operații de calcul globale în cadrul unui grup;
contexte de comunicare și comunicatori pentru dezvoltarea de biblioteci de funcții utilizabile în programe paralele;
rutine pentru definirea de topologii virtuale de grup;
interfață pentru efectuarea de măsuratori de performanță (profiling);
rutine pentru accesul la un set de valori globale
Spre deosebtre de PVM, standardul actual MPI nu prevede funcții de creare dinamică de procese, depănare, gestiunea de procese sau operații de intrare/ieșire. Standardizarea acestor tipuri de funcții ar putea implica standardizări impuse sistemelor de operare. Cu toate acestea, implementările actuale de MPI oferă mecanisme proprietare pentru rezolvarea problemelor neclarificate de standard. Este important să precizăm că standardul nu necesită în teroperabilitatea versiunilor de MPI, dar acest lucru face practic imposibilă cooperarea între două programe scrise cu implementări diferite de MPI.
Pentru o bună înțelegere a MPI, este necesară clarificarea noțiunilor de proces și grup de procese. Procesul MPI este unitatea fundamentală de calcul, fiind constituit dintr-un fir de control independent și un spațiu de adrese privat. Procesele MPI se execută în stil MIMD, fără a avea însă descrise mecanisme de încărcare a codului pe procesoare, atribuire a proceselor pe procesoare sau mecanisme de creare și distrugere de procese. Aceste mecanisme sunt de obicei, în cadrul implementărilor existente, împrumutate de la sistemul de operare pe care se rulează procesul MPI, fapt ce creează dificultăți de portare între sisteme de operare diferite. Numărul de procese MPI este cunoscut de la începerea execuției aplicației și nu poate fi modificat. Deși nu oferă explicit suport pentru multithreading, MPI este proiectat a fi thread-safe. Cu toate acestea, implementările publice existente nu sunt thread-safe. Grupurile de procese în MPI sunt dinamice, adică se pot crea și distruge în timpul rulării programului. Apartenența la grup este statica, în sensul că un proces nu poate fi eliminat dintr-un grup decît prin distrugerea grupului. Grupurile se pot suprapune, adică un proces poate face parte din mai multe grupuri simultan. Procesele sunt identificate în cadrul grupului printr-un întreg (rank) care ia valori între 0 și n-1, unde n este numărul proceselor din grup. după inițializarea unei aplicații MPI, există un singur grup, numit MPI_COMM_WORLD, care include toate procesele MPI care formează aplicația.
Standardul MPI a fost proiectat astfel încît programatorul începător să nu simtă complexitatea de la primele programe. Debutul în lumea MPI se poate face cunoscînd doar un număr de 6-7 funcții din cele peste 150 definite de standard. Acest set de 6 funcții este minimul necesar pentru scrierea unei aplicații MPI și vor fi prezentate (ca nume de funcții C) în ordinea în care apar de obicei în programele MPI:
MPI_Init() este funcția care inițializează variabilele locale MPI și înștiințează sistemul global MPI despre execuția unui nou proces MPI. Funcția acționează și ca barieră de initializare, în sensul că nici un proces MPI nu-și poate continua execuția pînă cînd nu au executat toate celelalte procese partea de inițializare. Deși această funcție apare la inceputul unui program, locul ei poate fi oriunde.
MPI_Comm_rank() întoarce idendficatorul procesului MPI în cadrul grupului specificat în lista de parametri.
MPI_Comm_size() întoarce numărul de procese care fac parte din grupul specificat ca parametru,
MPI_Send() și MPI_Recv() sunt funcțiile de bază care implementează comunicația prin mesaje între procese.
MPI_Finalize() pentru anunțarea sistemului MPI despre terminarea procesului MPI.
La aceste funcții, se poate adăuga și MPI_Barrier(), care acționeaza ca un punct de sincronizare totală între procesele membre unui grup.
Stilul de programare care poate fi folosit cu MPI se încadrează fie în MIMD, în cazul în care procesele MPI provin din programe diferite, fie în stilul SPMD (Single Program Multiple Data, adică un singur program cu mai multe variante interne de execuție), dacă procesele MPI provin din același program, dar executa porțiuni diferite pe baza unor instrucțiuni de condiție.
Scopul principal al MPI este de a oferi un set de funcții pentru transmisia de mesaje între diferite procese MPI. Din acest motiv, MPI înglobează o sumă de mecanisme de comunicație prezente în alte sisteme. Astfel, comunicația punct-la-punct prevazută de MPI definește mai multe moduri de comunicație si de blocare, Prin mod de comunicapie se înțelege legea care guverneazî inițierea și terminarea unei operații de transmisie sau recepție. Modul de blocare stabilește condițiile în care se poate refolosi zona de date indicată de programator ca sursă sau destinație a transferului de date.
Pentru MPI, o operație este considerată terminată local în cadrul unui proces dacă procesul a terminat partea sa de operație (atît în comunicația punct-la-punct, cît și în cea colectivă). O operație de comunicare este terminată global dacă toate procesele implicate în comunicare au terminat local părțile ce le revin din operația de comunicare.
MPI oferă 4 moduri de comunicare. În modul standard de transmisie operația de trimitere poate începe chiar dacă operația corespunzătoare de recepție nu a început. În modul ready operația send poate începe doar dacă operația corespunzătoare de recepție a început. În modul sincron, operația de trimitere poate începe oricînd, dar nu se poate termina decît atunci cînd mesajul a ajuns la receptor. Modul în care transmisia este terminată indiferent de operația pereche de recepție se numește cu buffere, datorită necesității păstrării mesajului în zone temporare pentru a asigura transmisia. În acest ultim mod, utilizatorul poate furniza sistemului un buffer pentru a permite ca operația de trimitere să se termine întotdeauna înainte ca mesajul să fie recepționat la destinație.
Modul de comunicație trebuie combinat cu un mod de blocare pentru a obține funcția ce urmează a se utiliza. MPI definește două moduri de blocare:
fără blocare (imediat), în care funcțiile de transmisie sau recepție se termină înainte ca informația să fie trimisa/recepționată. Bufferul indicat într-o funcție neblocantă nu trebuie folosit pînă la detectarea sfîrșitului funcției inițiate.
cu blocare, caz în care după terminarea funcției bufferul de transmisie sau recepiae poate fi refolosit.
În cazul comunicației imediate, MPI definește funcții care execută testul de terminare a operatei. Testul se poate face asupra terminării tuturor operațiilor dintr-o mulțime (MPI_Waitany), a unei operații dintr-o mulțime (MPI_Waitany) sau a cel puțin unei operații (MPI_Waitsome). O aplicație poate reduce latența de comunicare prin intermediul acestor operații imediate, presupunînd că platformele hardware pe care se face implementarea includ mecanisme care permit rutarea și gestiunea mesajelor în paralel cu alte calcule.
Combinînd modurile de comunicație cu cele de blocare, se obțin 8 tipuri de funcții de trimitere și 2 de recepție.
MPI nu impune restricții asupra modului de împerechere a funcțiilor de transmisie cu cele de recepție, deci orice tip de rutină de transmisie poate fi folosită cu orice tip de rutină de recepție.
O altă facilitate a MPI este reprezentată de funcția MPI_Sendrecv(), care permite, în același timp, transmiterea și așteptarea unui mesaj de la procesul partener, cu sau fără refolosirea bufferelor implicate în operații.
Identificarea mesajelor în cadrul MPI se face prin identificatorul sursei (rank) și o etichetă atașată mesajului. Ambele valori sunt interpretate relativ, în cadrul zonei de comunicație identificată de un comunicator. Este posibil ca recepția să fie facută indiferent de sursă (MPI_ANY_SOURCE) sau de etichetă (MPY_ANY_TAG).
MPI a fost proiectat pentru a opera în medii neomogene, ceea ce a impus introducerea unui mod propriu de reprezentare a datelor. MPI definește anumite tipuri de date abstracte, conversia între diferitele moduri de reprezentare a acestora pe arhitecturi diverse fiind realizată implicit de către subnivelul de comunicare MPI. Pe lîngă un set de 8 tipuri de date fundamentale (întreg, real simplă și dublă precizie, complex simplă și dublă precizie, logic, caracter și octet), MPI oferă mecanisme pentru construcția de tipuri de date agregate, ca structuri, vectori. Noul tip de date se construiește ca o listă de perechi (tip date, deplasament) și poate fi folosit apoi la fel ca un tip fundamental în MPI.
Comunicația colectivă permite difuzarea către toate procesele unui grup, sincronizarea la bariere, împarțirea/adunarea datelor de la procesele unui grup, operații globale cum ar fi suma, minim, maxim, plus comunicație de tip all-to-all. Toate aceste operații se pot împarți în două mari clase: operații de transfer de date și operații de calcul global.
Rutinele de transfer de date se referă la difuzarea datelor (broadcast), distribuirea (scatter) și colectarea rezultatelor (gather) spre sau de la procesele unui grup. Colectarea de rezultate se poate face de către toate procesele (all-gather) sau de către un singur proces. De asemenea, există operații all-to-all, în care fiecare proces trimite date către, respectiv recepționează date de la celelalte procese.
Operațiile de calcul global (sau, mai pe scurt, globale) pot fi împărțite în operații de reducere, în care funcția de reducere se aplică pe toate datele corespunzătoare fiecarui proces din grup, și operații de scanare, în care funcția de reducere se aplică pe datele proceselor cu rank mai mic decît cel al procesului care execută operația. Funcția de reducere trebuie să fie asociativă și comutativă. Rezultatul unei operații globale poate fi cunoscut de toate procesele sau doar de un singur proces. În operațiile globale pot fi folosite atît operațiile predefinite în MPI cit și cele definite de utilizator.
În cadrul comunicației colective, nu se folosesc etichete de mesaj. Coordonarea comunicației proceselor este implicită, iar toate rutinele de comunicație colectivă se blochează pînă cînd se termină local.
MPI introduce noțiunea de context de comunicare sau comunicator pentru a defini cadrul unei comunicații colective, adică procesele care sunt implicate în această comunicare.
Un comunicator definește un context de comunicare care este, de fapt, un grup de procese implicate într-un subset al calculului efectuat. Prin introducerea comunicatorilor, comunicația între subseturi de procese ale programului poate fi separată de alte comunicații din cadrul programului. Comunicația între procese din grupuri distincte este posibilă prin definirea unui inter-comunicator.
Comunicația inter-grupuri este, de obicei, gestionată de un conducător al grupului. Grupurile pot fi create și prin intermediul reuniunii, intersecției, diferenți între grupuri deja există, inițial toate procesele aparținînd comunicatorului MPI_COMM_WORLD.
Noțunea de comunicator este fundamentală pentru definirea într-un mod modular a bibliotecilor de funcții care pot fi invocate de procesele utilizator. Putîndu-și defini propriul comunicator (care este alocat de către sistem, asigurîndu-se astfel unicitatea), procesele definite de codul din biblioteci pot schimba mesaje fără a interfera cu comunicația dintre procesele aplicației utilizatorului. Alte probleme legate de implementarea unei biblioteci ca un set de procese cum ar fi codul reentrant sau invocări multiple pot fi rezolvate prin intermediul atributelor unui comunicator.
Un atribut al unui comunicator este topologia virtuală, care este topologia structurii de interconectare a proceselor dintr-un grup. Topologia virtuală este folosită pentru a mapa procesele pe arhitectura fizică. Topologia implicită este cea aleatoare.
Topologia este definită prin grupul de procese, numărul de conexiuni al fiecărui proces și partenerul pentru fiecare conexiune. Deoarece grilele carteziene sunt foarte raspindite, MPI definește operații pentru acest tip de topologie. Astfel, MPI definește operații pentru mutarea datelor de-a lungul unei dimensiuni a grilei, precum și executarea de operații colective de-a lungul unei direcții a grilei.
Topologia virtuală este distinctă de gradul programului, pentru că două procese pot comunica chiar dacă în topologie nu sunt conectate. Topologia virtuală descrie acei comunicatori care trebuie considerați de maparea grupului de procese pe arhitectura fizică. Noțiunea de topologie virtuală este utilă pentru atingerea portabilitații performanțelor atunci cînd nu este disponibil un mecanism eficient de mapare a topologiei virtuale pe un calculator masiv paralel.
Asupra tuturor implementărilor publice disponibile (MPICH, LAM/MPI, CHIMP/MPI) se impun citeva remarci generale;
nici o implementare nu este o implementare MPI nativă, ci se bazează pe sisteme de comunicare dezvoltate anterior (adică P4, LAM sau CHIMP).
Nu există o implementare care să poată fi folosită sigur în medii multithreading.
Pentru că standardul nu oferă un mecanism pentru crearea de procese, fiecare implementare se bazează pe mecanismul oferit de subsistemul de comunicare pe care s-a scris MPI.
MPICH este o implementare oferită de Argonne National Laboratory și Mississippi State University. Este o implementare completă a standardului MPI 1.1, portabilă pe toate platformele care oferă modelul de comunicare prin mesaje, incluzînd supercomputere cu memorie distribuită, multiprocesoare cu memorie partajată sau rețele de calculatoare. În cazul implementării pe rețele de calculatoare, comunicația interprocese și mecanismele de creare de procese sunt bazate pe P4. Dintre toate implementările public, MPICH este portat pe cele mai multe platforme și sisteme de operare, și datorită abordării modulare a nivelelor de comunicație pe care este bazat.
Procesele MPICH sunt definite static, prin intermediul unui fișier de configurare interpretat de biblioteca de P4. Crearea proceselor se poate face atît prin mecanisme clasice Unix, ca rsh, cît și prin intermediul unui server furnizat special pentru acest scop.
CHIMP/MPI este o implementare oferită de Edinburgh Parallel Computing Center pe baza bibliotecii CHIMP (Common High-level Interface to Message Passing), dezvoltată anterior în cadrul aceluiași centru. În mod normal, configurarea proceselor pe procesoare este realizată într-un mod pseudo-dinamic, adica sistemul poate fi configurat din interiorul proceselor utilizator la momentul rulării aplicației prin intermediul unor funcții de bibliotecă. Configurarea implică trei faze. Mai întîi, configurația este nedefinită pentru toate procesele. Apoi se intră în faza de definire a configurării, care se termină atunci cînd toate procesele au fost înștiințate de configurare. după aceasta fază, configurația mai poate fi modificată doar sincron (o facilitate a ultimei versiuni de CHIMP), pe baza grupurilor create inițial.
LAM/MPI (from Local Area Multicomputer) este mai mult decît o implementare de MPI, oferind un nucleu de sistem de operare distribuit pentru un multicomputer (constituit din stații de lucru Unix) bazat pe comunicația cu mesaje. Sistemul își are rădăcinile în sistemul de operare Trollius, de la care moștenește principalele sale caracteristici. Controlul destul de performant al tuturor proceselor care rulează ca procese lansate de LAM poate fi un bun argument pentru alegerea acestei platforme pentru programarea MPI. Mecanismul de creare de procese, preluat tot din Trollius, permite crearea unui proces pe baza unei imagini transmise prin rețea, fiind o soluție foarte bună pentru utilizatorii care nu doresc folosirea sistemului NFS pentru pornirea programelor pe stațiile care alcătuiesc multicomputerul. Ultima versiune a MPI/LAM introduce un mod de comunicare direct între procesele MPI, prin ocolirea demonului de comunicare, lucru care accelerează sensibil comportarea unei aplicații MPI. În plus, versiunea LAM poate fi atractivă și pentru operațiile cu fișiere la distanță sau pentru diferitele posibilitați pe care le mai poate oferi în afara de MP, numind aici PVM și o versiune de Linda numita Brenda.
Mai sunt de menționat și implementările bibliotecilor de funcții, majoritatea pentru calcule științifice, sense cu ajutorul MPI. Astfel, există biblioteci de funcții pentru rezolvarea paralelă a sistemelor liniare, a ecuațiilor neliniare, factorizări și diferite operații necesare în calculul matricial, pentru vizualizări și grafică și grafică în mediul XI 1, pentru operații de intrare ieșire în paralel și lista ar putea continua chiar și cu exemple comerciale, nu numai din domeniul public.
Forumul MPI își continuă efortul de standardizare, anul viitor urmînd să apară versiunea 2 a standardului MPI. De asemenea, se vor aduce corecții la standardul actual (1.1), versiunea de referință pentru MPI-1 devenind MPI-1.2.
Noutățile care sunt așteptate în versiunea a doua a standardului includ procese dinamice (se prevede eliminarea modelului static al proceselor prin oferirea de rutine pentru crearea și eliminarea de procese), comunicații uni-direcționale (care includ operații cu memoria partajată de tip put/get sau read-modify-write), operații colective extinse, interfețe exteme pentru interfațarea cu nivele care se sprijină pe MPI, interfața de programare pentru C++ și Fortran 90, operații de intrare/ieșire paralele și suportul oferit de MPI pentru procesarea evenimentelor în timp real.
Așa cum se poate remarca, MPI este un standard în evoluție, eforturile depuse de lumea științifică și de cea comercială pentru susținerea acestui standard fiind relevante pentru succesul MPI.
MPI este un standard pentru programarea sistemelor distribute prin modelul schimbului de mesaje care merită să fie luat în seamă. Existența a cel puțin trei implementări publice de calitate (MPICH, LAM, CHIMP) permite fiecărui programator dornic de a învăța MPI să poată rula programe MPI pe o rețea de calculatoare. MPI nu impune folosirea unor alte instrumente de programare, iar utilitarele scrise pentru o versiune de MPI se pot folosi și pentru celelalte. Definirea interfeței prin care programatorul are acces la informațiile de performanță conduce la posibilitatea de a scrie instrumente de analiză care să nu fie în legatură directă cu codul sursă al diferitelor implementări. Operațiile de transmisie și recepție imediată permit suprapunerea calculelor cu operațiile de comunicare, ceea ce duce la un model perfect asincron de programare și la creșteri de performanță. Mecanismele de lucru cu grupuri de procese asigură robustețea prin apartenența statică la grup, evitîndu-se astfel probleme de concurență legate de intrarea sau părăsirea grupului de către membrii săi. Folosirea pentru transmisie a zonelor de date furnizate de programator evită supraîncarcări legate de copieri inutile. Mecanismele introduse de comunicatori permit crearea de biblioteci de funcții paralele care se pot executa în cadrul oricărui program fără a exista riscul de interferență între traficul aplicației și cel al funcțiilor de bibliotecă. Suportul pentru topologii virtuale face posibilă utilizarea unor mecanisme automate sau semiautomate pentru rularea eficientă pe arhitecturi masiv paralele.
MPI este un standard specificat formal, cu o semantică precisă, care asigură o mare portabilitate a aplicațiilor, atît din punct de vedere al codului, cît și al performanțelor.
2.3 Tehnologia CORBA
Pentru a simplifica programarea aplicațiilor distribuite și a permite realizarea de software bazat pe componente, s-a standartizat un model distribuit orientat pe obiecte, CORBA (Common Object Request Broker Architecture).
CORBA este un model de programare distribuită, orientat pe obiecte, propus de către OMG (Object Management Group)( http://www.omg.org). OMG este o organizație înființată în 1989, având ca scop dezvoltarea, adoptarea și promovarea de standarde pentru dezvoltarea de aplicații iî medii distribuite eterogene.
În centrul modelului arhitectural CORBA se află conceptul de Object Requcst Broker (ORB). care are un rol de "magistrală software" care intermediază interacțiunea transparentă a unor obiecte, atât local cât și la distanță [Vinoski97]. Un obiect CORBA este reprezentat printr-o interfață și un set de metode. O instantă a unui obiect este identificată printr-o referință la obiect. Clientul unui obiect CORBA obține referința obiectului și o utilizează ca un handle în realizarea apelurilor metodelor ca și cum obiectul ar fi localizat în spațiul de adrese al clientului. ORB este responsabil de mecanismul necesar găsirii implementării obiectului, pregătirii acesteia pentru primirea unei cereri, comunicarea cererii și transmiterea rezultatului înapoi spre client. Implementarea obiectului interacționează cu ORB prin intermediul lui Object Adapter (OA) sau prin ORB Interface.
Modelul CORBA este bazat pe comunicații de tip client-server. Când cere un serviciu, un client invoca o metodă implementată de un obiect aflat la distanță, care se comportă ca un server din modelul client-server. Serviciul oferit de server esle încapsulat ca un obiect și interfața obiectului este descrisă într-un limbaj numit Interface Description Language(IDL). Interfața definită în IDL servește ca un contract între un server și clienții săi.
Clienții interacționează cu serverul prin invocarea metodelor descrise în IDL. Implementarea obiectului este ascunsă clienților. La nivelul IDL sunt prezente unele caracteristici ale programării orientate pe obiecte, cum ar fi: încapsularea, polimorfismul și moștenirea simplă sau multiplă. De asemenea se permite specificarea excepțiilor. Un avantaj important al OMG IDL este independentă de limbaj. Deoarece OMG IDL este un limbaj declarativ, nu un limbaj de programare, el forțează definirea interfețelor separat de implementările obiectelor. Aceasta permite ca obiectele să fie construite folosind diferite limbaje de programare și totuși să poată comunica între ele. Interfețele independente de limbaj sunt importante în cadrul sistemelor heterogene, unde nu orice limbaj de programare este suportat sau disponibil pe orice platformă.
Interacțiunea între un proces client și un obiect server sunt implementate în stilul apelului de procedură la distanță – Remote Procedure Call (RPC). Figura 1 prezintă structura tipică pentru RPC.
Fig.3 Structura clasică RPC
Pentru a invoca o funcție la distanță, clientul face un apel la funcția stub-client. Stub-ul împachetează parametrii de apel într-un mesaj pe care îl transmite folosind protocolul de rețea către stub-ul server. Pe partea server-ului, protocolul de rețea recepționează mesajul și îl transmite stub-ului server, care despachetează mesajul și apelează funcția care trebuie să efectueze cererea. În terminologie CORBA, stub-ul client poartă denumirea de stub, dar stub-ul server este denumit skeleton.
Modelul de referință OMA (Object Management Architecture)
CORBA este componenta de baza a unui model mai extins elaborat de OMG, modelul OMA (Object Management Architecture). Figura 2 prezintă componentele modelului de referință OMA.
Fig.4 Componentele modelului de referință OMA
Principala componentă a modelului OMA este Object Request Broker (ORB). Acesta este responsabil cu facilitarea comunicării între clienți și obiecte.
Celelalte 4 categorii de interfețe, care utilizează componenta ORB, sunt: Object Services, Common Facilities, Domain Interfaces și Application Interfaces.
• Object Services: Acestea sunt interfețe independente de domeniu, folosite de majoritalea programelor. Serviciile specificate de CORBA sunt: Concurrency Control Service, Event Service, Naming Service, Transaction Service, etc.
• Common Facilities: acestea sunt utile în construcția aplicațiilor din mai multe domenii. Principalele categorii de common facilities sunt: user interface facilities, information management facilities, system management facilities, task management facilities
• Domain Interfaces: au un rol asemanător cu object services și common facilities, dar sunt orientate înspre anumite domenii de aplicații (financiare, medicale, business, telecomunicații)
• Application Interfaces: aunt interfețe dezvoltate special pentru anumite aplicații; acestea nu sunt încă standartizate.
Rolul și proprietățile de bază ale ORB
Figura 3 prezintă o cerere trimisă de către un client către o implementare a unui obiect.
Fig.5 Cerere transmisă prin intermediul unui ORB
Clientul este o entitate care dorește să realizeze o operație și Object Implementation este codul și datele care implementează obiectul. ORB asigură mecanismele necesare pentru găsirea implementării, pregătirea obiectului de a primi mesajul, comunicarea datelor. Interfața pe care o vede clientul este complet independentă de locul unde este localizat obiectul, de limbajul de programare în care este implementat acesta sau de orice alt aspect care nu este reflectat în interfața obiectului.
Sarcinile nucleului ORB (ORB Core)
ORB livrează cererile catre obiecte și returnează răspunsurile către clienți. Principalul scop al ORB este de a asigura transparența comunicării client-obiect.
ORB ascunde următoarele informații despre obiectul țintă (server):
• locația obiectului: clientul nu cunoaște unde se află obiectul țintă (target object). Acesta poate să fie într-un proces pe o mașină din rețea, pe aceeași mașină ca și clientul dar în alt proces sau în același proces cu acesta.
• implementarea obiectului: clientul nu cunoaște cum este implementat obiectul, în ce limbaj de programare a fost scris, nici pe ce sistem dc operare sau hardware funcționează.
• starea execuției obiectului: când face o cerere, clientul nu știe dacă obiectul apelat este curent activat și gata să accepte cereri. Este sarcina ORB-ului să pornească serverul , dacă e necesar, înainte de a-i livra cererea.
• mecanismul de comunicare: clientul nu știe ce fel de mecanism (de ex. TCP/IP, shared memory, apel local de procedură) foloseste ORB pentru a livra cererea și a returna răspunsul.
Aceste proprietăti ale ORB permit celor care dezvoltă aplicații să se concentreze numai asupra domeniului aplicației și să ignore aspectele de programare distribuită de nivel scăzut.
Structura unui ORB . Vedere de ansamblu
Principalele facilități componente ale CORBA sunt: ORB Core, OMG Interface Definition Language, Interface Repository, Language Mappings, Stubs and Skeletons, Dynamic Invocation and Dispatch, Object Adapters, Inter-ORB Protocols. Majorilatea dintre acestea pot li regăsite în figura 4, care arată de asemenea și modul în care componentele CORBA sunt legate unele de altele. Fiecare componentă va fi descrisă mai în detaliu în următoarele capitole. Figura 4 prezintă structura unui ORB și interfețele acestuia. Interfețele ORB-ului sunt reprezentate prin dreptunghiuri, iar săgețile indicate dacă ORB-ul este apelat sau efectuează apeluri de tip "up-call".
Fig.6 Structura ORB și interfețele sale
Pentru a transmite o cerere, clientul poate folosi fie Dynamic Invocation Interface(aceeași interfață independent de interfața obiectului țintp) sau un IDL Stub(stub specific dependent de interfața obiectului țintă).
Clientul mai poate de asemenea interacționa direct cu ORB, prin unele funcții.
ClientuI trebuie să aibă acces la o Object Reference pentru a transmite cererea. Atât DII cât și Stub Interface satisfac aceeași semantică a cererii iar obiectul care recepționează mesajul nu poate deduce prin care mecanism s-a efectuat cererea.
ORB localizează codul adecvat al implementării, transmite parametrii și transferă controlul către Object Implementation.
Implementarea obiectului recepționează o cerere ca și un up-call, fie prin intermediul skeleton-ului static generat pentru un IDL, sau printr-un skeleton dinamic. Implementarea obiectului poate apela Object Adapter și ORB în timp ce procesează o cerere sau la orice alte momente.
Fig. 5 arată cum informațiile despre interfețe și implementări sunt facute accesibile clienților și implementărilor. Interfața este definită în IDL și/sau Interface Repository; această defniție este folosită la generarea stub-urilor client și a skeleton-urilor implementărilor. Informațiile despre implemenlea unui obiect sunt furnizate la momentul instalării și stocale în Implementation Repository pentru a fi utilizate în timpul livrării cererilor.
OMG Interface Description Language(IDL)
OMG IDL este un limbaj folosit la definirea interfețelor obiectelor CORBA. Obiectele CORBA sunt văzute numai în termenii interfețelor lor. IDL asigură incapsularea implementării unui obiect în spatele unei interfețe care este independentă de limbajul de implementare, de algoritmul folosit la implementare, de localizarea obiectului, de arhitectura mașinii pe care rulează, de sistemul de operare și tehnologia rețelei. Această separare a interfeței de implementare dă posibilitatea de a vedea CORBA ca o "magistrală software" (software bus) și constituie unul din punctele forte ale CORBA.
O interfață a unui obiect specifică operațiile și tipurile suportate de obiect, definește cererile care pot fi adresate obiectului. Interfețele sunt definite în limbajul IDL. Interfețele sunt similare claselor în C++ și interfețelor în Java.
Un exemplu de interfață IDL este:
Fig.7 Interfață IDL
// OMG IDL în fișierul grid.idl
interface Grid {
readonly attribute short height;
readonly attribute short width;
void set (in short x, in short y, in long value};
long get (in short x, in short y) ;
};
Interfața Grid are 2 atribute, height si widt, care definesc dimensiunile tabelei. Deoarece au fost etichetate "readonly" nu pot fi modificate direct. Există și două operații: set si get, care permit modificarea valorii unui anumit element și respectiv returnează o valoare. Parametrii operațiilor sunt etichetați ca parametrii in, deci sunt parametrii de intrare, transmiși de la client la client la server. De asemenea, mai pot exista parametrii de tip out (de la server la client) sau inout (în ambele direcții).
Mapping of OMG IDL to Programming Languages
După cum s-a menționat, OMG IDL este doar un limbaj declarativ, nu un limbaj de programare. De aceea nu are facilități privind descrierea unor structuri de control, nici nu este folosit direct pentru implementarea unor aplicații distribuite.
Language mapping slabileșle modul cum facilitățile IDL sunt mapate pe facilitățile oferite de diferite limbaje de programare. Există reguli de mapare pentru C, C++, Smalltalk, ADA si Java.
Interface Repository
Fiecare aplicație bazată pe CORBA necesită acces la sistemul de tipuri al OMG IDL în timpul execuției.
Interface Repository este un serviciu care furnizează obiecte persistente care reprezintă informațiile IDL într-o formă disponibilă la runtime. Informațiile din Interface Repository pot fi folosite de către ORB pentru realizarea cererilor. Este posibil ca, utilizând Interface Repository, un program să întâlnească un obiect a cărui interfață nu era cunoscută atunci când programul a fost scris și compilat, dar acum programul poate afla care sunt operațiile permise asupra obiectului și să realizeze o invocare.
Stubs and Skeletons
Pe lângă generarea de tipuri corespunzătoare limbajului de programare, compilatoarele și translatoarele de IDL generează și stub-uri client si skeleton-uri server. Un stub este un mecanism care crează și transmite efectiv mesajele de cerere, iar un skeleton este mecanismul care livrează cererea către implementarea obiectului. Deoarece sunt generate direct din specificațiile IDL, stub-urile și skeleton-urile sunt în mod normal specifice interfeței.
Dynamic Invocation and Dispatch
Pe lângă invocarea statică prin stub-uri și skelelon-uri, CORBA suportă 2 interfețe pentru invocarea dinamică:
• Dynamic Invocation Interface (DII) – suportă invocări dinamice
• Dynamic Skeleton Interface (DSI) – asigură dynamic dispatch către obiecte
Dynamic Invocation Interface
Folosind DII o aplicație client poate invoca cereri către orice obiect, fără a avea cunoștințe despre interfețele obiectului la momentul compilării. Aceasta înseamnă că în loc să apeleze o rutină stub specifică unei anumite operații a unui anumit obiect, un client poate realiza specificarea obiectului care va fi invocat, a operației de executat și a setului de parametri, printr-un apel sau o secvență de apeluri. Clientul trebuie să dea informații despre operația ce trebuie efectuată și tipurile parametrilor, informații obținute de la Interface Repository sau din alte surse la runtime.
Dynamic Skeleton Interface
La fel cum DII permite clienților să invoce cereri fără să aibă acces la stub-uri statice. DSI permite serverelor să fie scrise fără să aibă skeleton-uri pentru obiectele invocate la compilare.
Implementation Repository
Implementation Repository conține informații care permit ORB să localizeze și să activeze implementările obiectelor. Instalarea unei implementări și controlul activării și execuției obiectelor se realizează prin intermediul unor operații asupra Implementation Repository.
Object Adapters
Object Adapter (OA) servește ca liant între implementările obiectelor CORBA și ORB. Un object adapter este un obiect care adaptează interfața unui alt obiect la inlerfața așteptată de apelant. OA este un obiect care permite apelantului să invoce cereri către un obiect chiar dacă apelantul nu cunoașle interfața reală a acelui obiect.
Responsabilitățile OA cuprind urmatoarele:
• Înregistrarea obiectelor – OA oferă operații care permit ca anumite entități implementate în limbaje de programare să fie înregistrate ca implementări ale obiectelor CORBA. Detalii privind ce și cum se înregistrează depind de limbajul de programare.
• Generarea referințelor la obiect – OA generează referințele pentru obiectele CORBA
• Activarea proceselor server – dacă este necesar, OA pornește procesul care conține serverul
• Activarea obiectelor – OA activează obiectele dacă acestea nu sunt active când sosesc cereri pentru acestea
• Demultiplexarea cererilor – OA trebuie să coopereze cu ORB pentru a asigura că se pot primi mai multe cereri și că nu există posibilități de blocare pe nici o conexiune
Inter-ORB Protocols
Interoperabilitatea este posibilă între ORB-uri diferite, dar conforme CORBA. S-au specificat două protocoale, GIOP (General Inter-ORB Protocol) și UOP(lnternet Intcr-ORB Protocol). GIOP specifică sintaxa de transfer și un set de formate de mesaje, acceptabile pe orice tip de protocol orientat pe conexiune. IIOP specifică modul cum GIOP poate fi implementat deasupra protocolului TCP/IP.
3 ELABORAREA REȚELEI DE PRELUCRARE DISTRIBUITĂ A IMAGINILOR
3.1 Formularea sarcinii pentru proiectul de diplomă
Lipsa în Republica Moldova a unui sistem centralizat de stocare și prelucrare a datelor personale este o problemă strigentă, care n-a fost pînă în prezent rezolvată din cauza prețului enorm a astfel de sisteme. Acest fapt a condiționat la crearea unui sistem autonom de acest fel. Structura unui astfel de sistem de sistem este arătată în fig.8.
Avem la dispoziție un server cu bază de date, cîteva module de recunoaștere compuse din bloc de sistem cu plachetă de I/E și procesor optic și stații de lucru conectate la server. Aceasta este structura unui sistem complex pentru identificarea persoanelor după amprentele digitale.
Pe server se instalează baza de date, aplicația server și aplicația client la care se conectează stațiile de lucru. Aplicația client are acces direct la baza de date pentru a face înscrieri noi despre personae, despre care se completează datele de pașaport, fotografia, antecedentele penale și amprentele digitale. Aplicația server transmite la modulele de prelucrare pentru caompararea imaginii sursă cu cîte o imagine din baza de date , rezultatul fiind întors la server. După ca se compară imaginea sursă cu toate imaginile din baza de date se transmit rezultatele compară în formă de o valoare numerică la aplicația client.
Rezolvarea problemei date presupune divizarea ei în mai multe sarcini:
Elaborarea structurii rețelei distribuite care realizează funcția de paralelizare a procesului de recunoaștere a amprentelor
Modelarea funcționării rețelei proiectate cu utilizarea limbajului de programare Perl în scopul de a obține configurația optimă a rețelei pentru utilizareaa cât mai eficientă a resurselor folosite.
Investigarea modelului elaborat pentru diferite valori a vitezei de transfer a datelor în rețea .
Analiza datelor investigațiilor și calcularea numărului optim de module de recunoaștere utilizate pentru paralelizarea procesului de identificare a imaginilor amprentelor digitale.
Analiza posibilității de optimizare a productivității rețelei prin extinderea numărului de servere în scopul de a mări viteza de recunoaștere în cazul când există o suprasolicitare de cereri de identificare, dar care nu pot fi prelucrate în timp real, sau când baza de date conține un număr mare de înregistrări.
Fig.8 Structura sistemului de recunoaștere a amprentelor digitale
3.2 Proiectarea rețelei
Rețeaua dată constă dintr-un server (sau mai multe) și câteva module cu procesoare optice. Pe servere se păstrează baza de date cu datele despre persoane și aplicația server care primește cererea de la aplicația client și transmite imaginea cu amprenta digitală (care servește ca etalon) la modulele cu procesoare optice, care compară imaginile primite și trimite ca rezultat un semnal care indică coincidența lor. După ce aplicația server compară toate imaginile din baza de date cu imaginea etalon se trimit la aplicația client datele de coincidență.
Aplicația server notează care modul de recunoaștere este ocupat și care nu. De asemenea aplicația memorizează timpul dintre trimiterea cererii și primirea răspunsului – determinând care modul optic este mai productiv, făcând astfel balansarea dintre modulele optice.
În cazul multor cereri simultane aplicația le pune în rând și/sau stabilește daca nu sunt coincidențe între cereri. De asemenea este realizat regimul cache-ului sau cum mai este numit – cererile frecvente. În acest caz deoarece răspunsul deja a fost cerut într-o perioadă recentă de timp el este dat din baza cererilor frecvente. Pentru a nu da date greșite sau învechite programul compară indicatorul imaginii recente cu cel din baza de date folosind accesul direct. Această metodă permite de a micșora simțitor timpul de acces și căutare în bazele de date și nu încarcă deloc modulele optice. Mai mult ca atât procedura dată practic garantează coincidența amprentelor.
Fizic rețeaua poate fi implementată după mai multe standarde: 10 Mbiți/sec, 100 Mbiți/sec, 1Gbit/s (500 Mbiți/sec viteza maximală a hard-ului).
Calcule și date despre rețea
Pentru rețeaua de 10 Mbiți/sec avem următorii timpi pentru prelucrarea unei imagini a amprentei digitale
Fig.8 Schema rețelei pentru viteza de conectare 10 Mbiți/sec
Tab.1
Timpii de prelucrare a amprentelor
Tab.2
Timpii de prelucrare a 100 amprente pentru viteza 10 Mbiți/sec
Deci pot fi conectate maximum 3 module cu procesoare optice
Pentru rețeaua de 100 Mbiți/sec avem următorii timpi pentru prelucrarea unei imagini a amprentei digitale
Fig.9 Schema rețelei la viteza 100Mbiți/sec
Tab.3
Timpii de prelucrare a amprentelor
Tab.4
Timpii de prelucrare a 100 amprente pentru viteza 100Mbiți/sec
Deci pot fi conectate maximum 7 module cu procesoare optice
Pentru rețeaua de 500 Mbiți/sec avem următorii timpi pentru prelucrarea unei imagini a amprentei digitale
Fig.10 Schema rețelei pentru viteza 500 Mbiți/sec
Tab.5
Timpii de prelucrare a amprentelor
Tab.6
Timpii de prelucrare a 100 amprentelor pentru viteza 500Mbiți/sec
Deci pot fi conectate maximum 28 module cu procesoare optice
Dacă este o suprasolicitare de cereri de identificare , care nu pot fi prelucrate în timp real se poate de conectat încă un server care să lucreze cu o bază de date duplicat în regim”oglindă”, dacă baza de date conține un număr mare de înregistrări atunci se mai pune un server pe care se fac următoarele înscrieri. Pe aceste servere se instalează softul necesar.
3.2 Elaborarea programului
Avem un server conectat la rețea pe care este instalată o bază de date, cîteva calculatoare cliente și cîteva servere. Scopul e: de efectuat programul server care primeste cererile de la programul client pentru identificarea amprentelor degetale utilizînd bibliotecile de programare paralela pentru prelucrarea datelor pe cîteva servere optice concomitent.
Programul random.pl generează cereri care trebuiesc deservite și timpul de deservire a serverelor optice, rezultat care se înscrie în fișierul FILE. (Anexa 1)
În acest fragment de program se generează identificatoarele ID pentru cereri:
srand;
$r=int rand 9999;
$user="$r$^T";
Se primește formula pentru imagine: $formula=$ENV{QUERY_STRING};
Se inițializează lista IP-adreselor modulelor de recunoaștere:
@SERVERS=(
'xxx.xxx.xxx.xxx',
'xxx.xxx.xxx.xxx',
'xxx.xxx.xxx.xxx'
);
$N=@SERVERS;
Se trimit cereri de deservire la modulele de recunoaștere:
foreach $s(@SERVERS)
{
$r=get("$s?$formula&$user");
}
Se așteaptă răspunsurile de la modulele de recunoaștere:
$flag=1;
while ($flag==1)
{
$v=-s "process/c$user";
if ($v>=$N) {$flag=0;}
}
Se primesc răspunsurile de la servere:
open FILE,"process/$user";
$result=<FILE>;
close FILE;
Se șterg fișierele temporare:
`rm process/$user`;
`rm process/c$user`;
Se scot rezultatele : print $result;
Programul exe.pl prelucrează cererile verificînd datele cu cele din baza de date_ după ce rezulatul se înscrie în baza de date. (Anexa 2)
Se inițializează segmentul în care se află înscrierile din baza de date:
$linim_A=100;
$limit_B=200;
Se prelucrează datele de intrare, se ia numele persoanei și formula:
$in=$ENV{QUERY_STRING};
$in=~/(.+?)&(.+?)/;
$formula=$1;
$user=$2;
Se prelucrează formulele din baza de date:
$REZULT=0;
for ($this=$limit_A;$this<=$limit_B;$this++)
{
Se inițializează datele pentru prelucrare:
$cond=" WHERE id=$this";
$sth=$dbh->prepare(q{select formula from base }.$cond);
$sth->execute;
$rv=$sth->bind_columns(\$_formula);
if ($sth->fetch())
{algoritmul de comparare}
Înscrierea rezultatului pe server:
$r=get("mainserver/cgi-bin/back.cgi?$r&$user")
}
Programul rezult.pl după verificare înscrie datele rezultante în fișierul FILE pe care îl citește calculatorul client care a transmis cererea. (Anexa3)
Se prelucrează datele de intrare:
$in=$ENV{QUERY_STRING};
$in=~/(.+?)&(.+?)/;
$result=$1;
$user=$2;
Se generează rezultatul:
open FILE,">>process/$user";
print FILE "result\n";
close FILE;
open FILE,">>process/c$user";
print FILE "*";
close FILE;
Schema-bloc este prezentată în Anexa 4.
4 CALCULAREA SINECOSTULUI PROGRAMULUI
La etapa actuală de dezvoltarea țării, când au loc schimbări esențiale în diferite probleme legate de economie, planificare, piață, o cerință principală în pregătirea inginerilor de toate specialitățile este pregătirea organizator – economică la un nivel înalt, deoarece aceasta este dictat de trecerea întreprinderilor la autofinanțare, de schimbarea relațiilor între întreprinderi, de trecerea la economia de piață.
Lucrarea de diplomă trebuie să corespundă cerințelor generale, înaintate proiectelor tehnice, pe baza cărora este creată tehnica nouă și în ea trebuie să fie reflectată aprecierea tehnico-economică a proiectelor elaborate și organizarea LEP (lucrare economică de proiectare), care se folosește în organizațiile de proiectare și cercetări științifice.
Deoarece lucrarea de diplomă conține mai multe lucrări de proiectare și experimentale, ea aparține clasei lucrărilor LEP. Deaceea toate calculele economice sînt efectuate ca pentru LEP.
Tab.7
Cheltuielile materiale de elaborare a proiectului
Tab.8
Cheltuielile indirecte de elaborare a proiectului
Efectuarea calculelor s-au efectuat conform următoarelor date:
Energia electrică – 0,65 bănuți pentru 1 kW: 1 calculator timp de 166 zile cîte 8 ore cu coeficientul de utilizare 0,8, care consumă 200w pe oră = 137,6 lei
Energie termică – aproximativ 250 pentru 1 Gcal
Bibliografia
Servicii de telecomunicații, telefon – 50 lei pe lună
Cheltuieli de reparații = 2.5% din costul ei = 237,5 lei
Paza = 200 lei * 6 luni = 1200 lei
Cheltuieli de transport = 5% din cheltuieli materiale = 1155,50 lei
Am împărțit efectuarea proiectului pe etape de lucru, ce va fi foarte important la alcătuirea grafului rețea și la calculul cheltuielilor.
Tab.9
Etapele de lucru
În dependență de etapele de lucru fiecare colaborator a proiectului participă la diferite etape după cum este reprezentat în tabelul următor
Tab.10
Etapele de lucru cu repartizarea zilelor
Tab.11
Salariile
Defalcări de bază se calculează din considerația a 22 zile lucrătoare pe lună și 8 ore pe zi. Salariul suplimentar constituie 20% din salariul de bază.
Contribuții pentru asigurări sociale se ia 31% din salariul de bază și cel suplimentar.
La construirea grafului-rețea se fac următoarele calcule:
La construirea grafului-rețea se face următoarele calcule:
,
, ,
, .
Aici Td – timpul devreme de efectuare a evenimentului; Tt – timpul târziu de efectuare a evenimentului I; Ri – rezerva de timp pentru efectuare evenimentului I; Ni – numărul evenimentului; Rig – durata efectuării lucrării IG; Rdig – rezerva deplină de timp a lucrului IG; Rlig – rezerva liberă de timp pentru lucrul IG.
Drumurile critice vor fi
1 – 2 – 6 – 7 – 10 – 11 – 12 – 13 – 14 – 16 – 17 – 18 – 19 – 20 – 21 – 22 – 23
1 – 2 – 6 – 8 – 10 – 11 – 12 – 13 – 14 – 16 – 17 – 18 – 19 – 20 – 21 – 22 – 23
1 – 2 – 6 – 9 – 10 – 11 – 12 – 13 – 14 – 16 – 17 – 18 – 19 – 20 – 21 – 22 – 23.
Sinecostul = Cheltuieli materiale + cheltuieli indirecte + Salarii + Amortizarea =
23110+3324,14+5505,98+6054 = 37994,12 lei
Prețul de livrare angro= Sinecostul + Profit= 37994,12*1,2 =45592,94 lei
Prețul de livrare = prețul de livrare angro + TVA = 54711,53 lei
Prețul de cost de instalare:
Prețul de instalare = Cheltuieli de elaborare + Cheltuieli de instalare + Profit
Tab.12
Cheltuieli de instalare
Prețul de instalare = 101989,84
Tab.13
Cheltuieli de deservire
Cheltuieli de deservire = 1750 + Profitul + TVA = 2450
Deoarece procurarea softului și hardului în domeniul Tehnologiilor Informaționale se consideră investiție capitală, vom amortiza aceste cheltuieli în timp de 2 ani fiindcă sunt supuse uzurii morale rapide:
[S/(A*365)]*Z
unde: S – suma ce trebuie de amortizat;
A – perioada de amortizare în ani;
Z – perioada proiectului în zile.
[26000/(2*365)]*170=6054 lei
În finisarea proiectului cu succes și exploatarea lui eficientă sunt cointeresați toți participanți, realizând în așa mod interesele proprii, și anume:
clientul primește proiectul și veniturile pe sama lui;
conducătorul proiectului și colaboratorii lui primesc plata prestabilită și ridicarea calificării.
Business-plan ușureasă rezolvarea problemelor și opstaculelor ce pot apărea sub influiența unor factori interni și externi în condiții actuale de tranziție economică a țării noastre așa ca:
o economie instabilă;
dificitul și limitările a resurselor și mijloacelor;
inflația și majorarea costului proiectului;
probleme și necesități sociale;
creșterea cerințelor față de calitatea productului.
Dacă condițiile sus enumerate nu sunt cercetate, ele pot duce la apariția diferitor probleme, de exemplu: depășirea costului prestabilit, longitivității și termenelor de finisare a proiectului; scăderea eficacității și marirea termenului de recuperare a productului.
În condițiile formate lucrul inginerului va conține nu numai găsirea soluționărilor progresiste, ci și argumentarea tehnico-economică, ce va demonstra că alegearea variantei date este cea mai potrivită și economic efectivă.
5 PROTECȚIA MUNCII LA ÎNTREPRINDERE
5.1 Aprecierea pericolului la monitor
Odată cu dezvoltarea tehnicii de calcul tot mai mult se atrage atenția asupra problemelor protecției utilizatorilor, în special acelor care lucrează la calculator, adică lângă monitor. Principalii factori dăunători, care influențează asupra sănătății omului, când acesta lucrează lângă monitor sunt:
radiația sau iradieri ionizate;
câmpul electrostatic;
câmpul electromagnetic, etc.
Iradieri Ionizate reprezintă iradierea electro-magnetică cu o capacitate de ionizare a moleculelor. Dacă se provoacă ionizarea moleculelor organismului uman, atunci legăturile între molecule se distruge și ca rezultat apar diferite boli. Capacitatea de ionizare o au următoarele particule: X- iradieri, fluxul de electroni, substanțele radioactive.
În cazul monitoarelor cel mai semnificativ tip de iradiere ionizată este – iradiere, care însă este foarte mică, de obicei nu depășește normele biologice. Celelalte tipuri de iradieri pot fi neglijate deoarece greu pot fi depistate.
– iradierea apare în urma ciocnirii electronilor cu atomii substanței luminofore sau cu atomii ecranului din sticlă.
Pentru a micșora iradierea ionizată a monitoarelor moderne, pe suprafața lor se aplică o foaie metalică străvezie, care atenuează fluxul de iradiere. O altă cale de apărare împotriva iradierii ionizate este procurarea unui ecran protector, care se instalează pe monitor și are același efect ca și foaia metalică străvezie.
În genere iradierea ionizată asupra omului poate provoca următoarele acțiuni:
locale – acțiuni de scurtă durată cu doze mari, care aduce la traume locale: îmbolnăvirea pieii, pierderea pieii, pierderea unghiilor, defectarea oaselor, cancer;
totale – reprezintă iradieri îndelungate cu doze mici, aduce la îmbolnăvirea sângelui (leucemie).
Câmpul electrostatic, care apare pe ecranul monitorului este rezultatul bombardării permanente a monitorului cu fascicolul de electroni emis de catod. Astfel sarcina electrică, case se acumulează pe suprafață monitorului, formează câmpul electrostatic. Fenomenul electrizării statice este legat și de starea aerului din mediu. În condiții normale aerul se caracterizează cu proprietăți izolatorii înalte, însă sub acțiunea razelor solare și celor cosmice, radiației materialelor radioactive a scoarței pământului și a altor factor ionizatori, moleculele neutrale a aerului se ionizează, formând ioni pozitivi și negativi – purtători ai sarcinii electrice. Dacă intensitatea câmpului electric, format de materialele, de dispozitivele de curent continuu și de obiectele, care ușor se electrizează, este mare, atunci ionii liberi obțin energie cinetică suficientă pentru a forma ioni noi la ciocnirea lor cu moleculele neutre. În urma ionizării aerul își pierde proprietatea sa de izolator (devine conductibil) și descărcarea electrică latentă se transformă într-o descărcare sferică, adică are loc o străpungere electrică a aerului.
Descărcarea electricității statice poate provoca o explozie, incendiu și alte accidente. La unele întreprinderi, care produc substanțe sintetice, polimeri și produse din aceste substanță, și care posedă proprietăți dielectrice înalte, electrizarea micșorează productivitatea muncii și este unul din motive care duc la scăderea calității producției.
Influența sistematică a câmpului electrostatic de intensitate înaltă asupra corpului omului poate duce la unele dereglări funcționale a sistemului central nervos, a sistemului cardio-vascular și a altor organe. Din aceste motive, intensitatea maxim-admisibilă a câmpului electric la locurile de muncă este normată:
Tab.8
Intensitatea maxim-admisibilă a câmpului electric la locurile de muncă
Intensitățile admisibile a câmpului electrostatic sînt indicate fără a lua în considerație influența asupra omului a descărcărilor electrice. Normele indicate pentru intensitatea câmpului electrostatic mai mare de 20 kW/m se utilizează numai cu condiția, restul timpului a zilei de lucru intensitatea nu întrece 20 kW/m. Dacă intensitatea câmpului electrostatic întrece valorile indicate, atunci se aplică unele măsuri de micșorare a ei.
Măsurile principale de micșorare a intensității câmpului electric în zona de lucru sânt:
îndepărtarea surselor a câmpurilor electrostatice din zona personalului care deservește aparatura;
ecranarea sursei câmpului sau a locului de muncă;
utilizarea neutralizatorilor de sarcini electrice statice;
umezirea materialului care se electrizează;
schimbarea materialelor, care ușor se electrizează cu materiale ce nu se electrizează;
alegerea suprafețelor care contactează conform condițiilor de electrizare minimă;
modificarea procesului tehnologic în așa mod ca să se micșoreze nivelul de electrizare;
alegerea materialelor și suprafețelor care greu electrizează alte corpuri sau le electrizează cu sarcini de polaritate diferită;
instalarea în toate încăperile, unde se află oameni, a podelelor care conduc curentul electric.
În calitate de măsură de protecție individuală a omului de la electricitatea electrostatică poate servi încălțămintea ce conduce curentul electric, albituri, halat, etc. adică tot ce asigură legătura electrică a corpului omului cu pământul.
În majoritatea monitoarelor moderne problema câmpului electrostatic este parțial rezolvată prin introducerea tehnologiei antistatice. Datorită acestei tehnologii câmpul electrostatic se micșorează până la 10% din intensitatea inițială a acestuia. În afară de această majoritatea ecranelor protectoare, care micșorează iradierea ionizată, mai sigură și atenuarea considerabilă a câmpului electrostatic.
Câmpul electromagnetic creat de monitor este de asemenea un factor dăunător sănătății omului.
Influența câmpurilor electromagnetice de mare intensitate asupra omului constă în absorbția de către țesuturile corpului uman a energiei, însă influența principală îi revine câmpului electric. Nivelul de influență a câmpurilor electromagnetice asupra omului depinde de frecvență, de puterea emisiei, de durata acțiunii, de regimul de emisie (prin impulsuri sau continuu), și de asemenea de proprietățile individuale ale organismului. Influența câmpului electric de frecvență joasă provoacă dereglări în activitatea funcțională a sistemului cardio-vascular, și chiar la schimbări privind componența sângelui.
Influența câmpului electromagnetic de frecvență înaltă se reflectă sub forma efectului termic, care duce la ridicarea temperaturii corpului, la supraîncălzirea locală a țesuturilor corpului și a organelor cu o termoreglare slabă. Ca rezultat unii lucrători suferă din cauză insomniei, simt dureri în regiunea inimii, dureri de cap, ușor obosesc.
Pentru a micșora puterea de emisie a sursei câmpului electromagnetic pot fi utilizate următoarele mijloace tehnice:
utilizarea unui astfel de regim de lucrul, în care dispozitivul lucrează cu o putere mai mică decât cea proiectată;
lichidarea locurilor de emisie suplimentară;
micșorarea undelor reflectate prin ajustarea sarcinilor, etc.
Alegerea corectă a regimului de lucru a personalului și a utilajului permite micșorarea prezenței omului în zona de acțiune a câmpurilor electromagnetice.
Utilizarea sistemelor de dirijare la distanță cu utilajul permite personalului să-și îndeplinească funcțiile în afara zonei de acțiune a câmpurilor electromagnetice.
Procesul de ecranare, des utilizat cu scopul de micșora influența câmpurilor electromagnetice, utilizează fenomenul de absorbție și reflectare a energiei câmpului electromagnetic. Pentru confecționarea ecranului se utilizează materiale cu o conductibilitate electrică înaltă (aluminiu, cupru, oțel), și cu proprietăți de absorbție și reflectare sub formă de foi și plasă. Ecranele obligatoriu se unesc la pământ.
Eficacitatea acțiunii de ecranare a materialului se caracterizează prin adâncimea infiltrării câmpului electromagnetic în ecran, care depinde de materialul de confecționare.
Adâncimea infiltrării câmpului electromagnetic, la care acest câmp scade de 2,718 ori:
unde – permeabilitatea magnetică relativă a materialului ecranului, Hn/m;
– conductibilitatea relativă a materialului ecranului, cm/m;
f frecvența câmpului electromagnetic Hz.
Adâncimea infiltrării a frecvențelor înalte și supraînalte în ecran de obicei nu întrece un milimetru, astfel grosimea ecranului se alege din considerente constructive.
5.2 Calcularea protecției “legare la nul”
Legarea la nul este o măsură de protejare a omului de electrocutare prin deconectarea strictă și în viteză a rețelei în caz de apariție a tensiunii pe carcasă (străpungerea izolării). Deconectarea strictă se efectuează, dacă curentul de scurt circuit format prin fază și firul nul este destul de mare pentru ca declanșatorul să funcționeze corect.
Scopul calculării instalației “legarea la nul” – determinarea secțiunii firului nul, care satisface condiția funcționării protecției maximale de curent. Valoarea protecției se determină după puterea instalației electrice proiectate (exploatate).
Curentul de scurtcircuit trebuie să depășească valoarea protecției conform cerințelor (pentru siguranțe Is.c. ≥ 3 In, unde In – curentul nominal al siguranței). Modul de calculare este următorul:
Se calculă rezistența circuitului “faza – nul”:
;
unde: Rf – rezistența activă a firului fazic, Ohm;
Rn – rezistența activă a firului nul, Ohm;
Xc – rezistența inductivă a rețelei “faza – nul” și pentru rețelele cu tensiune joasă (până la 1000 V) și firele din cupru și aluminiu, deci Xc este foarte mică (Xc = 0).
Rezistențele active se calculă după formula:
; ;
unde Lf, Sf, Ln, Sn – lungimea și secțiunea firului fazic și nul corespunzător;
–rezistența electrică specifică: pentru cupru, Cu0.018 Ohm * (mm / m);
pentru aluminiu Al = 0.028 Ohm * (mm / m);
Deoarece materialul din care s-a confecționat cablul (firul) este cupru, lungimea firului de fază = 400 m, iar secțiunea firului = 16 mm vom obține următoarele calcule:
;
Pentru lungimea firului nul Ln = 400 m și secțiunea firului = 10 mm vom obține:
;
curentul de scurt-circuit calculat în A:
;
unde Zt – rezistența transformatorului.
Pentru tensiunea U = 380 V și Zt / 3 = 0.0354 Ohm (din tabel) obținem următoarele calcule:
Se compară Is.c. cu In: dacă Is.c. ≤ 3 In pentru siguranță atunci se aleg conductoare de o secțiune mai mare și calculul se repetă.
Deoarece In este egal cu 63 A obținem:
Rezultă că, curentul de scurtcircuit depășește valoarea cerințelor obiectului protecția muncii (pentru siguranțe) sînt respectate.
5.3 Securitatea antiincendiară
Incendiu se numește procesul necontrolat de ardere în afara unui loc de ardere special amenajat, ce aduce daune materiale.
În cadrul oricărei organizații, sau întreprinderi trebuie să existe mijloace de anunțare, de apel rapid la serviciile orășenești antiincendiare în cazul apariției incendiului. Pentru obiectele de o importanță majoră sau periculoase, este recomandată posibilitatea legăturii telefonice directe cu secția antiincendiară orășenească. Semnalizarea antiincendiară se execută cu ajutorul diferitor sisteme. Pentru a anunța despre incendiu se utilizează legătura telefonică, legătura radio, sirena, semnalizarea cu ajutorul clopotelor etc. Mijloacele de anunțare despre incendiu trebuie să fie disponibile toate 24 ore.
Semnalizarea incendiului se execută de diferite sisteme. Cel mai simplu și mai des utilizat este semnalizatorul manual, care se activează prin apăsarea butonului. Așa semnalizatoare se instalează pe scări, în paliere și sînt vopsite în culoarea roșie.
În timpul de față larg se utilizează semnalizatoarele automate, care conform principiului de lucru se împart în cele termice, de fum, combinate și optice.
Semnalizatoarele termice de acțiune maximă acționează la deformarea unei plăci bimetalice, la încălzirea ei până la 60, 80, 100 °C în dependență de reglaj.
În semnalizatoarele termice semiconductoare, în calitate de elemente sensibile sânt termorezistențele, din cauza cărora se schimbă curentul în rețea la încălzirea lor.
Termosemnalizatoarele diferențiale reacționează la ridicarea rapidă a temperaturii (la 30°C timp de 7 secunde), iar în calitate de element sensibil se folosește elementul la încălzirea căruia apare termo-FEM.
În semnalizatoarele de fum în calitate de element sensibil se utilizează camera de ionizare, în care sub acțiunea izotopului radioactiv (plutoniu-239) apare un curent de ionizare. Apariția fumului în cameră mărește consumul de raze ceea ce cauzează micșorarea curentului de ionizare.
În semnalizatoarele combinate se folosește interconectarea semnalizatorului de fum cu cel termic. La camera de ionizare se mai conectează în plus încă o termorezistență.
Semnalizatoarele combinate reacționează atât la apariția fumului, cât și la schimbarea temperaturii. Semnalizatoarele optice reacționează la razele ultraviolete ale spectrului flăcării, deoarece elementul sensibil reprezintă contoarele de fotoni. Semnalizatoarele de diferite tipuri pot controla suprafețe de la 15 până la 100 m2.
Semnalizatoarele de fum și cele combinate nu se instalează în încăperi umede și prăfuite, sau în încăperi în care se conțin vapori de acizi, baze, sau unde temperatura este mai mare decât 80 °C, deoarece în așa locuri poate avea loc acționarea falsă ale semnalizatoarelor.
5.3.1 Cauzele apariției incendiilor
Procesul de ardere este posibil în cazul când este prezentă substanța arzătoare, sursa de aprindere și oxidantul, care în cele mai dese cazuri este oxigenul, ce se conține în aer. La reducerea concentrației oxigenului din aer până la 12-14% arderea majorității substanțelor se oprește. Procesul de ardere este posibil și în lipsa oxigenului – deoarece hidrogenul, stibiul și unele metale ard în clor. Unele substanțe ( turba, cărbunele, funinginea, cârpele uleioase), numite piriforme pot să se autoinflameze la contactul cu aerul. Auto-aprinderea acestor substanțe are loc în urma proceselor chimice, termice sau microbiologice. Substanțele se încălzesc sub acțiunea căldurii ce vine din afară, ce se elimină în timpul reacțiilor chimice, și de asemenea în rezultatul acțiunii micro-organismelor.
În procesul de producție, incendiul poate apare în urma unor cauze de ordin electric sau ne electric. La cauzele de ordin ne electric se referă:
funcționarea proastă a instalațiilor de producție și dereglarea procesului tehnologic; comportarea iresponsabilă sau ne atentă cu focul (fumatul, lăsarea fără supraveghere a dispozitivelor de încălzire);
construcția incorectă sau dereglarea sistemului de ventilare;
autoinflamarea materialelor.
La cauzele de ordin electric se referă:
scurtcircuitul;
supraîncărcarea conductoarelor;
rezistența mare de trecere;
scânteierea;
electricitatea statică și descărcarea fulgerului;
arcul electric ce apare în timpul sudării electrice și în timpul operațiilor greșite cu aparatajul de comutare;
instabilitatea tensiunii electrice din rețea – ca rezultat se aprind unele circuite integrate din calculator, sau monitor, etc.
5.3.2 Mijloacele de stingere a incendiilor
Cel mai răspândit mijloc de stingere a incendiilor este apa, ce posedă o capacitate termică enormă și o temperatură mare de vaporizare, ceea ce permite de a lua căldura din focarul incendiului. În același timp apa nu poate fi folosită pentru stingerea soluțiilor ușor inflamabile (benzina, gaz lampant, ulei mineral), deoarece din cauza greutății relative mari, ea se adună sub aceste soluții și împrăștiindu-se ușor și rapid măresc considerabil suprafața de ardere. De asemenea, se interzice stingerea cu apa a substanțelor ce elimină reagenți inflamabili (carbid de calciu, silitra) la contactarea lor cu apa.
Pentru stingerea instalațiilor electrice sub tensiune, apa nu poate fi folosită fără măsuri speciale de protecție a oamenilor de la atingerea curentului electric prin getul de apa. În clădiri, în locuri special rezervate, se instalează scuturi antiincendiare, ce conțin unele rechizite necesare pentru stingerea focului: robinet de presiune, țeava elastică, în unele locuri nisip, găleți, topoare și alte instrumente de distrugere a pereților.
O mare răspândire au căpătat mijloacele automate de detectare și stingere a incendiului. Principiul de funcționare a acestora, în majoritatea cazurilor, se bazează pe prezența unor țevi în interiorul cărora se află apă sub presiune, și niște dopuri din materiale ce se topesc ușor, introduse în aceste țevi. La ridicarea temperaturii în încăpere, dopurile se topesc și apa din țevi sub acțiunea presiunii stropește focul.
O modalitate efectivă în prevenirea incendiilor, minimizarea daunelor și reducerea jertfelor omenești este familiarizarea muncitorilor, copiilor și a populației în întregime cu regulile de comportare în situații de incendiu, modalitățile de stingere a focului, normele elementare de prevenire a incendiului.
5.3.3 Securitatea antiincendiară în sălile de calcul
Pentru a analiza nivelul securității incendiare a locurilor de muncă, a zonelor de producție, a sălilor de calcul se folosește următoarea clasificare :
1.Clasificarea materialelor de construcție și construcțiilor după nivelul de inflamabilitate:
ne inflamabile;
greu inflamabile;
inflamabile;
2. Clasificarea construcțiilor după nivelul rezistență la incendiu (limita nivelului de rezistența la incendiu – timpul în ore din momentul începerii incendiului până la momentul apariției crăpăturilor).
3. Clasificarea încăperilor după RCIE ("Regulile de Construcție a Instalațiilor Electrice"):
cu pericol de explozie;
cu pericol de inflamare.
Criteriile de apreciere:
Conținutul de substanțe inflamabile;
Regimul termic de prelucrare.
4. Clasificarea proceselor de producție după pericolul incendiar:
cu pericol de explozie;
cu pericol de explozie și inflamare;
cu pericol de inflamare;
fără pericol de inflamare;
Conform primei clasificări (clasificarea materialelor de construcție și construcțiilor după nivelul de inflamabilitate) sala de calcul este ne inflamabilă deoarece sînt prevăzute multe măsuri de prevenire a incendiului cum ar fi: sisteme de semnalizare, podele din metal, mese metalice, pereții în sala de calcul se acoperă cu substanțe ne arzătoare.
După clasificarea a doua (clasificarea construcțiilor după nivelul rezistență la incendiu), de obicei sălile de calcul se află în clădiri construite sau din beton armat sau coteleț (pentru instituțiile de învățământ). Ambele materiale de construcție au o rezistență la incendiu mare – pereții în sala de calcul se acoperă cu substanțe ne arzătoare.
După clasificarea a treia (după Regulile de Construcție a Instalațiilor Electrice), luând în considerație conținutul mic de substanțe inflamabile și regimul termic de prelucrare, sălile de calcul pot fi caracterizate – cu pericol mic de inflamare.
Sălile de calcul după pericolul incendiar a proceselor de producție se referă la categoria celor cu pericol de inflamare ceea ce se explică prin faptul, că în încăpere se găsesc substanțe inflamabile: de obicei, aceste săli sînt echipate cu utilaj care conține masă plastică, care totuși arde. Trebuie însă de menționat, în ultimul timp masa plastică utilizată la fabricarea tehnicii de calcul are o astfel de componență chimică, care nu arde sau care se autostinge după primele secunde de ardere. În sala de calcul de obicei lipsesc așa atribute cum ar fi : covoare, obiecte din lemn, dulapuri cu cărți, etc. Reiese că, cu toate că pericolul de inflamare există, el este foarte mic.
Securitatea antiincendiară poate fi asigurată prin măsuri de profilaxie antiincendiară și prin respectarea regulilor de prevenire a incendiului. Noțiunea de profilaxie antiincendiară include un complex întreg de măsuri, necesare pentru preîntâmpinarea apariției incendiului sau reducerea urmărilor lui.
5.3.4 Măsurile profilactice de luptă cu cauzele incendiului în sălile de calcul
Măsurile de eliminare a cauzelor incendiilor și exploziilor se divizează în:
măsuri tehnice;
măsuri de exploatare;
măsuri organizatorice;
măsuri de regim.
La măsurile tehnice se referă – respectarea normelor antiincendiare la construcția clădirilor, sistemului de încălzire, sistemului de ventilare, la alegerea și montarea echipamentului electric, sistemele paratrăsnet.
La măsurile de exploatare se referă – exploatarea corectă a utilajului de producere, instalațiilor de compresie, cuptoarelor și a altor dispozitive de forță și a utilajului electric; menținerea corectă a încăperilor, a clădirilor și a teritoriului întreprinderii.
La măsurile organizatorice se referă – studierea regulilor antiincendiare de către personalul întreprinderii, sau organizației, editarea instrucțiunilor și placatelor necesare.
La măsurile de regim se referă – interzicerea sau impunerea unor restricții de utilizare a focului deschis, fumatului, a lucrărilor de sudare în anumite locuri.
La proiectarea și construcția clădirilor și încăperilor, (în particular a sălii de calcul), de asemenea trebuie să se respecte măsurile antiincendiare:
protecția construcțiilor de lemn (dacă sînt) se realizează prin îmbibarea cu substanțe
chimice ne inflamabile (antipirene), acoperirea cu vopsele refractare;
pentru limitarea extinderii incendiului se fac obstacole antiincendiare: pereți, bariere, uși, porți, ferestre. Toate acestea trebuie îndeplinite din materiale ne arzătoare.
Măsurile active de luptă cu incendiile în sălile de calcul:
izolarea locului de ardere de aer cu ajutorul substanțelor solide (nisip, pături, etc.);
răcirea focarului până la unele temperaturi stabilite, care se face cu ajutorul apei, însă apa are restricții la stingerea substanțelor inflamabile, instalațiilor electrice, etc., de aceea mai des se folosește bioxidul de carbon, care în reacție cu aerul micșorează temperatura până la -78 C;
reducerea vitezei petrecerii reacției chimice în flacără – în acest scop se folosesc prafurile;
distrugerea mecanică a flăcării în rezultatul acționării asupra ei a unui get puternic de gaz sau apa.
Pentru stingerea focului în sălile de calcul se utilizează extinctoarele cu CO2 și praf, care posedă o viteză mare de stingere, timp îndelungat de acțiune, posibilitate de stingere a instalațiilor electrice, eficacitate înaltă de luptă cu focul.
Reieșind din normele securității antiincendiare, pentru o sală de calcul cu suprafața de 100 m˛ sînt necesare următoarele mijloace primare de stingere a incendiului:
un extinctor de CO2 de tip OU-5 sau OU-8, cu ajutorul căruia se poate stinge flacăra de pe diferite materiale și instalații electrice (până la 1000 V);
un extinctor de spumă chimică (OHP-10) sau un extinctor de spumă (OVP-5 sau OVP-10) pentru stingerea materialelor solide și lichidele inflamabile (în afara de instalațiile sub tensiune);
pâslă sau asbest (1X1; 2X1,5; 2X2 m).
Sălile de calcul trebuie să fie echipate cu semnalizatoare incendiare – pentru semnalizarea apariției incendiului. În calitate de semnalizatoare incendiare pentru sălile de calcul se utilizează semnalizatoarele de fum fotoelectrice de tip IDF-1 sau DIP-1.
În dependență de înălțimea podului (3 m) și aria podelei (40 m.), după norme este suficientă prezența a trei semnalizatoare pentru toată încăperea. Aceste dispozitive se caracterizează printr-o viteză mare, sensibilitate înaltă și care funcționează după principiul difuziunii căldurii de către particulele de fum.
Avantajul acestor semnalizatoare constă în lipsa inerției, controlul unei suprafețe mari. Neajunsul lor este posibilitatea acționării false și costul ridicat.
Toate sistemele, care utilizează curent electric – dispozitivele de repartizare, aparatele de măsură, sistemele de siguranță și alte aparate electrice trebuie să fie montate pe suporturi care nu ard (marmor, textolit, asbest, etc.).
Măsurarea rezistenței izolației circuitului electric trebuie să se execute în fiecare an în încăperile cu mediul normal, iar în încăperile cu umiditate înaltă, cu exces de gaze și aburi – nu mai rar de 2 ori pe an.
Suportul metalic, carcasele echipamentelor electrice și electronice, de asemenea țevile metalice, prin care trece sârmele electrice, trebuie să fie conectate la pământ.
În gospodăria obiectelor electrice deseori se utilizează acumulatoarele, încărcarea cărora se însoțește de emisia gazelor și aburilor explozive și periculoase pentru sănătatea omului. Din aceste motive acumulatoarele trebuie instalate în încăperi aparte, bine izolate de celelalte, cu o ventilare corespunzătoare.
Aceste măsuri sînt mai mult valabile pentru acumulatoarele produse până în anul 1990.
Astăzi acumulatoarele, care se utilizează la alimentarea calculatoarelor, sînt proiectate și fabricate după alte tehnologii mai avansate, și încărcarea lor nu se mai însoțește de emisia gazelor și aburilor explozive și periculoase.
În caz de incendiu trebuie să fie prevăzută posibilitatea evacuării rapide a oamenilor. Căile de evacuare trebuie să asigure evacuarea tuturor oamenilor, care se află în încăperile întreprinderii într-un timp foarte scurt.
Numărul ieșirilor de evacuare din încăperi și de la fiecare etaj trebuie să se stabilească în corespundere cu ГОСТ 2.09.02-85, și să fie nu mai puțin de două ieșiri.
CONCLUZII
Dezvoltarea tehnologiilor informaționale se reflectă în diferite domenii și nu în ultimul rând în domeniul administrării de stat. Folosirea tehnologiilor avansate în domeniul programării distribuite face ca lucrul să fie mult mai efectiv și econom.
În această lucrare am descris cîteva tehnologii și limbaje de programare distribuite care serversc pentru procesarea efectivă a datelor.
A fost proiectată structura rețelei distribuite pentru realizarea funcției de paralelizare a procesului de recunoaștere a imaginilor, a fost elaborat modelul rețelei proiectate și au fost făcute investigații asupra modelului elaborat pentru valori diferite a vitezei de transfer a datelor în rețea, în rezultatul cărora s-a calculat numărul optim de module de recunoaștere pentru paralelizarea procesului de recunoaștere.
Este modelată funcționarea rețelei proiectate cu utilizarea limbajului de programare Perl în scopul de a obține configurația optimă a rețelei pentru utilizarea cât mai eficientă a resurselor folosite. Cu ajutorul bibliotecilor procesării distribuite s-a mărit productivitatea utilizării resurselor serverelor și s-a ajuns la mărirea semnificativă a vitezei de prelucrare a datelor.
Am analizat posibilitatea de a adăuga mai multe servere pentru a mări productivitatea sistemului în cazul când există o suprasolicitare de cereri de identificare, dar care nu pot fi prelucrate în timp real, sau când baza de date conține un număr mare de înregistrări.
Un mare avantaj al acestui program este că faptul că este independent de platformă și poate fi rulat atât sub sistemele de operare Unix cât și Windows. În cazul utilizării sistemelor de operare Unix softul adițional folosit (server Web, interpretatorul limbajului Perl, MySQL) este absolut gratuit în baza proiectului Open Source. Aceasta reduce costul întregului proiect de recunoaștere și în special în cazul când programul este distribuit pe rețele.
În procesul de lucru am calculat sinecostul programului, unde am luat pentru soft prețul pentru versiuni licențiate, din care cauză prețul e mare, dar pentru platforma Unix acest soft e gratis, respectiv și sinecostul e mult mai mic.
În cadrul lucrării am apreciat nivelul pericolului la monitor, am analizat cauzele aparițiilor incendiilor, mijloace de stingere a lor, securitatea antiincendiară în sălile de calcul.
Această lucrare este un proiect bazat pe analiză și modelare, pentru a implementa acest proiect e necesar de finisat programul utilizând una din tehnologiile de programare distribuită.
BIBLIOGRAFIE
Sisteme cu prelucrare distribuită și aplicațiile lor; Florin Călinescu, Dănuț P. Golesteanu; Editura Tehnică, 1992.
Wall D. – Limits of Instruction Level Paralelism, ASPLOS Conf., 1991.
Vințan L. – Metode de evaluare și optimizare în arhitecturile paralele de tip ILP, Editura Universității Lucian Blaga din Sibiu, ISBN 973-9280-67-6, 1997.
Message Passing Interface Forum. MPI: A message-passing interface standard. International Journal of Supercomputer Applications, 8(3/4), 1994. Special issue on MPI.
Andrew S. Tanenbaum, Distributed Operating Systems, Prentice Hall, 1995.
Vassiliadis S., Phillips J., Blaner B. – Interlock Collapsing ALUs, IEEE Trans. Computers, No. 7, 1993.
Vințan L. – Metode de evaluare și optimizare în arhitecturile paralele de tip ILP, Editura Universității Lucian Blaga din Sibiu, ISBN 973-9280-67-6, 1997.
Vințan L., Steven G. – Static Data Dependence Collapsing in a High Performance Superscalar.
Franklin M., Sohi G. – The expandable Split Window Paradigm for Exploiting Fine Grain Parallelism, Proceedings 19th Ann. Int. Conf. On Comp. Archit., New Zork, 1992.
Huang A. – Speculative Disambiguation: A Compilation Technique for Dynamic Memory Hwu W. – The Superblock: An Effective Technique for VLIW and Superscalar Compilation, Journal of Supercomputing, Vol.7, 1995.
Lam M., Wilson R. – Limits of Control Flow on Parallelism, Proc. 19th Ann. Int. Conf. On Comp. Archit., New York, 1992.
M. Van Steen, P. Homburg, L. Van Doorn, A.S. Tanenbaum, and W de Jonge „Towards Object-based Wide Area Distributed Systems, august 1995”.
K.Mandi, Carl Kesselman, „Compositional C++: Compositional Parallel Programing”.
Carriero, David Gelenter, „Linda in Context”, Communication of distributed systems”, IEEE Transactions on Software Endineering, March 1992.
Saniya Ben Hassen, Irina Athanasiu, Henri Bal, „A Flexible Operation Execution model for Shared Distributed Objects”.
Andonie, R., Garbacea, I. Algoritmi fundamentali: o perspectivă C++, Editura Libris, Cluj-Napoca, 1995.
[Vinoski97] S.Vinoski, CORBA: Integrating diverse applications within distributed heterogeneous environments, in IEEE Communications, vol. 14, no. 2, Feb. 1997, http://www.iona.com/hvplan/vinoski/iccc.ps.Z.
[Frey97] Anthony Frey, Network Computing Into Orbi., http://techweb.cmp.com/nc/804/804n.html.
[Brando95] Thomas J. Brando, Comparing DCE and CORBA, MITRE Document MP 95B-93, March 1995. http://www.mitre.org/research/domis/reports/DCEvCORBA.html .
[ DCOM | P.E.Chung, Y.Huang, S.Yajnik, D.Liang, J.Shih, C-Y Wang. Yi-Mm Wang:.DCOM and CORBA Side by Side, Step by Step and Layer by Layer.
ANEXE
Anexa 1. Listingul programului random.pl
#!/usr/bin/perl
use LWP::Simple;
srand;
$r=int rand 9999;
$user="$r$^T";
$formula=$ENV{QUERY_STRING};
@SERVERS=(
'xxx.xxx.xxx.xxx',
'xxx.xxx.xxx.xxx',
'xxx.xxx.xxx.xxx'
);
$N=@SERVERS;
foreach $s(@SERVERS)
{
$r=get("$s?$formula&$user");
}
$flag=1;
while ($flag==1)
{
$v=-s "process/c$user";
if ($v>=$N) {$flag=0;}
}
open FILE,"process/$user";
$result=<FILE>;
close FILE;
`rm process/$user`;
`rm process/c$user`;
print $result;
Anexa 2.Listingul programului exe.pl
#!/usr/bin/perl
use DBI;
use LWP::Simple;
$linim_A=100;
$limit_B=200;
$in=$ENV{QUERY_STRING};
$in=~/(.+?)&(.+?)/;
$formula=$1;
$user=$2;
$REZULT=0;
for ($this=$limit_A;$this<=$limit_B;$this++)
{
$cond=" WHERE id=$this";
$sth=$dbh->prepare(q{select formula from base }.$cond);
$sth->execute;
$rv=$sth->bind_columns(\$_formula);
if ($sth->fetch())
{
############
processing formula
result to $REZULT
############
}
$r=get("mainserver/cgi-bin/back.cgi?$r&$user")
}
Anexa 3.Listingul programului rezult.pl
#!/usr/bin/perl
$in=$ENV{QUERY_STRING};
$in=~/(.+?)&(.+?)/;
$result=$1;
$user=$2;
open FILE,">>process/$user";
print FILE "result\n";
close FILE;
open FILE,">>process/c$user";
print FILE "*";
close FILE;
Anexa 4.Schema-bloc a programului
I II III
start start start
inițializarea procesarea procesarea datelor
procesului ID datelor de intrare de intrare
se inițializează cererea SQL înscrierea
datele de intrare pentru BD rezultatelor
executarea procesului primirea
de paralelizare rezultatelor finish
așteptarea
rezultatelor finish
printarea
rezultatelor
finish
Anexa 5.Graful rețea
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Retea de Prelucrarea Distribuita a Imaginilor (ID: 161084)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
