You are on page 1of 12

Cauzalitate şi timp

În sistemele distribuite asincrone nu se dispune de o modalitate de măsurare a timpului real. Pentru a cunoaşte ordinea relativă în care au loc evenimentele se studiază relaţiile de
cauzalitate dintre ele.
Vom considera în continuare sisteme distribuite asincrone de tip MP. Evenimentele vor fi numai de calcul (dacă nu se specifică altceva).

Definiţie: Fie α o execuţie fixată a sistemului şi ϕ 1, ϕ 2 două evenimente ale sale. Spunem că ϕ 1 se întâmplă înaintea lui ϕ 2 (happens before) şi notăm
α
ϕ 1 ⇒ ϕ 2 , dacă are loc una din condiţiile:
1.ϕ 1 şi ϕ 2 sunt evenimente ale aceluiaşi procesor şi ϕ 1 apare în α înaintea lui ϕ 2.
2.ϕ 1 trimite un mesaj m de la procesorul pi la procesorul pj, iar ϕ 2 este evenimentul de primire al mesajului m de la pi (ϕ 2 este primul eveniment de calcul al lui pj care apare
în α după livrarea lui m).
α
3.∃ ϕ un eveniment a.î. ϕ 1 ⇒ ϕ şi perechea ϕ , ϕ 2 satisface condiţia 1 sau 2 (cu ϕ în locul lui ϕ 1).
α
Observatie: ⇒ este o ordine parţială ireflexivă.

Definiţie: Dacă α =exec(C, σ ) este un segment de execuţie, un amestec cauzal (causal shuffle) al lui σ este orice permutare π a lui σ care satisface:
-∀i= 0, n 1 , σ i=π i (τ i notează subşirul lui τ care se referă doar la procesorul pi).
-Dacă un mesaj m este trimis în α în evenimentul ϕ al lui pi, atunci în π ϕ precede livrarea lui m.
α
Lema 1: Fie α =exec(C, σ ). Orice ordonare totală a evenimentelor lui σ care e consistentă cu relaţia ⇒ este un amestec cauzal al lui σ .

Lema 2: Fie α = exec(C, σ ). Fie π un amestec cauzal al lui σ . Atunci α ’=exec(C, σ ) este un segment de execuţie similar lui α .
α
Pentru a „observa“ relaţia ⇒ dintr-o execuţie, procesoarele pot adăuga un tag numit logical timestamp pentru fiecare eveniment (de calcul). Această asociere trebuie să fie a.î.
α
ϕ 1 ⇒ ϕ 2 ⇒ LT(ϕ 1)<LT(ϕ 2).
Un algoritm de construcţie a timestamp-urilor este următorul:

 Fiecare procesor pi păstrează o variabilă locală întreagă LTi numită ceas logic, iniţial 0.
 Fiecare eveniment de calcul este extins cu o nouă operaţie care atribuie lui LTi
max (valoarea curentă a lui LTi, valoarea maximă a unui timestamp
primit în acel eveniment)+1.
 Fiecare mesaj trimis într-un eveniment, este ştampilat cu valoarea nouă a lui LTi.

Timestampul unui eveniment este valoarea lui LTi calculată în timpul acelui eveniment. Relaţia de ordine între timestampuri este relaţia de ordine din N.

Teorema 1: Fie α o execuţie şi ϕ 1, ϕ 2 două evenimente din α .


α
Dacă ϕ 1 ⇒ ϕ 2 atunci LT(ϕ 1)<LT(ϕ 2).
α α
Observatie: Dacă LT(ϕ 1)≥ LT(ϕ 2)⇒  ( ϕ 1 ⇒ ϕ 2). Este însă posibil ca LT(ϕ 1)<LT(ϕ 2) şi totuşi  (ϕ 1 ⇒ ϕ 2). Necauzalitatea nu-i surprinsă deoarece N este total ordonat, iar
α
⇒ este o ordine parţială.
Vom folosi vectori cu componente întregi pentru a surprinde necauzalitatea.

Definiţie: : Spunem că ϕ 1 şi ϕ 2 sunt concurente (ϕ 1 ϕ 2 ) în α , dacă


α α
 ( ϕ 1 ⇒ ϕ 2) ∧ ( ϕ 2 ⇒ ϕ 1).
α α
Din lemele 1 şi 2 rezultă că dacă ϕ 1 ϕ 2 atunci există α 1 şi α 2 similare cu α a.î. ϕ 1 ⇒ 1 ϕ 2 şi ϕ 2 ⇒ 2 ϕ 1.

Considerăm următorul algoritm:


 fiecare procesor pi păstrează un tablou n-dimensional VCi (ceasul vectorial), cu componente întregi, iniţial 0.
 fiecare eveniment de calcul este extins cu următoarele operaţii:
- VCi [i]:= VCi [i]+1
- ∀j≠ i VCi [j]:=max(VCi [j], cea mai mare componentă j a timestampurilor primite în acest eveniment)
- ∀mesaj trimis este ştampilat cu noua valoare a lui VCi.

Observatie:
10.VCj(i) este o „estimare” a lui VCi[i] ţinută de pj (numărul de paşi executat de pi până în acest moment).
20.Pentru ∀pj, în orice configuraţie accesibilă VCj[i]≤ VCi[i] ∀i (întrucât numai pi măreşte valoarea lui VCi[i]).
Pe mulţimea vectorilor definim relaţia de ordine parţială v1≤ v2 ⇔∀i= 1, n v1[i]≤ v2[i]. v1<v2⇔v1≤ v2, v1≠ v2.
α
Urmărind definiţia relaţiei ⇒ şi modul de construcţie a ceasurilor vectoriale rezultă:
Teorema 2: Fie α o execuţie şi ϕ 1, ϕ 2 evenimente ale lui α .
α
ϕ 1 ⇒ ϕ 2 ⇔VC(ϕ 1)<VC(ϕ 2).

Observatie: Rezultă că ϕ 1ϕ 2⇔VC(ϕ 1) şi VC(ϕ 2) sunt incomparabile (timestampurile vectoriale surprind (captureaza) concurenţa).
Defectul major al acestui mecanism este că se măreşte enorm complexitatea de comunicare. Din păcate are loc:

Teorema 3: Dacă VC este o funcţie care asociază fiecărui eveniment al unei execuţii oarecare un vector din Rk a.î. concurenţa să fie capturată, atunci k≥ n.

Dem.: Considerăm un sistem distribuit cu topologia un graf complet şi α execuţie în care fiecare procesor pi trimite secvenţial mesaje la toate celelalte, cu excepţia lui pi-1 în ordinea:
pi+1, pi+2,…, pn-1, p0,…, pi-2. După ce toate mesajele au fost primite, fiecare pi primeşte secvenţial mesajele transmise lui în ordine descrescătoare a indicelui transmiţătorului, începând
cu pi-1: pi-1, pi-2, …, p0,pn-1, …, pi+2 (pi nu primeşte mesaj de la pi+1).
Pentru fiecare procesor pi notăm cu ai primul eveniment de trimitere şi cu bi ultimul eveniment de primire.
Cum în α un procesor trimite toate mesajele sale înainte de a primi unul rezultă că relaţia de cauzalitate este simplă şi nu include relaţii derivate de tranzitivitate. Cum nu ∃ mesaj de
la pi+1 la pi şi lipsa tranzitivităţii în patternul de trimitere descris de α , obtinem
(*)∀i 0 ≤ i ≤ n-1, ai+1bi.
Pe de altă parte, ∀pj≠ pi, primul eveniment de trimitere al lui pi+1 influenţează cauzal un anumit mesaj de primire al lui pj. Rezultă
α
(**)∀i,j 0≤ i≠ j≤ n-1 ai+1⇒ bj.
α
(Pentru j=i+1, ai+1 şi bj=bi+1 apar la acelaşi procesor, deci ai+1⇒ bj.
Pentru j≠ i+1, cum j≠ i, pi+1 trimite un mesaj lui pj în execuţie; ai+1 este sau acest eveniment sau se întâmplă înaintea trimiterii mesajului de la pi+1 lui pj. Primirea de la pi+1 este sau egal
cu bj sau se întâmplă înaintea lui bj.)

Fixăm i 0≤ i≤ n-1. Din (*) ai+1bi. Cum VC capturează concurenţa rezultă


că VC(ai+1) şi VC(bi) sunt incomparabile. Deci, ∃ o componentă r a.î. VC[r](bi)<VC[r](ai+1). Notăm acest indice cu l(i).
Am definit o funcţie l:{0, …, n-1}→{0, …, k-1}. Dacă arătăm că l este injectivă teorema este demonstrată.
Presupunem că ∃ i,j: l(i)=l(j)=r. Din definiţia funcţiei l, rezultă VC[r](bi)<VC[r](ai+1) şi VC[r](bj)<VC[r](aj+1). Conform (**),rezultă
α
ai+1⇒ bj, deci VC(ai+1)≤ VC(bj). Am obtinut
VC[r](bi)<VC[r](ai+1)≤ VC[r](bj)<VC[r](aj+1)
care contrazice (**) pentru j=i şi i=j+1!
α
Definiţia relaţiei ⇒ pentru sisteme cu memorie partajată:
α
Fie α o execuţie într-un sistem distribuit cu memoria partajată. Atunci ϕ 1⇒ ϕ 2 dacă:
1.ϕ 1 şi ϕ 2 au aceeaşi valoare (se referă la acelaşi procesor pi) şi ϕ 1
apare în α înaintea lui ϕ 2.
2. ϕ 1 şi ϕ 2 sunt elemente conflictuale: accesează amândouă aceeaşi variabilă partajată, unul dintre ele este un write şi ϕ 1 apare înaintea lui ϕ 2 în α .
α
3.∃ ϕ un eveniment a.î. ϕ 1 ⇒ ϕ şi perechea ϕ , ϕ 2 satisface condiţia 1 sau 2 (cu ϕ în locul lui ϕ 1 ).
Mai departe totul se poate adapta ca si in cazul sistemelor de tip MP.

Tăieturi

Într-un sistem distribuit nu există un observator care să înregistreze un instantaneu al stării sistemului. Aceasta ar fi necesar pentru rezolvarea unor probleme ca: restaurarea
sistemului după o cădere, determinarea existenţei unui deadlock sau detectarea terminării.
Se poate obţine un instantaneu aproximativ prin cooperarea procesoarelor. Pentru simplificarea expunerii vom presupune că fiecare eveniment de calcul primeşte cel mult un mesaj (se
poate implementa o coadă locală a mesajelor sosite şi procesând un singur mesaj la fiecare pas).
Fie α o execuţie fixată. Pentru fiecare procesor se pot număra evenimentele de calcul.
O tăietură a execuţiei este un vector k=(k0, …, kn-1) de întregi pozitivi. Pentru fiecare tăietură se poate construi o mulţime de stări ale procesoarelor: starea procesorului pi este starea sa
din α imediat după evenimentul de calcul numărul ki din pi.
Tăietura k a lui α este consistentă dacă pentru ∀i,j
evenimentul de calcul numărul ki+1 al lui pi în α nu se întâmplă înaintea evenimentului kj al procesorului pj din α (evenimentul numărul kj din α al procesorului pj nu depinde de nici
o acţiune luată de alt procesor după tăietură).
Vom presupune că fiecare canal livrează mesajele într-o ordine FIFO.

Determinarea unei tăieturi consistente maximale

Pentru ∀ tăietură k şi ∀ execuţie α , ∃ o tăietură consistentă k1<k.


O tăietură consistentă maximală ce precede k este o tăietură consistentă k1<k a.î. ∀k’ tăietură k1<k’<k, k’ nu este consistentă.
Se poate demonstra că tăietura consistentă maximală ce precede k este unică.

Presupunem că avem un algoritm A ce se execută pe un sistem distribuit asincron de tip MP. La un moment dat ∀ procesor primeşte o aceeaşi tăietură k. Fiecare procesor trebuie să
calculeze componenta sa din tăietura maximală ce precede k.

(Nu discutăm modul în care se primeşte tăietura; problema este reală şi apare în restaurarea unui sistem distribuit după o cădere).

Pentru realizarea acestui task procesoarele pot memora extra-informaţie, pot ştampila mesajele lui A cu extra-informaţii şi pot trimite mesaje adiţionale.

Descriem o metodă ce necesită suplimentarea mesajelor lui A cu O(n) informaţii. Ideea e foarte simplă: fiecare mesaj al lui A este ştampilat cu VC. Pentru aceasta:
-fiecare procesor pi are un tablou (nemărginit) storei a.î.storei[l] păstrează ceasul vectorial VC asociat evenimentelor de calcul numărul l al lui pi.
-atunci când pi primeşte intrarea k, începe să parcurgă înapoi storei, începând cu storei[ki] până găseşte primul indice l, cu proprietatea că storei[l]<k.
-răspunsul calculat de pi este l.
Determinarea unui instantaneu distribuit
În timp ce procesoarele execută un algoritm A, fiecare procesor dintr-o anumită mulţime S primeşte indicaţia că procesoarele trebuie să înceapă calculul unei tăieturi consistente
care include starea cel puţin a unui procesor din S la momentul în care a primit indicaţia de start. (O astfel de tăietură se numeşte instantaneu distribuit).

Prezentăm un algoritm pentru rezolvarea acestei probleme prin trimiterea unor mesaje adiţionale numite markere.
Cum problema este obţinerea unui instantaneu pentru execuţia algoritmului A, primirea mesajelor marker nu trebuie să influenţeze calculul tăieturii.

•fiecare procesor pi are o variabilă locală ansi, iniţial nedefinită care la sfârşit păstrează răspunsul (intrarea lui pi în tăietura consistentă dorită).
•la primirea unui mesaj marker de la un vecin, sau la primirea indicaţiei să înceapă algoritmul, pi execută : dacă ansi nu a fost deja setată atunci atribuie lui ansi numărul mesajelor
primite de la algoritmul A până în acel moment şi trimite un mesaj marker tuturor vecinilor (inundare).

Algoritm de determinare a unui instantaneu distribuit


(codul pentru procesorul pi):
Iniţial, ans=⊥ şi num=0.

La primirea unui mesaj al algoritmului A:


1: num:=num+1
2: execută acţiunile algoritmului A

La primirea unui mesaj marker sau a indicaţiei să ia un instantaneu:


3: if ans=⊥ then
4: ans:=num
5: send marker tuturor vecinilor.

Teoremă: Algoritmul de mai sus calculează un instantaneu distribuit folosind O(m) mesaje adiţionale.
Dem.: Fie k răspunsul calculat de algoritm. Fie pf primul procesor care primeşte o indicaţie de start. Clar, kf va avea valoarea lui numf din momentul primirii indicaţiei de start.
Presupunem că ∃ pi şi pj a.î. evenimentul de calcul kj al lui pj (în algoritmul A) depinde de evenimentul ki+1 al lui pi (în algoritmul A).
Există un şir de mesaje ale algoritmului A de la pi la pj: m1, m2, …, ml a.î. m1 e trimis de pi lui pi2 după tăietura din pi, m2 este trimis de pi2 lui pi3 după primirea lui m1 ş.a.m.d. iar ml
este trimis de pil lui pj după primirea lui ml-1 şi primit de pj înainte de tăietura din pj. Există deci un mesaj mh care e trimis de pih după tăietură şi primit de pih+1 înaintea tăieturii. Dar cum
pih este trimis după tăietură pih a trimis deja mesajul marker lui pih+1 înaintea trimiterii lui mh. Cum canalele sunt organizate FIFO şi mesajul marker este primit de pih+1 înaintea lui mh şi
deci mh n-a fost primit înaintea tăieturii.
Observatie: Cei doi algoritmi ignoră conţinutul canalelor (stivelor de mesaje). O soluţie e să presupunem că stările locale ale procesoarelor pătrează ce mesaje au fost primite şi
trimise. Atunci informaţia despre canale se obţine din colecţia stărilor procesoarelor. Soluţia este nepractică datorită volumului de memorie locală necesar.
O altă soluţie se obţine după cum urmează:
Algoritm de determinare a tăieturilor maximale consistente: În tabloul store fiecare componentă conţine şi numărul de mesaje primite de procesor de la vecinii săi pe lângă VC.
Atunci când trebuie calculată o tăietură maximală consistentă, fiecare procesor pi parcurge tabloul său store înainte, începând cu prima componentă, şi simulează o „reluare“ a
mesajelor pe care le-ar fi trimis. Procesul se termină cu ultima intrare, l, din storei a.î.VC din storei[l] este ≤ k (tăietura dată). Considerăm un vecin pj oarecare al lui pi. În storei[l] se
cunoaşte numărul x al mesajelor primite de pi de la pj. Când pi a terminat „reluarea“ sa, trimite x lui pj. Când pj primeşte mesajul de la pi, aşteaptă până când îşi calculează propria sa
reluare. Atunci pj calculează starea canalului de la pj la pi pentru tăietura consistentă ca fiind sufixul, începând cu al (x+1)-lea al secvenţei de mesaje care este generată de „reluare“ pe
care el le-a trimis lui pi.
Algoritmul de determinare a unui instantaneu distribuit: se modifică a.î. fiecare procesor pi înregistrează şirul de mesaje primite de la fiecare pj, de la momentul când pi şi-a determinat
răspunsul ansi până în momentul în care pi primeşte un mesaj marker de la pj. Se obţine astfel şi informaţie referitoare la mesajele în tranzit în configuraţia care corespunde
instantaneului distribuit.

Problema sesiunii.
α
Relaţia ⇒ capturează dependenţele din interiorul sistemului, dar nu surprinde interacţiunea cu mediul înconjurător.
Problema sesiunii pe care o descriem în continuare poate fi uşor rezolvată în sisteme sincrone, însă necesită extra-timp considerabil pentru sisteme asincrone, datorită necesităţii
comunicării explicite.

O sesiune este o perioadă minimă de timp în care fiecare procesor execută o acţiune specială cel puţin o dată. Problema sesiunii cere ca pentru un s dat să se garanteze execuţia a cel
puţin s sesiuni.

Mai precis:
-fiecare procesor pi are o variabilă întreagă SAi.
-în timpul execuţiei fiecare procesor pi incrementează SAi la anumite evenimente de calcul (incrementarea lui SA reprezintă „acţiunea specială“ menţionată mai sus).
-orice execuţie se partiţionează în sesiuni disjuncte, unde o sesiune este un fragment de execuţie în care orice procesor îşi incrementează variabila SA cel puţin o dată.

Problema cere să se construiască un algoritm care pentru un s dat să garanteze că în orice execuţie admisibilă:
-există cel puţin s sesiuni
-nici un procesor nu-şi incrementează variabila SA de o infinitate de ori (procesoarele se vor opri odată şi odată în execuţia acţiunii speciale).

Timpul de execuţie este timpul până la ultima incrementare a lui SA (folosind convenţiile standard de la măsurarea timpului în sisteme asincrone).
Pentru sistemele sincrone algoritmul este banal: fiecare procesor este lăsat să execute s acţiuni speciale. În fiecare rundă avem o sesiune şi deci timpul este cel mult s.
În sistemele asincrone timpul de rezolvare a problemei depinde de diametrul reţelei de comunicaţie.
Teoremă: Fie A un algoritm pentru problema s-sesiunii într-un sistem distribuit sincron de tip memorie partajată cu reţeaua de comunicaţie având diametrul D. Atunci CT a lui A este
> (s-1)⋅ D.
Dem.: Presupunem, prin reducere la absurd, că exista un algoritm A cu CT≤ ( s-1)⋅ D.
Fie α o execuţie admisibilă a lui A care este sincronă (α constă dintr-o serie de runde, fiecare rundă conţinând un eveniment de livrare pentru fiecare mesaj în tranzit, urmat de un
pas de calcul al fiecărui procesor).
Fie β δ planificarea lui α unde β se termină la sfârşitul rundei conţinând ultima acţiune specială. Deci δ nu are acţiuni speciale (iar β constă din cel mult (s-1)D runde, din
ipoteza asupra algoritmului A).
Ideea demonstraţiei: Vom înlocui β cu un amestec cauzal al lui β δ a.î. să se realizeze mai puţin de s sesiuni şi totuşi procesorul să nu distingă această situaţie de cea originală şi
deci ele vor opri execuţia acţiunilor speciale prematur. Intuitiv, aceasta se întâmplă întrucât nu-i timp suficient pentru ca informaţia referitoare la îndeplinirea sesiunilor să circule prin
toată reţeaua.
Lema 1: Fie γ un subşir contiguu al lui β constând din cel mult x runde complete (x-întreg pozitiv). Fie C configuraţia ce precede imediat primul eveniment al lui γ în execuţia
α .Considerăm două procesoare oarecare pi şi pj. Dacă dist(pi, pj)>x (în reţeaua de comunicaţie) atunci există un şir de evenimente γ ’=γ 1γ 2 numit split(γ , j, i) a.î.:
-γ 1 este pi-free (nu are evenimente referitoare la pi)
-γ 2 este pj-free
-exec(C,γ ’) este un segment de execuţie similar lui exec(C, γ ).
Dem.: Fie ϕ i primul eveniment al lui pi în γ şi ϕ j ultimul eveniment al lui pj în γ (Dacă γ este pi-free γ 1=γ şi γ 2 vid; Dacă γ este pj-free atunci γ 2=γ şi γ 1 vid). Arătăm că
α
 (ϕ i⇒ ϕ j) (nici un eveniment al lui pj în timpul lui γ nu depinde de vreun eveniment al lui pi în timpul lui γ ). Dacă ar exista o astfel de dependenţă, ar exista un şir de mesaje de
la ϕ i la ϕ j în γ . Numărul rundelor necesare pentru acest lanţ ar fi cel puţin dist(pi, pj)+1, din construcţia lui α (într-o rundă nu există două evenimente care să se influenţeze cauzal).
Dar acest număr de runde este cel puţin x+1, contradicţie cu alegerea lui γ .
α
Fie R restricţia relaţiei ⇒ la evenimentele din γ la care adăugăm perechea (ϕ j, ϕ i): ϕ j trebuie să apară înaintea lui ϕ i.
R este o relaţie de ordine pe mulţimea evenimentelor din γ .
Fie γ ’ o ordine totală a evenimentelor din γ care este consistentă cu R. Cum γ ’ e consistentă cu restricţia ca ϕ i să apară după ϕ j urmează că γ ’=γ 1γ 2 unde γ 1 este pi-free şi γ 2
este pj-free.
Întrucât γ ’ este un amestec cauzal al lui γ rezulta ca exec(C, γ ’) este un fragment de execuţie similar lui exec(C, γ ).
Partiţionăm β =β 1…β s-1 , în care fiecare β i constă din cel mult D runde (dacă n-ar fi posibil, atunci numărul de runde din β ar fi mai mare de (s-1)⋅ D, în contradicţie cu
presupunerea asupra timpului de execuţie al lui A).
Alegem p0 şi p1 a.î. dist(p0, p1)=D.
split ( βi ,1,0) daca i este impar
Considerăm β ’i=  0 ≤ i ≤ s −1 .
 split ( β i ,0,1) daca i este par
Lema 2. Fie C0 configuraţia iniţială a lui α . Atunci exec(C0, β ’1…β ’s-1) este o execuţie a lui A care e similară lui exec(C0,β ).

Dem.: Se arată prin inducţie după i că exec(C0,β ’1 … β ’i) este o execuţie a lui A care este similară lui exec(C0, β 1 … β i) 0≤ i≤ s-1. În pasul inductiv se aplică lema precedentă.

Rezultă că α ’=exec(C0, β ’1 … β ’s-1 δ ) e o execuţie admisibilă a lui A.


Arătăm că există prea puţine sesiuni în α ’, contrazicând ipoteza de corectitudine a lui A.
Sesiunea 1 nu se poate termina înaintea primei părţi a lui β ’1 întrucât p0 nu face nici un pas în prima parte a lui β ’1. Sesiunea 2 nu se poate termina înaintea părţii a II-a a lui β ’2, căci
p1 nu face nici un pas după terminarea sesiunii 1 până în a doua parte a lui β ’2. În acest fel obţinem că sesiunea s-1 nu se poate termina până la a doua jumătate a secţiunii β ’s-1. Dar
ultima parte a lui β ’s-1 nu conţine o sesiune completă întrucât sau p0 sau p1 nu apare în ea!
Cum în γ nu se execută nici o acţiune specială, toate sesiunile trebuie incluse în exec(C0, β ’1 … β ’s-1) şi prin urmare α ’ conţine cel mult s-1 sesiuni .

Sincronizarea ceasurilor.
Pentru studiul complexităţii timp a sistemelor distribuite asincrone s-a introdus noţiunea de t-executie (timed execution). Fiecare eveniment are asociat un timp de apariţie (timpul
real) care nu este accesibil procesoarelor.
Modele mai puternice ale sistemelor distribuite presupun că procesoarele au acces la informaţia referitoare la timp prin intermediul ceasurilor hard: acestea oferă aproximaţii ale
timpilor reali.

Modelul formal al sistemelor distribuite cu ceasuri hard:


Într-o t-executie, se asociază fiecărui procesor pi o funcţie HCi:R→R. Atunci când pi execută un pas de calcul la timpul real t, HCi(t) e disponibil ca intrare în funcţia de tranziţie a lui
pi. Această funcţie de tranziţie nu poate modifica HCi.
Vom considera că ∀i HCi(t)=t+ci (ceasul hard al procesorului pi măsoară fără abateri timpul trecut de la un eveniment la altul).
Pentru fiecare t-executie se poate asocia starea iniţială şi şirul de evenimente (de calcul şi de livrare) asociate unui procesor: view(pi). Putem proceda şi invers, din cele n view-uri să
construim o execuţie.
Definiţie: view(pi) într-un model cu ceasuri hard constă dintr-o stare iniţială a lui pi, un şir de evenimente (de calcul sau de livrare) ce apar în pi şi câte o valoare a ceasului hard
asociată fiecărui eveniment. Şirul valorilor ceasurilor hard este crescător şi dacă şirul de evenimente este infinit, atunci şirul valorilor ceasurilor hard este nemărginit.
Definiţie: t-view(pi) într-un model cu ceasuri hard este un view(pi) împreună cu o valoare reală asociată fiecărui eveniment. Aceste valori trebuie să fie consistente cu ceasurile hard
satisfăcând HCi(t)=t+ci.

O mulţime de n t-view-uri η i i= 0, n −1 pot fi reunite într-o t-exec astfel:


Configuraţia iniţială se obţine considerând stările iniţiale din η i. Se consideră apoi un şir de evenimente prin interleavingul evenimentelor din η i, consistent cu timpii reali (dacă
există mai multe evenimente la un moment t se respectă ordinea impusă de evenimentele de livrare, dacă nu mai există alt criteriu de ordonare se folosesc indicii procesoarelor).
Aplicând acest şir de evenimente stării iniţiale se obţine o t-execuţie. Rezultatul este merge(η 0, …, η n-1). Aceasta este o execuţie dacă t-view-urile sunt „consistente“.
 
Definiţie: : Fie α o t-exec cu ceasuri hard şi fie x un vector real cu n componente. Definim shift(α , x ) ca fiind merge(η 0, …, η n-1) unde η i este t-view-ul obţinut adăugând xi
la timpul real asociat cu fiecare eveniment din α i.

Lema: Fie α o t-exec cu ceasuri hard HCi 0≤ i ≤ n-1 şi x un vector real .

In shift(α , x ):
(a)HC’i (ceasul hard asociat lui pi) este HCi-xi 0 ≤ i ≤ n-1.
(b)∀mesaj de la pi la pj are întârzierea δ -xi+xj unde δ este întârzierea mesajului din α ∀i,j∈{0, …, n-1}.

Problema sincronizării ceasurilor.


Fiecare procesor are o componentă specială de stare adji pe care o poate manipula. Ceasul ajustat al lui pi este funcţie de HCi şi variabila adji.
În procesul de sincronizare a ceasurilor, pi modifică valoarea lui adji şi deci schimbă valoarea ceasului ajustat.Dacă ceasurile hard sunt fără abateri, atunci ACi(t)=HCi(t)+adji(t) unde
adji(t) este valoarea lui adji în configuraţia imediat dinaintea ultimului eveniment a cărui apariţie în timp este mai mare decât t. Dacă ceasurile hard sunt fără abateri, odată atinsă
sincronizarea nu mai este nevoie de nici o acţiune ulterioară.
Atingerea ε -sincronizării ceasurilor: În ∀ t-exec admisibilă ∃ tf timp real a.î. algoritmul se termină la momentul t f şi ∀ pi, pj ∀t ≥ tf ACi(t)-ACj(t)≤ ε .
ε se numeşte skew.(distorsiune, perturbaţie)
•Vom presupune că ∃ d,u d ≥ u > 0 a.î. în ∀ t-exec admisibilă ∀ mesaj are întârzierea în intervalul [d-u,d].
(pi trimite un mesaj m lui pj la momentul real t, atunci trebuie să apară un eveniment de livrare a lui m urmat de un pas de calcul al lui pj nu mai târziu de t+d şi nu mai devreme de t+d-
u).
•Vom presupune că reţeaua de comunicare este completă (pentru simplificarea expunerii)

Algoritm de sincronizare a ceasurilor pentru n procesoare


(cod pentru pi , 0≤ i ≤ n-1)

la primul pas de calcul:


1: trimite HC tuturor procesoarelor

la primirea mesajului T de la pj :
2: diff[j]:=T +d -u/2-HC
3: if (s-au primit mesaje de la toate procesoarele) then
4: adj:= media aritmetică a componentelor vectorului diff

Se poate demonstra
Teoremă: Algoritmul atinge u(1-1/n)-sincronizarea ceasurilor.

Observaţie: S-a dovedit că orice algoritm care atinge ε-sincronizarea satisface εΣ u(1-1/n), ceea ce arată că algoritmul dat este optimal.

Consens tolerant la defectări

1. Sisteme sincrone cu căderi

Cel mai simplu scenariu de procesare distribuită tolerantă la defectări: sisteme distribuite sincrone în care procesoarele "cad" , încetând să opereze.
Vom considera numai sisteme distribuite sincrone cu topologia graf complet. Canalele vor fi considerate ca fiind fără defecte, deci toate mesajele trimise vor fi livrate.
Sistemul se numeşte f-rezilient dacă numărul maxim de procesoare care se pot defecta este f.

Definiţia unui execuţii trebuie modificată pentru un sistem f-rezilent. În sistem există o mulţime F ⊂ {p0, ..........pn-1} cu F ≤ f , necunoscută, a procesoarelor defecte.

Fiecare rundă care conţine exact un eveniment de calcul pentru fiecare procesor care nu-i din F şi cel mult un eveniment de calcul pentru fiecare eveniment din F.
În plus, dacă un procesor din F nu are un eveniment de calcul într-o rundă, atunci nu va mai avea în nici o rundă care urmează. De asemenea se presupune că într-o rundă
în care un procesor cade, vor fi livrate doar o submulţime arbitrară dintre mesajele pe care le trimite. Dacă am avea o cădere curată - toate mesajele trimise sunt livrate sau nici un
mesaj nu este livrat- atunci problemele create se rezolvă mult mai simplu.

Problema consensului
Fiecare procesor pi are o componentă a stării sale xi (intrarea) şi o componentă yi (ieşirea sau decizia). Iniţial xi are o valoare dintr-o mulţime total ordonată iar yi este
nedefinit. Orice asignare asupra lui yi este ireversibilă. O soluţie la problema consensului trebuie să garanteze:
Terminarea: În ∀ execuţie admisibilă, yi va primi o valoare pentru fiecare procesor nedefect pi.
Agreement: În ∀ executie dacă yi şi yj au fost asignate atunci yi = yj pentru ∀ procesoare nedefecte pi şi pj. (procesoarele nedefecte nu decid pe valori conflictuale)
Validitate: În ∀ execuţie dacă ∃ o valoare v a.î. xi = v pt ∀ pi şi dacă yi este asignat pentru un procesor nedefect pi, atunci yi =v (dacă toate procesoarele au aceeaşi intrare, atunci
singura valoare pe care ele vor decide este intrarea comună).

Un algoritm simplu
Fiec procesor işi menţine o mulţime a valorilor pe care el le ştie că ∃ în sistem. Iniţial această mulţime este formată doar din intrarea sa. În fiecare din cele f+1 runde pe
care le execută sistemul, fiecare procesor îşi actualiză mulţimea sa cu mulţimile primite de la acel procesor şi difuzează orice nouă modificare. În acest moment, procesoarele decid pe
valorile minime din multimea fiecăruia.

Algoritm de consens (codul pentru pi)

Iniţial V= {x} // V conţine intratea lui pi


runda k 1 ≤ k ≤ f+1

1. send {v; v∈V, v n-a fost deja trimis} tuturor procesoarelor

2. receive Sj de la pj 0 ≤ j ≤ n-1 j≠ i
n −1
3. V := V ∪  S j
j =1

4. if k = f+1 then y:= min(V)

Terminarea este asigurată deorece algoritmul prevede exact f+1 runde, ultima asignând o valoare a lui y.
Validitatea este asigurată, deoarece această valoare este o intrare a unui procesor.
Condiţia de agreement este satisfăcută aşa cum rezultă din următoarea lemă.

Lemă: În orice execuţie, la sfârşitul rundei f+1, Vi = Vj, ∀ două procesoare nedefecte pi şi pj.

Demonstraţie: Considerăm două proceasoare nedefecte oarecare pi şi pj.


Demonstrăm că dacă x ∈ Vi la sfârşitul rundei f+1 atunci x ∈ Vj la sfârşitul rundei f+1. Fie r prima rundă la care x este adăugat la un V k pentru un procesor nedefect pk (r =0 dacă x
era valoarea iniţială a lui pk).
Dacă r ≤ f, în runda r+1 (≤ f+1), x va fi trimis lui pj care îl adaugă la Vj , dacă nu era deja prezent.

Presupunem, deci, că r= f+1 şi că p k primeşte x pentru prima oară în runda f+1. Există un şir de f+1 procesoare pi , pi
1 f +1
a.î. pi
1
trimite x lui pi 2
în runda 1,

pi 2
lui pi 3 în runda 2, ......... , p i f lui pi f +1
în runda f şi pi f +1
lui pk în runda f+1. Cum fiecare procesor trimite o valoare particulară o singură dată, acestea sunt

distincte. Deci avem o mulţime de f+1 procesoare care va conţine sigur unul nedefect, care deci va adăuga x la mulţimea sa într-o rundă ≤ f < r contrazicând alegerea lui r.
Teoremă: Algoritmul precedent rezolvă problema consensului în prezenţa a f căderi în f+1 runde.

O margine inferioară asupra numărului de runde


Fie α o execuţie admisibilă a unui algoritm de consens şi fie dec(α ) decizia unui procesor oarecare nedefect ( care din condiţia de agreement este unic definită).
Ideea obţinerii marginii inferioare: dacă procesoarele decid prea devreme ele nu pot distinge o execuţie admisibilă în care ele iau decizii diferite.
Vom presupune f ≤ n – 2.
p1
Definiţie: Două execuţii α 1 şi α 2 sunt similare în raport cu pi, notat
α1 ~ p2 ,
dacă α 1 | pi = α 2 | pi.
pi
Evident, dacă α 1 ~α 2 rezultă că pi decide pe aceeasi valoare în ambele execuţii. Din condiţiile de agreement toate procesoarele nedefecte vor decide pe o aceeasi

valoare.
pi
Deci, α1 ~α 2 ⇒ dec(α 1) = dec(α 2).

Considerăm închiderea tranzitivă a relaţiei ~ notată ≈ :


α 1 ≈ α 2 ⇔ ∃ β 1,..............., β k+1 şi pi1,..............,pik a.î.
pi pi pi
α 1=β β ,..., β = α 2.
1
~ 2
~ ~ k+1

Evident, α 1 ≈ α 2 ⇒ dec(α 1 ) ≈ dec (α 2 ).


Vom presupune că ∀ procesor nedefect trimite mesaje la toate celelalte în fiecare rundă (dacă nu-i aşa se pot trimite mesaje fictive).
Considerăm mai întâi cazul parcticular când f=1.
Lema. Dacă n ≥ 3, nu există algoritm care să rezolve problema consensului în mai puţin de două runde în prezenţa unei singure căderi.
Demonstratie:
Presupunem că ∃ un algoritm în care toate procesele nedefecte decid după runda 1, pentru mulţimea intrărilor {0,1}.

Fie αi execuţia admisibilă a algoritmului în care procesoarele p0 până la pi-1 au valorile iniţiale 1 şi celelalte 0 (0 ≤ i ≤ n) (în α o procesoarele au toate intrările 0 iar α n

au toate intrările 1).

Dacă arătăm că α
i
≈ α i +1 0 ≤ i ≤ n − 1 ⇒ 0 = dec (α 0 ) = dec (α n ) = 1 , contradicţie.
Considerând αij excuţia în care procesoarele încep cu aceeaşi valoare iniţială ca şi α i, dar care în runda 1 se "defectează" netrimiţând mesaje la ultimele j procesoare:

p n −1 ,   p n − j , 0 ≤ j ≤ n-1 (excluzându-se eventual pe el însuşi).

Evident α 0i = α i . Pentru fiecare 0 ≤ j ≤ n-2, cum n > 3, ∃ un procesor nedefect pk diferit de procesorul care primeşte mesaj în αij dar nu în αij +1 . Deci

pk
α ij ∼ α ij +1
pk
În αni −1 pi nu trimite mesaje. Dacă schimbăm intrarea lui pi din 0 în 1 rezultă o execuţie admisibilă β0i . Pentru ∀ procesor p k ≠ pi
α ni −1 ∼ β 0i pentru că am modificat

intrarea unui procesor care nu trimite mesaje.

Pentru j =0, n −1 considerăm βij execuţia admisibilă în care p0,....... pi încep cu 1 restul cu 0 şi în runda 1 p i trimite mesajele sale la primele j cele mai mici

procesoare, excluzându-se pe el însuşi dacă este cazul. Ca mai înainte ∀ j 0 ≤ j ≤ n-2, cum n ≥ 3, ∃ un procesor nedefect în pk altul decât procesorul ce primeşte mesajul lui pi

p
în βij +1 dar nu în βij , deci β i ∼k β i . Evident β ni −1 = α i +1 şi deci am demonstrat că α i ≈ α i +1
j j +1

Cazul general.

Presupunem că există un algoritm care rezolvă problema consensului în cel mult f runde 1 ≤ f ≤ n-2.
Un pattern al mesajelor specifică pentru fiecare rundă şi fiecare procesor care din mesajele trimise de el vor fi livrate altui procesor în acea rundă. Clar, patternul mesajelor
descrie patternul căderilor.
Un procesor este nedefect în runda r a unei execuţii dacă toate mesajele pe care el le-a trimis în runda r sunt livrate.
O execuţie admisibilă este r - failure–free (r-ff) dacă nici un procesor nu este defect într-o rundă ≥ k. În particular, o execuţie admisibilă este failure-free dacă este 1-ff.
Fie α o execuţie admisibilă r-ff cu configuraţia iniţială I şi patternul căderilor M şi presupunem că procesorul p i este nedefect în runda r. Notăm cu crash (α , pi, v)
execuţia admisibilă cu configuraţia iniţială I şi patternul mesajelor M' unde M' este egal cu M cu excepţia faptului că p i nu va mai transmite nici un mesaj începând cu runda r; după
runda r este posibil ca pi să se comporte diferit în cele 2 execuţii.
Lemă. Pentru ∀ r, 1 ≤ r ≤ f, dacă α este r-ff cu cel mult o defecţiune în fiecare rundă şi procesorul pi este nedefect în α , atunci
α ≈ crash (α , pi, r).

Demonstraţie: Inducţie după f-r.


r = f. Fie α r-ff execuţie şi presupunem că pi e nedefect în α . În runda f există cel puţin 3 procesoare nedefecte . (În fiecare rundă se defectează cel mult un procesor, în runda f nu
avem procesoare defecte deci avem cel mult f-1 procesoare defecte iar f ≤ n-2).
Procedăm ca în demonstraţia precedentă şi construim un şir de execuţii eliminând câte un mesaj trimis de p i în runda f (execuţia α0i până la α0n −1 ). Cum măcar două
procesoare în afara lui pi sunt nedefecte în runda f şi numai un procesor are view-urile diferite în fiecare pereche de execuţii consecutive, cel puţin un procesor nedefect are acelaşi

p
view în fiecare pereche de execuţii consecutive. Deci avem pentru fiecare din execuţiile consecutive. Ultima execuţie din acest şir este o execuţie în care pi nu trimite nici un

mesaj în runda f, deci crash (α ,pi , f)≈ α .
În pasul inductiv, presupunem că lema are loc pentru runda r+1, 1 ≤ r ≤ f-1 şi demonstrăm că are loc pentru r.
Fie α o execuţie r-ff cu cel mult o defecţiune în fiecare rundă şi presupunem că pi este nedefect în runda r.
Evident α este şi (r+1)-ff cu cel mult o defecţiune în fiecare rundă şi deci aplicând ipoteza inductivă lui pi obţinem crash(α ,pi , v+1)≈ α .
Fie α 0 o execuţie care este exact crash(α ,pi , r+1) cu excepţia faptului că pi cade la sfârşitul rundei r după ce trimite toate cele n-1 mesaje, în loc să cadă la începutul rundei
r+1.
pj

Dar α 0
∼ crash(α ,p , r+1) pentu ∀ procesor nedefect p . Se observă că α
i j 0 este (r+1)-ff. În plus α 0 are cel mult o defecţiune pe rundă întrucât α este r-ff şi în runda r
în α 0 se adaugă o defecţiune prin construcţie.
Eliminăm mesajele lui pi din runda r unul câte unul astfel: pentru ∀ j 1 ≤ j ≤ n-1, fie α j execuţia cu aceeasi configuraţie iniţială ca α 0 şi acelasi pattern al mesajelor ca
α 0, cu excepţia faptului că pi nu trimite în runda r mesaje ultimelor j procesoare, cu excepţia sa, dacă este necesar (şi desigur nu mai trimite mesaje în viitor). Fiecare α j este (r+1)-ff
şi are cel mult o cădere pe rundă.
Dacă demonstrăm că α ≈ α j-1 ∀ j 1 ≤ j ≤ n-1 obţinem α n-1 ≈ α şi cum α n-1 = crash(α ,pi , v) lema este demonstrată.
Fie ph procesorul care prin mesajul lui pi din runda r în α j-1 dar nu în α j ( h = n-1-j dacă ultimile j procesoare includ pi , altfel h = n-2-j).

pl
Cazul 1. ph defect în α . Cum α este r-ff, ph cade într-o rundă k< r şi deci cade şi în α j-1 şi în α j . Clar α j-1
∼α j pentru un procesor nedefect pl (∃ pentru că r<f ≤ n-2
şi ∃ cel mult o cădere pe rundă). (Nici un procesor nu poate spune dacă pi trimite lui ph un mesaj în runda r, pentru că ph era deja mort).
Cazul 2. ph nu este defect în α .
Cum α j-1 este (r+1)-ff şi are cel mult o cădere pe rundă, aplicand ipoteza inductivă, rezultă crash(α j-1 , ph , r+1)≈ α j-1 .
Similar crash (α j , ph , r+1 ) ≈ α j . Cum singura diferenţă dintre crash(α j-1 , ph , r+1) şi crash (α j , ph , r+1 ) este că mesajul lui pi către ph din runda r este prezent în prima şi nu este
prezent în a doua, iar ph nu va trimite mesaje mai departe, rezultă că crash(α j-1 , ph , r+1) ≈ crash (α j , ph , r+1 ).

Teoremă: Nu există algoritm care să rezolve problema consensului în mai puţin de f+1 runde în prezenţa a f căderi dacă n≥ f+2.

Demonstraţie: Presupunem prin reducere la absurd că ∃ un algoritm care rezolvă problema în mai puţin de f+1 runde.
Considerăm o execuţie admisibilă fără căderi în care toate procesoarele au intrarea 0.
Fie α i (0 ≤ i ≤ n) execuţia admisibilă a algoritmului fără căderi în care procesoarele p 0 până la pi -1 încep cu 1 şi celelalte încep cu 0. Deci α 0 are toate intrările 0 iar α n

are toate intrările 1. Demonstrăm că: α 0 ≈ α 1 ≈ ...≈ α n


şi cum dec(α 0) = 0 (datorită condiţiei de validitate) obţinem că dec(α n) = 0 contrazicand condiţia de validitate pentru α n .
α i este fără căderi deci are cel mult o cădere pe rundă. Deci α i ≈ crash (α i,pi , 1) şi α i+1
≈ crash (α i+1
,pi , 1). Cum singura diferenţă dintre crash (α i,pi , 1) şi crash (α i+1
,pi , 1)
este intrarea lui pi şi cum pi nu trimite mesaje ⇒
crash (α i,pi , 1) ≈ crash (α i+1
,pi , 1).

2. Sisteme sincrone cu căderi bizantine

Defecţiunile sunt "răutăcioase" faţă de cele "curate" ale modelului precedent.


Descrierea metaforică a problemei: Mai multe divizii ale armatei Bizantine sunt campate lângă cetatea inamicului. Fiecare divizie este comandată de un general. Generalii
comunică între ei doar prin mesageri (care işi îndeplinesc ireproşabil sarcinile). Generalii trebuie să decidă asupra unui plan comun de acţiune, adică să decidă dacă să atace sau nu
cetatea (agreement) şi dacă generalii sunt toţi unanimi în opinia lor iniţială atunci aceasta trebuie să fie decizia pe care o vor lua.
Problema este că unii dintre generali pot fi trădători (doar sunt în armata bizantină !!) şi ei pot încerca să-i împiedice pe generalii loiali să fie de acord. Pentru aceasta ei
trimit mesaje diferite la generali diferiţi, retransmit în mod eronat ce-au auzit de la alţii sau chiar pot conspira şi forma o coaliţie.
Modelul formal: Sistem distribuit sincron f - rezilient.
În orice execuţie ∃ o submulţime de cel mult f procesoare care se pot defecta (procesoarele defecte, trădătorii). Într-un pas de calcul al unui procesor defect nu se impune
nici o restricţie asupra noii stări sau asupra mesajelor transmise (în particular se poate comporta ca în modelul precedent). Sistemul se comportă ca şi în lipsa căderilor: la fiecare rundă
fiecare procesor execută un pas de calcul şi orice mesaj transmis în acea rundă este livrat pentru următoarea rundă.
Problema consensului : exact acelaşi enunţ.

Spre deosebire de modelul precedent, condiţia de valabilitate nu este echivalentă cu a cere ca decizia unui procesor oarecare nedefect să fie intrarea unui anumit procesor.
O margine superioară pentru numărul procesoarelor defecte
Lema: Într-un sistem cu 3 procesoare în care unul poate fi bizantin nu există un algoritm care să rezolve problema consensului.
Demonstraţie: Presupunem că există un astfel de algoritm într-un sistem cu 3 procesoare p0, p1 , p2 conectate printr-un graf complet cu trei vârfuri.
Notăm cu A, B, C programele locale ale lui p0, p1 , p2 respectiv.
Considerăm un inel sincron cu 6 procesoare în care p0 şi p3 au programul local A, p1 şi p4 au programul local B şi p2 şi p5 au programul local C.

P3: A(0)

P4: B(0) P2: C(1)

P1: B(1)
P5: C(0)

P0: A(1)
Desigur, mesajele dintr-un program local vor fi transmise procesorului vecin cu acelaşi program cu cel din triunghi. (p0, nu trimite lui p2 ci lui p5 , p3, nu trimite lui p1 ci lui p4 etc. ).
Considerând β o execuţie particulară a acestui algoritm pe inel, în care p0, p1 , p2 au intrarea 1 iar p3, p4 , p5 au intrarea 0.
Revenim la problema nostră.
Consideram α 1 execuţia algoritmului în
{ p0, p1 , p2 } în care toate procesoarele pornesc cu 1 şi procesorul p2 este defect. Mesajele pe care le trimite p2 le considerăm ca fiind:
p2 → p0 mesajele trimise în β de p5 lui p0
p2 → p0 mesajele trimise în β de p2 lui p1

Din condiţia de validitate, p0 şi p1 vor decide pe 1 în α 1.

• Considerăm α 2 execuţia algoritmului în { p0, p1 , p2 } în care toate procesoarele pornesc cu intrarea 0 şi procesorul p0 este defect.
Mesajele pe care le trimite p0 le considerăm ca fiind:
p0 → p1 mesajele trimise în β de p3 lui p4
p0 → p2 mesajele trimise în β de p0 lui p5

Din condiţia de validitate, p1 şi p2 decid pe 0 în α 2.

• Considerăm α 3 execuţia algoritmului { p0, p1 , p2 } în care p0 porneşte cu intrarea 0, p1 porneşte cu intrarea 1, p2 porneşte cu intrarea 0 şi defect este p1.
Mesajele pe care le trimite p1 le considerăm ca fiind:
p1 → p2 mesajele trimise în β de p4 → p5
p1 → p0 mesajele trimise în β de p1 → p0

Observăm că :
 p0 are acelaşi view în α 1 pe care îl are şi în β

 p0 are acelaşi view în β pe care îl are şi în α 3

p0
Deci (inductiv după numărul de runde) α α 3⇒ p0 decide 1 în α 3.
1

p2
Similar α α 3 ⇒ p2 decide 0 în α 3.
2

Dar acesta contravine condiţiei de agreement. Contradicţie.

Teoremă. Într-un sistem cu n procesoare dintre care f sunt bizantine nu există un algoritm care să rezolve problema consensului dacă n ≤ 3f.
Demonstraţie. Presupunem, prin reducere la absurd, că există un astfel de algoritm.

n 
Partiţionăm mulţimea procesoarelor în P0, P1, P2 fiecare conţinând cel mult  procesoare.
3 

Considerăm un sistem cu trei procesoare {p0, p1, p2}. Pentru acest sistem descriem un algoritm de consens care poate tolera o cădere bizantină (contrazicând teorema
precedentă).
În algoritm, p0 simulează toate procesoarele din P0, p1 pe cele din P1 şi p2 pe cele din P2.

n
Dacă unul din procesoare în sistemul {p0, p1, p2} este defect cum ≤ f rezultă că în sistemul simulat cu n procesoare avem cel mult f procesoare defecte. Algoritmul
3
simulat trebuie să păstreze validitatea şi condiţia de agreement din sistemul simulat şi deci şi în sistemul cu 3 procesoare.

Un algoritm exponential

Prezentăm un algoritm care în f +1 runde rezolvă problema consensului în ipoteza că n ≥ 3f+1. Totuşi, foloseşte mesaje de dimensiune exponenţială
Algoritmul are două etape:
- I se colectează informaţia prin comunicare între procesoare
- II pe baza informaţiei colectate, fiecare procesor ia decizia sa.
Este convenabil să descriem informaţia menţinută de fiecare procesor cu ajutorul unor arbori etichetaţi.
Arborele fiecărui procesor are proprietatea că oricare drum de la rădăcină la frunze are f+2 noduri (arborele are adâncimea f+1). Fiecare nod este etichetat cu şiruri de nume
de procesoare astfel:
- rădăcina are eticheta cuvântul vid λ

- nodul v cu eticheta i1 i2 ...ir (de pe nivelul r+1; aflat la adâncimea r) are ca descendenţi câte un nod etichetat i1 i2 ...ir i pentru oricare

i ∈{0, 1, ..., n-1} \ {i1 i2 ...ir} (etichetele au simboluri distincte).


Vom spune că nodul i1 i2 ...ir-1 i de pe nivelul r corespunde procesorului i.

Faza I-a
În runda 1: fiecare procesor trimite valoarea sa tuturor procesoarelor (inclusiv lui însuşi; aceasta se simulează)
În runda 2: (fiecărui procesor îi sunt livrate mesajele din runda precedentă şi procesoarele nedefecte memorează valoarea primită de la procesorul pj în nodul etichetat j de
pe nivelul 1. Deci fiecare procesor nedefect are completat arborele:

n
1 2
x1 x2 xn

• fiecare procesor trimite un mesaj format din nivelul 2 din arborele său celorlalte procesoare.
În runda 3: (fiecare procesor a luat mesajul primit de la pj şi valoarea memorata de pj în nodul i, o memorează în nodul ij de pe nivelul 3.

j n
1 2

1j 2j nj

• fiecare procesor trimite un mesaj format din nivelul 3 din arborele său celorlalte procesoare.

În general
În runda r fiecare procesor difuzează celorlalte nivelul r din arborele său.
Cînd un procesor primeşte un mesaj de la pj cu valoarea din nodul arborelui lui pj etichetat i1 i2 ...ir-1 = x, el memorează valoarea x în nodul
i1 i2 ...ir j din arborele său.
Intuitiv pi memorează în i1 ...ir j valoarea: "pj spune că pir spune că

pir-1 spune că .... că p i1 spune x".

Vom nota această valoare treei (i1, ..., iv, j) omiţind indicile i când nu este pericol de confuzie.
Faza I-a conţine f+1 runde, când se umple fiecare arbore al procesoarelor.
Urmează faza II-a.
Procesorul pi îşi calculează decizia sa aplicând fiecărui subarbore o funcţie recursivă resolve. În arborele lui p i, dacă avem un subarbore etichetat π , valoarea determinată de funcţie o
notăm resolvei (π ). (eventual omiţând indicele).
Decizia luată de pi va fi resolvei ( )(aplicarea funcţiei rădacinii arborelui)

 t r ( π e) d e an c o cã deu ut i lπc e h sf etr etu a(π na lrz gfeã+ 1).


r e s( π )o=  l v e
 m a ( rj oe sr( π ′ o)i; π t′ l ydv e s ca lel uπ n) i d e n t
Observaţie:

1. dacă în prima fază a algoritmului un nod primeşte o valoare nelegitimă sau nu primeşte o valoare (procesorul care ar fi trebuit să i-o trimită este defect) nodul memorează în

nodul corespunzător o valoare default v⊥.

2. dacă majority nu există funcţia resolve ia valoarea v⊥.

Fixăm o execuţie admisibilă a algoritmului. Să reamintim că dacă un nod π din arborele lui pi corespunde lui pj atunci valoarea memorată în tree(π ) a fost primită într-un mesaj de la
pj.

Lema 1. Pentru orice nod π de forma π 'j unde pj este nedefect avem
resolvei (π ) = treej (π ') , ∀ pi nedefect.
Demonstraţie: Inductiv după adâncimea lui π în arbore, pornind din frunze.
π frunză: prin definiţie resolvei(π ) = treei(π ), dar treei(π ) memorează valoarea lui π ' pe care pj o trimite lui π i în ultima rundă. Cum pj nu este defect acceastă valoare
este treej(π ').
π nod intern. Cum arborele are f +2 nivele rădăcina are n descendenţi şi la fiecare nivel numărul descendenţilor scade cu 1 ⇒ π are cel puţin n - f descendenţi. Cum n ≥
3f+1 gradul lui π este ≥ 2f +1. Majority aplicată descendenţilor lui π corespunde procesoarelor nedefecte. Fie π k un descendent al lui π (care corespunde procesorului nedefect pk).
Din ipoteza inductivă, resolvei(π k) = treek(π ), pj nedefect ⇒ treek(π ) = treej (π ') adică pj îi spune corect lui pk valoarea pe care pj a memorat-o în π '.
Deci pi rezolvă fiecare copil al lui π corespunzător unui procesor nedefect ca fiind treej(π ') şi deci resolvei(π ) este egală cu valoarea majoritară treej(π ').

Algoritmul satisface condiţia de validitate. Presupunem că toate procesoarele nedefecte pornesc cu aceasi valoare v iniţială. Decizia fiecărui procesor nedefect pi este resolvei(), care
este valoarea majoritară din valorile rezolvate pentru descendenţii rădăcină. Pentru fiecare descendent j cu pj nedefect, lema precedentă asigură că resolvei(j) = treej( ) =v (pj nu este
defect). Cum valoarea majoritară corespunde procesoarelor nedefecte ⇒ pi decide pe v.

Pentru a demonstra condiţia de agreement considerăm următoarea definiţie:


Nodul π este comun într-o execuţie dacă toate procesoarele nedefecte calculează aceeaşi valoare în nodul π :
resolvei(π ) = resolvej(π ), ∀ pi, pj nedefecte.
Un subarbore are frontieră comună dacă există un nod comun pe oricare drum din rădăcina subarborelui la frunzele sale.

Lema 2. Fie π un nod. Dacă subarborele cu rădăcina în π are frontieră comună ⇒ π e comun.
Demonstraţie: Inductiv după înălţimea lui π .
Dacă π este frunză, evident. În pasul inductiv,
presupunem că lema are loc pentru orice nod cu înălţimea k şi fie π cu înălţimea k+1. Presupunem că π nu este comun. Cum subarborele cu rădăcina în π are frontieră comună ⇒
orice subarbore cu rădăcina în copiii lui π are frontieră comună, şi din ipoteza inductivă fiecare copil al lui π este comun. Deci toate procesoarele rezolvă aceeaşi valoare pentru toţi
copii lui π şi prin urmare şi pentru π (pentru că se aplică majoritatea ).
Rezultă că π este comun.

Nodurile de pe fiecare drum de la un copil al rădăcinei la o frunză corespund la procesoare diferite (f+1), cel puţin unul este nedefect şi deci este comun conform lemei 1. Deci, lema 2
asigură faptul că rădăcina este comună, adică are loc condiţia agreement.
Concluzie:
Teoremă. Dacă n > 3f, există un algoritm pentru n procesoare care rezolvă problema consensului în prezenţa a f căderi bizantine în f+1 runde, folosind mesaje de dimensiune
exponenţială.
Observaţie: MC = n2 (f+1) (numărul mesajelor trimise).
Mesajul cel mai lung trimis conţine n(n-1)...(n-(f+1)) = θ (nf+2) valori.

Un alg polinomial
Dacă n > 4f se poate construi un algoritm cu mesaje de dimensiune constantă care rezolvă problema în 2(f+1) runde
Algoritmul are f+1 faze, fiecare fază cu 2 runde.
Pentru fiecare fază, fiecare procesor are o decizie preferată (preferinţa sa), iniţial, aceasta fiind valoarea sa.
• În prima rundă a fiecărei faze toate procesoarele îşi trimit preferinţa lor tuturor celorlalte.

Fie v ik valoarea majoritară în mulţimea valorilor primite de un procesor pi la sfârşitul primei runde din faza k (dacă nu există majoritate se foloseşte o valoare default vT).

• În a doua rundă a fiecărei faze k, procesorul pk - numit regele fazei - trimite valoarea sa majoritară v kk celorlalte procesoare.

n
Dacă un procesor pi primeşte > +f copii a lui v ik (în prima rundă a fazei) atunci el consideră preferinţa sa pentru faza următoare ca fiind v ik . Altfel, alege drept
2

preferinţa sa pentru faza următoare ca fiind cea a regelui v kk (primită în runda 2-a a fazei).

• După f+1 runde procesorul decide pe preferinţa sa

Algoritm polinomial de consens în prezenţa căderilor bizantine


Codul pentru pi ( 0 ≤ i ≤ n −1)
Iniţial pref [i] = x pref [j] = v⊥ ∀j≠ i

Runda 2k-1 1 ≤ k ≤ f +1 // prima rundă a fazei k

1: send < pref [i] > tuturor procesoarelor


2: receive < vj > de la pj şi asignează-l lui pref [j] 0 ≤ j ≤ n-1, j≅ i
3: fie maj valoarea majoritară din pref [0], ..., pref [n-1] (v⊥ dacă nu
există)
4: fie mult multiplicitatea lui maj

Runda 2k, 1≤ k ≤ f+1 // a doua rundă a fazei k.


5: if i=k then send <maj> tuturor procesoarelor // regele fazei
6: receive <king-maj> from pk (v⊥ dacă nu există)

n
7: if mult > + f
2
8: then pref [i]: = maj
9: else pref [i]: = king-maj
10: if k= f+1 then y : = pref [i] // decide

Lema 1. Dacă toate procesoarele nedefecte preferă v la începutul fazei k, atunci toate preferă v la sfârşitul fazei k, ∀ k, 1≤ k ≤ f+1.

Demonstraţie: Cum toate preferă v la începutul fazei k fiecare precesor primeşte cel puţin n-f copii ale lui v (inclusiv pe a sa) în prima rundă a fazei k. Cum n > 4f ⇒ n-f >
n/2 + f ; deci toate procesoarele preferă v la sfârşitul fazei k.
Din acestă lemă rezultă imediat proprietatea de validitate: dacă toate procesoarele nedefecte încep cu aceeaşi valoare de intrare v atunci ele vor prefera v în toate fazele;
deci şi în faza f+1 când vor decide pe v.
Condiţia de agreement este asigurată de intervenţia regilor. Cum sunt f+1 faze, măcar o fază are un rege nedefect.
Lema 2. Fie g o fază astfel încât regel pg nu este defect. Atunci toate procesoarele nedefecte sfârşesc faza g cu acceaşi preferinţă.
Demonstraţie: Presupunem că toate procesoarele nedefecte folosesc valoarea majoritară primită de la rege ca preferinţă. Cum regele nu este defect, trimite acest mesaj
tuturor şi deci ele vor avea aceeaşi preferinţă.

n
Presupunem că un procesor nedefect pi foloseşte valoarea majoritară proprie v ca preferinţă. Deci pi primeşte mai mult de + f mesaje egale cu v în prima rundă a
2

n
fazei g. În consecinţă orice procesor (inclusiv regele pg ) primeşte > mesaje egale cu v în prima rundă a fazei g şi işi va alege valoarea sa majoritară egală cu v. Deci în faza g+1
2
toate procesoarele vor avea acceaşi preferinţă şi lema 1 ne asigură că vor decide pe acceaşi valoare la sfârşit. Concluzie:
Teoremă: Dacă n>4f, algoritmul precedent rezolvă problema consensului în prezenţa a f defecţiuni Bizantine în 2(f+1) runde folosind mesaje de dimensiune constantă.

Observaţie. In cazul sistemelor distrbuite asincrone, nu se poate rezolva problema consensului, chiar în prezenţa unei singure defecţuni.

You might also like