This shows you the differences between two versions of the page.
apd:laboratoare:10 [2021/12/27 14:29] florin.mihalache [Verificarea topologiei] |
apd:laboratoare:10 [2023/10/08 16:33] (current) dorinel.filip Move |
||
---|---|---|---|
Line 1: | Line 1: | ||
===== Laboratorul 10 - Stabilirea topologiei și alegerea liderului ===== | ===== Laboratorul 10 - Stabilirea topologiei și alegerea liderului ===== | ||
- | + | Documentația de laborator s-a mutat la [[https://mobylab.docs.crescdi.pub.ro/docs/parallelAndDistributed/introduction|această adresă]]. | |
- | În acest laborator vom explora utilizarea MPI în cadrul unei topologii de noduri. Vom învăța să stabilim topologia unei rețele de noduri (folosind algoritmul sondă-ecou / undă-ecou și algoritmul arbore), să alegem un lider (folosind heart-beat) și să determinăm numărul de noduri din topologie folosind un algoritm epidemic. | + | |
- | ==== Organizarea unui cluster ==== | + | |
- | + | ||
- | În cazul unui sistem distribuit, elementul cheie este **comunicarea** între procese. Aceasta dictează performanța sistemului, toleranța la defecte și logica fluxului de transfer de informații între nodurile din cadrul sistemului distribuit. | + | |
- | + | ||
- | Din punct de vedere al arhitecturii, nodurile pot fi organizate în mai multe moduri într-un cluster: | + | |
- | * **grid** -> nodurile sunt organizate pe nivele. Fiecare nod poate comunică cu vecinii pe orizontală și pe verticală. Fluxul informației este vertical și orizontal. Fiecare nod are maxim 4 vecini. | + | |
- | * **inel** -> nodurile sunt organizate în cerc. Fiecare nod vorbește cu vecinii din stânga și din dreapta. Fluxul informației este orizontal. Fiecare nod are doi vecini. | + | |
- | * **arbore** -> nodurile sunt organizate ierarhic, sub forma de arbore. Fluxul informației este vertical. Fiecare nod poate avea un număr nelimitat de vecini. | + | |
- | * **graf** -> nodurile sunt organizate sub forma unui graf. Fiecare nod poate comunica cu unul sau mai mulți vecini. Fluxul informației este abstract. Fiecare nod poate avea un număr nelimitat de vecini. | + | |
- | + | ||
- | În cadrul acestui laborator vom explora organizarea unui sistem sub forma de graf generic. Topologia de mai jos va fi folosită pentru exemplificări în cadrul laboratorului și în cadrul exercițiilor. | + | |
- | + | ||
- | {{ :apd:laboratoare:graph.png?600 |}} | + | |
- | ==== Stabilirea unei topologii ==== | + | |
- | + | ||
- | Există trei moduri prin care o topologie poate fi stabilită în cadrul unui cluster. Nodurile pot cunoaște starea întregului cluster de la bun început, pot cunoaște doar vecinii sau nu pot ști nimic despre starea sistemului. | + | |
- | + | ||
- | Pentru a stabili topologia, clusterul poate opera în două moduri: | + | |
- | * nodurile pot transmite starea lor celorlalte moduri de mai multe ori până când toate nodurile au topologia stabilită. Numărul de dați necesar asigurării topologiei între noduri se numește **convergență**. Acest mod este simplu de realizat, dar ineficient | + | |
- | * nodurile aleg un **lider** care să calculeze topologia sistemului | + | |
- | + | ||
- | Problema care se ridică în cazul utilizării unui lider care să creeze matricea de topologie, este ca nodurile //nu știu// calea către lider, ci doar cine este acest lider. **Arborele de acoperire** rezolvă această problemă. Pe baza arborelui de acoperire, nodurile trimit informația pe care o dețin către lider, trecând prin nodurile intermediare care sunt reprezentate de părinții lor în arbore. Nodurile intermediare adăugă informația primită la informația proprie și o trimit mai departe. În final, liderul are toată informația sistemului și poate crea matricea de topologie. Matricea este trimisă, apoi, fiecărui nod în parte. | + | |
- | + | ||
- | În cadrul acestui laborator vom explora stabilirea topologiei prin alegerea liderului. | + | |
- | + | ||
- | <note tip>În cazul rețelelor de calculatoare, router-ele și switch-urile sunt organizate sub forma unui cluster unde nodurile nu știu nimic despre starea sistemului la început.</note> | + | |
- | + | ||
- | <note important>În cazul alegerii liderului, nu este nevoie să se cunoască topologia la început, ci doar vecinii cu care nodurile pot interacționa.</note> | + | |
- | + | ||
- | ==== Algoritmi undă ==== | + | |
- | Un algoritm undă este un tip de algoritm distribuit folosit pentru propagarea informațiilor în cadrul unei rețele distribuite de noduri. | + | |
- | + | ||
- | Un algoritm undă este caracterizat de următoarele trăsături: | + | |
- | * există un proces inițiator (sau mai multe), care declanșează trimiterea de mesaje în cadrul rețelei | + | |
- | * fiecare proces trimite informații către vecinii săi, cu excepția părintelui, de la care a primit informația pe care o pasează mai departe | + | |
- | * fiecare proces primește informații de la vecini (cu excepția părintelui) și o trimite părintelui | + | |
- | * la final se ia o decizie în legătură cu informațiile primite | + | |
- | + | ||
- | ==== Alegerea liderului ==== | + | |
- | + | ||
- | Clusterele de noduri pot sa fie ierarhizate sau nu. În cadrul clusterelor bazate pe noduri autonome, nu există un lider bine stabilit, ci contracte clare de comunicare între noduri. Pe de altă parte, în clusterele care au lider, unul sau mai multe noduri îndeplinesc funcții elevate. Printre funcțiile elevate se numără și //stabilirea și distribuirea topologiei// către celelalte noduri. | + | |
- | + | ||
- | Liderul reprezinta un nod sau un grup de noduri ales pe baza unei euristici. Euristica poate ține cont de resursele nodului respectiv, de numărul sau de natura proceselor care rulează pe el sau pur și simplu de lucruri simple, precum //identificatorul său//. | + | |
- | + | ||
- | În cadrul acestui laborator vom explora alegerea liderului bazat pe rangul cel mai mare al unui nod. Alegerea liderului se va face pe baza unui algoritm de tipul **heartbeat** (algoritmul pulsațiilor). | + | |
- | + | ||
- | === Alegerea liderului. Heartbeat === | + | |
- | + | ||
- | Funcționarea unui algoritm **heartbeat** se aseamănă cu bătăile inimii: | + | |
- | - **sistola** -> partea de "expandare". Informația este transmisă către nodurile vecine. | + | |
- | - **diastola** -> partea de "contracție". Informația este receptată înapoi de la nodurile vecine. | + | |
- | + | ||
- | În cadrul alegerii liderului, algoritmul heartbeat va fi aplicat în felul următor: | + | |
- | - nodurile vor trimite rangul lor către vecini | + | |
- | - fiecare nod va calcula //liderul local// în funcție de maximul dintre rangul propriu și informația primită de la vecin | + | |
- | - vecinii vor trimite înapoi liderul lor local către nodurile de la care au primit mesaj | + | |
- | - nodurile care au trimis mesajul inițial își vor actualiza valoarea liderului local | + | |
- | + | ||
- | Algoritmul se repetă de un număr suficient de ori ca să se asigure convergența informației. | + | |
- | + | ||
- | Pseudocod: | + | |
- | <code> | + | |
- | lider = rang; // la început, fiecare nod se consideră lider | + | |
- | + | ||
- | for (pas = 0; pas < convergență; pas++) { | + | |
- | for (i = 0 to nr_vecini) { | + | |
- | trimite lider către vecin[i] | + | |
- | primește lider_vecin de la oricare vecin | + | |
- | lider = max(lider_vecin, lider); | + | |
- | } | + | |
- | } | + | |
- | </code> | + | |
- | + | ||
- | <note tip>Un exemplu de rulare a acestui algoritm poate fi observat {{:apd:laboratoare:alegerea_liderului_folosind_heartbeat.pdf|aici}}</note> | + | |
- | + | ||
- | ==== Construirea arborelui de acoperire ==== | + | |
- | + | ||
- | După ce liderul a fost ales, acesta va **iniția construirea arborelui de acoperire**. | + | |
- | + | ||
- | <note tip>Scopul arborelui de acoperire este ca fiecare nod să știe, în orice moment de timp, cum să ajungă către lider.</note> | + | |
- | + | ||
- | Arborele de acoperire se reprezintă, cel mai ușor, printr-un //array de părinți//. Construirea acestui arbore se realizeaza printr-un algoritm de tip **undă - ecou**. | + | |
- | + | ||
- | === Construirea arborelui de acoperire. Undă - ecou === | + | |
- | + | ||
- | Algoritmul undă are două părți: | + | |
- | + | ||
- | - **unda** -> toate nodurile, cu excepția liderului, așteaptă să primească un mesaj. Liderul inițiază unda. La primirea **primei sonde**, fiecare nod își notează părintele și trimite un mesaj tuturor vecinilor, mai puțin celui de la care a primit (părintele său) | + | |
- | - **ecou** -> se așteaptă primirea unui mesaj de la toți vecinii, //mai puțin de la părinte//. Informațiile primite de la vecini sunt agregate într-un array de părinți și acesta este trimis către părinte. | + | |
- | + | ||
- | La final, liderul va deține array-ul de părinți final, care reprezintă arborele de acoperire. Arborele de acoperire este apoi distribuit întregului sistem. | + | |
- | + | ||
- | Pseudocod: | + | |
- | <code> | + | |
- | for (i = 0; i < nr_vecini; i++) { | + | |
- | // vedem dacă vecinul curent nu este părintele nodului, căci primim date de la părinte pe care le trimitem celorlalți vecini | + | |
- | if (vecin[i] != parinte[rank]) { | + | |
- | trimite array-ul de părinți (parinte[]) către vecin[i] // sondă sau undă | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | for (i = 0; i < nr_vecini; i++) { | + | |
- | // vedem dacă vecinul curent nu este părintele nodului | + | |
- | if (vecin[i] != parinte[rank]) { | + | |
- | primește array-ul de părinți (parinteRecv[]) de la vecin[i] // ecou | + | |
- | for (j = 0; j < nr_procese; j++) { | + | |
- | // dacă nodul j are părinte (parinte[j] == -1 => nodul j nu are părinte) | + | |
- | // se completează array-ul de părinți (bottom - top, de la frunze până în rădăcină) | + | |
- | if (parinteRecv[j] != -1) { | + | |
- | parinte[j] = parinteRecv[j]; | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | // topologia e stabilită (adică nodul curent are topologia formată de nodurile copii pana la nivelul curent) | + | |
- | if (rank != lider) { | + | |
- | // fiecare proces care nu e lider trimite topologia curentă către părintele său, care o va completa | + | |
- | trimite array de părinți (parinti[]) catre parinte[rank] // unda / sonda | + | |
- | // părintele, după ce a completat topologia, o trimite înapoi către nodul copil | + | |
- | primește array de părinți (parinti[]) de la parinte[rank] // ecou | + | |
- | } | + | |
- | + | ||
- | // acum topologia este completă | + | |
- | for (i = 0; i < nr_proc; i++) { | + | |
- | // procesul curent va trimite copiilor săi topologia completată | + | |
- | if (parinte[i] == rank) { | + | |
- | trimite array de părinți (parinti[] către nodul i | + | |
- | } | + | |
- | } | + | |
- | </code> | + | |
- | + | ||
- | <note tip>Un exemplu de rulare a acestui algoritm poate fi observat {{:apd:laboratoare:algoritmul_unda_ecou_sonda_ecou_-_arborele_de_acoperire.pdf| aici}}</note> | + | |
- | ==== Verificarea topologiei ==== | + | |
- | + | ||
- | După ce liderul a fost ales și topologia a fost distribuită către toate nodurile, este util ca informația să fie validată. Validarea poate implica procese foarte complexe, însă pentru acest laborator vom folosi o validare bazată pe numărul de noduri prezente în cluster. | + | |
- | + | ||
- | Calcularea numărului de noduri se poate realiza folosind un algoritm de tipul **epidemic**. | + | |
- | + | ||
- | + | ||
- | === Calcularea numărului de noduri folosind algoritm epidemic === | + | |
- | + | ||
- | Funcționalitatea unui algoritm de tipul **epidemic** se aseamănă cu răspândirea unei boli în care există un pacient 0: | + | |
- | - "pacientul 0" transmite informația vecinilor săi | + | |
- | - vecinii pacientului 0 devin "infectați" și transmit și ei, mai departe, informația către vecinii lor | + | |
- | + | ||
- | Pentru calcularea numărului de noduri, pacientul 0 va fi nodul lider. Acesta va deține o valoare de început, egală cu **1**. Toate celelalte noduri dețin valoarea **0**. Nodul lider va realiza media aritmetică dintre valoarea sa și valoarea vecinilor săi. Informația va fi sincronizată în ambele părți. Celelalte noduri vor executa aceeași operație cu vecinii lor. | + | |
- | + | ||
- | Algoritmul se repetă până când se atinge convergența soluției. La final, toate nodurile vor deține o aceeași valoare subunitară. Împărțirea lui 1 la această valoare va rezulta în numărul de noduri al clusterului. | + | |
- | + | ||
- | Pseudocod: | + | |
- | <code> | + | |
- | val = 0 | + | |
- | if (rank == leader) | + | |
- | val = 1 | + | |
- | else | + | |
- | val = 0 | + | |
- | + | ||
- | for (pas = 0; pas < convergență; pas++) { | + | |
- | for (i = 0 to nr_vecini) { | + | |
- | trimite val către procesul vecin[i] | + | |
- | primește recv_val de la vecin[i] | + | |
- | val = (val + recv_val) / 2; | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | return (1 / val); // numărul de noduri din rețea | + | |
- | </code> | + | |
- | + | ||
- | <note tip>Un exemplu de rulare a acestui algoritm poate fi observat {{:apd:laboratoare:numararea_nodurilor_din_topologie_folosind_epidemic.pdf|aici}}</note> | + | |
- | + | ||
- | ==== Construirea matricei de topologie folosind algoritmul arbore ==== | + | |
- | Algoritmul arbore reprezintă un algoritm undă, folosit pentru topologii de tip arbore sau pentru o **topologie de tip graf pentru care avem un arbore de acoperire**, unde avem ca **noduri inițiatori nodurile de tip frunză din topologie**. În cadrul acestui algoritm, nodurile transmit mesaje părinților lor, acestea fiind transmise mai departe prin aceeași cale până la rădăcina topologiei (rădăcina arborelui), care la final va lua o decizie ce va fi distribuită în toată rețeaua de noduri. | + | |
- | + | ||
- | Putem să construim matricea întregii topologii folosind algoritmul arbore, mai precis aplicând acest algoritm pe **arborele de acoperire al rețelei graf de noduri**. La început, fiecare nod are matricea sa de topologie, unde, inițial, vor apărea doar vecinii nodului respectiv. | + | |
- | + | ||
- | Pașii sunt următorii: | + | |
- | * fiecare nod, cu excepția liderului, care este nodul rădăcină în cadrul arborelui de acoperire, va trimite topologia sa către nodul părinte, care va completa topologia sa cu topologiile primite de la nodurile copil | + | |
- | * liderul va avea topologia completă a rețelei de noduri și o va răspândi în întreaga rețea de noduri. Mai precis, fiecare nod, care nu este frunză, va trimite topologia completată către nodurile copil. | + | |
- | + | ||
- | Pseudocod: | + | |
- | <code> | + | |
- | // se primesc informații de la toți copiii nodului curent și se actualizează matricea de topologie | + | |
- | for (i = 0 to nr_proc) { | + | |
- | // pentru copiii nodului curent | + | |
- | if (rank == parents[i]) { | + | |
- | for (j = 0 to nr_proc) { | + | |
- | // se primește, linie cu linie, topologia locală nodului i | + | |
- | se primeste recvTop[j] de la nodul i | + | |
- | for (k = 0 to nr_proc) { | + | |
- | if (top[j][k] == 0) { | + | |
- | // actualizăm matricea de topologie | + | |
- | top[j][k] = recvTop[j][k]; | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | // nodul curent trimite matricea de topologie proprie către părinte, rând cu rând | + | |
- | for (i = 0 to nr_proc) { | + | |
- | // dacă nodul curent are părinte | + | |
- | if (parents[rank] != -1) { | + | |
- | se trimite top[i] către parents[rank] | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | // dacă nodul curent nu e lider, primește topologia, rând cu rând, de la părinte | + | |
- | if (rank != leader) { | + | |
- | // nodul lider nu are părinte | + | |
- | for (i = 0 to nr_proc) { | + | |
- | se primește top[i] de la parents[rank] | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | // se trimite topologia completă către nodurile-copii, linie cu linie | + | |
- | for (i = 0 to nr_vecini) { | + | |
- | if (vecin[i] != parents[rank]) { | + | |
- | for (j = 0 to nr_proc) { | + | |
- | trimite top[j] către vecin[i] | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | </code> | + | |
- | ==== Exerciții ==== | + | |
- | + | ||
- | Pornind de la [[https://github.com/APD-UPB/APD/tree/master/laboratoare/lab10|scheletul de laborator]], va trebui să realizați următoarele sarcini: | + | |
- | - Aflați nodul lider al clusterului folosind un algoritm //heartbeat// | + | |
- | - Realizați arborele de acoperire, plecând din lider, folosind un algoritm //undă-ecou// | + | |
- | - Asigurați-vă ca numărul de elemente din arborele de acoperire a fost stabilit bine prin calcularea numărului de noduri folosind un algoritm //epidemic// | + | |
- | - Folosind arborele de acoperire, trimiteți către lider configurația fiecărui nod și realizați în lider matricea de topologie a clusterului. Distribuiți topologia către toate nodurile | + |