Sunteți pe pagina 1din 11

Aplicaţii folosind paralelismul de date

Calculul sumelor prefix

Problema
dat fiind tabloul a[1:n], se cere s[1:n], unde

s[i] = Σk=1,i a[k]

Algoritm secvential

s[1] = a[1];
for [i = 2 to n] s[i] = a[i] + s[i-1];

Algoritm paralel
derivat din algoritmul sumei elementelor unui vector
Suma elementelor unui vector

Σ1,8

Σ1,4 Σ5,8

Σ1,2 Σ3,4 Σ5,6 Σ7,8

1 2 3 4 5 6 7 8
Executia algoritmului ca opt procese paralele

p1 p2 p3 p4 p5 p6 p7 p8
-----------------------------------------
a1 a2 a3 a4 a5 a6 a7 a8
+----¦ +----¦ +----¦ +----¦
¦ ¦ ¦ ¦
a1 s12 a3 s34 a5 s56 a7 s78
+---------¦ +----------¦
¦ ¦
a1 s12 a3 s14 a5 s56 a7 s58
+---------------------¦
¦
a1 s12 a3 s14 a5 s56 a7 s18
Suma elementelor unui vector - algoritmul
int a [1:n];
process suma [k=1 to n]{ // suma ~ procesele p din figura !
for [j = 1 to sup(log2 n)]{
if (k mod 2 j == 0) a[k] = a[k-2j -1] + a[k];
barrier;
}
p1 p2 p3 p4 p5 p6 p7 p8
}
-----------------------------------------
a1 a2 a3 a4 a5 a6 a7 a8
+----¦ +----¦ +----¦ +----¦
¦ ¦ ¦ ¦
a1 s12 a3 s34 a5 s56 a7 s78
+---------¦ +----------¦
¦ ¦
a1 s12 a3 s14 a5 s56 a7 s58
+---------------------¦
¦
a1 s12 a3 s14 a5 s56 a7 s18
Sume prefix – varianta 1
SUME PREFIX SUMA ELEMENTELOR – tipar p6
int a [n];
int a [1:n]; process suma [k=1 to n]{
process suma [k=1 to n]{ for [j = 1 to sup(log2 n){
if k mod 2 j == 0 a[k] := a[k-2j -1] + a[k];
for [j = 1 to sup(log2 n]{ barrier;
if (k-2j-1>=1) a[k] = a[k-2j -1] + a[k]; }
}
barrier;
}
p1 p2 p3 p4 p5 p6
Solutia: promovarea a1 a2 a3 a4 a5 a6

tiparului pentru
ultimul proces la s11 s 12 s 23 s 34 s 45 s 56
celelalte procese

s11 s 12 s 13 s 14 s 25 s 36
Obs.: se poate si cu
un nr. oarecare de
procese (nu neaparat s11 s 12 s 13 s 14 s 15 s 16
putere a lui 2)
Sume prefix – varianta 2
1 2 3 1 2 3 1 2 temp 3
2
1 1
3 5 3 6 1 3 5
a1 a2 a3 a1 a a a1 a2 a3
2 3

int a[1:n], temp[1:n];


process suma [k=1 to n] {
for [j = 1 to sup(log2 n)]{
temp[k] = a[k];
barrier;
if (k-2j-1>=1) a[k] = temp[k-2j-1] + a[k];
barrier;
}
}
Sume prefix – varianta 3
int a[n], temp[n];
inlocuit 2j-1 cu d
process suma [k=1 to n){
ciclul rescris in functie for [j = 1 to sup(log2 n)]{
de d temp[k] := a[k];
barrier;
if (k-2j-1>=1) a[k] = temp[k-2j-1] + a[k];
barrier;
}
int a[1:n], temp[1:n]; }
process suma[k=1 to n]{
int d = 1;
while (d<n){
temp[k] = a[k];
barrier;
if (k-d>=1) a[k] = temp[k-d] + a[k];
barrier;
d = 2*d;
}
}
Sume prefix – varianta SIMD
int a[n], temp[n];
process suma[k=1 to n]{
int a[1:n]; for [j = 1 to sup(log2 n)]{
process suma [k=1 to n]{ temp[k] = a[k];
barrier;
int temp; if (k-2j-1>=1)
/*temp este locala procesului k*/ a[k] := temp[k-2j-1] + a[k];
barrier;
for [j = 1 to sup(log2 n)]
}
if (k-2j-1>=1){ }
temp = a[k-2j-1];
VARIANTA MIMD
a[k] = temp + a[k];
}
}

Pune in evidenta procesoarele care


lucreaza – k :=2j-1+1 to N
Liste

cap 3 4 2 5 0 leg
data
1 2 3 4 5

Considerăm o listă de pînă la n elemente, păstrate într-un tablou data[1:n],


legăturile între elemente fiind păstrate într-un tablou distinct, leg[1:n].
Problema: găsirea sfîrşitului listei
Algoritmul secvenţial - O(n)
Algoritm paralel: foloseste tehnica dublarii distantei (de la calcule prefix)
à O(log n)
Foloseste un tablou end[1:n]; initial end := leg

La fiecare ciclu: daca end[i] nu indica sfarsitul listei, se dubleaza distanta


dacă end[i] <> 0 şi end[end[i]] <> 0 à end[i] := end[end[i]]
După un ciclu, legăturile din end indică elemente aflate la 2 legături distanţă,
după două cicluri la 4 etc.
Liste (2)

initial cap 3 4 2 5 0 end

1 2 3 4 5

end[2] <> 0 şi end[end[2]] <> 0 end[4] <> 0 şi end[end[4]] = 0


à end[2] se modifica à end[4] nu se modifica

dupa pas
cap 1 23 45 42 5 0 end

1 2 3 4 5
int leg[1:n], end[1:n];
process Afla [i=1 to n){
int nou, d=1;
end[i] = leg[i];
barrier;
while (d<n){
nou = 0; //tampon pentru legatura urmatoare
if (end[i]<>0 and end[end[i]]<>0)
nou=end[end[i]];
barrier;
if (nou<>0) end[i]=nou;
barrier;
d = 2*d
}
}
cap 3 4 2 5 0 leg
data
1 2 3 4 5

S-ar putea să vă placă și