03.07.2013 Views

Algoritmen en Datastructuren III Partim: Parallelle algoritmen - caagt

Algoritmen en Datastructuren III Partim: Parallelle algoritmen - caagt

Algoritmen en Datastructuren III Partim: Parallelle algoritmen - caagt

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong><br />

<strong>Partim</strong>: <strong>Parallelle</strong> algoritm<strong>en</strong><br />

Veerle Fack<br />

12 november 2008


Inhoudsopgave<br />

1 Inleiding 1<br />

1.1 <strong>Parallelle</strong> algoritm<strong>en</strong> ontwerp<strong>en</strong> <strong>en</strong> analyser<strong>en</strong> . . . . . . . . . . . . . . . . . . . 2<br />

1.2 Modell<strong>en</strong> van parallelle computers . . . . . . . . . . . . . . . . . . . . . . . . . 4<br />

2 Het gedeelde-geheug<strong>en</strong>model 7<br />

2.1 Het gedeelde-geheug<strong>en</strong>model . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />

2.2 De Parallel Random-Access Machine (PRAM) . . . . . . . . . . . . . . . . . . 10<br />

2.2.1 Het PRAM-model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10<br />

2.2.2 Geheug<strong>en</strong>modell<strong>en</strong> voor PRAM . . . . . . . . . . . . . . . . . . . . . . 11<br />

2.2.3 Semigroep-problem<strong>en</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . 13<br />

2.2.4 Kost-optimaliser<strong>en</strong> van PRAM-algoritm<strong>en</strong> . . . . . . . . . . . . . . . . 14<br />

2.3 Het werk-tijd-paradigma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15<br />

2.3.1 Het WT-pres<strong>en</strong>tati<strong>en</strong>iveau . . . . . . . . . . . . . . . . . . . . . . . . . 15<br />

2.3.2 Het WT-scheduling-niveau . . . . . . . . . . . . . . . . . . . . . . . . . 16<br />

3 Het netwerkmodel 19<br />

3.1 Het netwerkmodel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20<br />

3.2 Circuits <strong>en</strong> systolische algoritm<strong>en</strong> . . . . . . . . . . . . . . . . . . . . . . . . . 20<br />

3.3 Interconnecti<strong>en</strong>etwerk<strong>en</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21<br />

3.3.1 Netwerktopologieën . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21<br />

3.3.2 Rij <strong>en</strong> ring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22<br />

3.3.3 Rooster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24<br />

3.3.4 Hyperkubus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24<br />

3.4 Communicatie-algoritm<strong>en</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27<br />

i


ii INHOUDSOPGAVE<br />

3.4.1 One-to-all broadcast . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28<br />

3.4.2 All-to-all broadcast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30<br />

3.4.3 Single-node scatter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31<br />

3.4.4 Total exchange . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32<br />

3.5 Gedistribueerde algoritm<strong>en</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32<br />

4 Ontwerptechniek<strong>en</strong> voor parallelle algoritm<strong>en</strong> 35<br />

4.1 Pipelining / Sorter<strong>en</strong> & Priemzeef . . . . . . . . . . . . . . . . . . . . . . . . . 36<br />

4.1.1 Techniek van pipelining . . . . . . . . . . . . . . . . . . . . . . . . . . 36<br />

4.1.2 Sorter<strong>en</strong> via pipelining . . . . . . . . . . . . . . . . . . . . . . . . . . . 36<br />

4.1.3 Priemzeef via pipeling . . . . . . . . . . . . . . . . . . . . . . . . . . . 37<br />

4.2 Gebalanceerde bom<strong>en</strong> / Prefixsomm<strong>en</strong> . . . . . . . . . . . . . . . . . . . . . . . 38<br />

4.2.1 Techniek van gebalanceerde bom<strong>en</strong> . . . . . . . . . . . . . . . . . . . . 38<br />

4.2.2 Wat zijn prefixsomm<strong>en</strong>? . . . . . . . . . . . . . . . . . . . . . . . . . . 38<br />

4.2.3 Berek<strong>en</strong><strong>en</strong> van prefixsomm<strong>en</strong> in het PRAM-model . . . . . . . . . . . . 39<br />

4.2.4 Berek<strong>en</strong><strong>en</strong> van prefixsomm<strong>en</strong> op e<strong>en</strong> rooster . . . . . . . . . . . . . . . 41<br />

4.2.5 Berek<strong>en</strong><strong>en</strong> van prefixsomm<strong>en</strong> op e<strong>en</strong> hyperkubus . . . . . . . . . . . . . 42<br />

4.3 Partitionering / Merge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42<br />

4.3.1 Techniek van partitioner<strong>en</strong> . . . . . . . . . . . . . . . . . . . . . . . . . 42<br />

4.3.2 E<strong>en</strong> e<strong>en</strong>voudig merge-algoritme . . . . . . . . . . . . . . . . . . . . . . 42<br />

4.3.3 Parallel algoritme voor merge via partitioner<strong>en</strong> . . . . . . . . . . . . . . 43<br />

4.4 Accelerated cascading / Maximum bepal<strong>en</strong> . . . . . . . . . . . . . . . . . . . . 45<br />

4.4.1 Bepal<strong>en</strong> van het maximum . . . . . . . . . . . . . . . . . . . . . . . . . 45<br />

4.4.2 Bepal<strong>en</strong> van het maximum in constante tijd . . . . . . . . . . . . . . . . 45<br />

4.4.3 Algoritme voor het maximum in dubbel-logaritmische tijd . . . . . . . . 46<br />

4.4.4 Het snelle algoritme optimaal mak<strong>en</strong> . . . . . . . . . . . . . . . . . . . 47<br />

4.4.5 Opmerking: speciaal geval . . . . . . . . . . . . . . . . . . . . . . . . . 48<br />

5 <strong>Parallelle</strong> sorteeralgoritm<strong>en</strong> 49<br />

5.1 Sorteernetwerk<strong>en</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50<br />

5.1.1 Wat zijn sorteernetwerk<strong>en</strong>? . . . . . . . . . . . . . . . . . . . . . . . . . 50<br />

5.1.2 Bitonisch sorter<strong>en</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


INHOUDSOPGAVE iii<br />

5.1.3 Merg<strong>en</strong> <strong>en</strong> sorter<strong>en</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55<br />

5.1.4 Het nul-e<strong>en</strong>-principe voor sorteernetwerk<strong>en</strong> . . . . . . . . . . . . . . . . 57<br />

5.2 Sorter<strong>en</strong> op interconnecti<strong>en</strong>etwerk<strong>en</strong> . . . . . . . . . . . . . . . . . . . . . . . . 60<br />

5.2.1 Odd-ev<strong>en</strong>-transposition sorter<strong>en</strong> op e<strong>en</strong> rij van processor<strong>en</strong> . . . . . . . . 60<br />

5.2.2 Bitonisch sorter<strong>en</strong> op de hyperkubus . . . . . . . . . . . . . . . . . . . . 60<br />

5.2.3 Shearsort op e<strong>en</strong> rooster van processor<strong>en</strong> . . . . . . . . . . . . . . . . . 60<br />

5.3 PRAM-variant<strong>en</strong> van klassieke sorteeralgoritm<strong>en</strong> . . . . . . . . . . . . . . . . . 63<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


Hoofdstuk 1<br />

Inleiding<br />

In dit gedeelte van de cursus bestuder<strong>en</strong> we hoe berek<strong>en</strong>ing<strong>en</strong> kunn<strong>en</strong> word<strong>en</strong> versneld door<br />

meerdere processor<strong>en</strong> te gebruik<strong>en</strong> in plaats van één <strong>en</strong>kele processor. <strong>Algoritm<strong>en</strong></strong> die ontworp<strong>en</strong><br />

werd<strong>en</strong> om uitgevoerd te word<strong>en</strong> op e<strong>en</strong> netwerk van processor<strong>en</strong>, word<strong>en</strong> parallelle of<br />

gedistribueerde algoritm<strong>en</strong> g<strong>en</strong>oemd, afhankelijk van de aard van het netwerk. Processor<strong>en</strong><br />

in gedistribueerde netwerk<strong>en</strong> zijn doorgaans onafhankelijker van elkaar dan processor<strong>en</strong> in e<strong>en</strong><br />

parallel netwerk.<br />

De bedoeling van dit cursusgedeelte is het introducer<strong>en</strong> van verscheid<strong>en</strong>e modell<strong>en</strong> van parallelle<br />

computers <strong>en</strong> het opstell<strong>en</strong> van e<strong>en</strong> geschikt raamwerk voor het voorstell<strong>en</strong> <strong>en</strong> analyser<strong>en</strong> van<br />

parallelle algoritm<strong>en</strong>. De nadruk ligt op techniek<strong>en</strong>, paradigma’s <strong>en</strong> methodes, eerder dan op de<br />

gedetailleerde implem<strong>en</strong>tatie voor specifieke toepassing<strong>en</strong>.<br />

1


2 Hoofdstuk 1. Inleiding<br />

1.1 <strong>Parallelle</strong> algoritm<strong>en</strong> ontwerp<strong>en</strong> <strong>en</strong> analyser<strong>en</strong><br />

E<strong>en</strong> vraag die zich onmiddellijk stelt is: Hoe kan e<strong>en</strong> algoritme geëvalueerd word<strong>en</strong> op zijn geschiktheid<br />

voor parallelliser<strong>en</strong>? Net zoals in het geval van sequ<strong>en</strong>tiële algoritm<strong>en</strong> zijn er meerdere<br />

belangrijke criteria, zoals uitvoeringstijd, geheug<strong>en</strong>gebruik <strong>en</strong> programmeerbaarheid. Maar de<br />

situatie bij parallelle algoritm<strong>en</strong> wordt nog ingewikkelder, door de aanwezigheid van bijkom<strong>en</strong>de<br />

factor<strong>en</strong>, zoals het aantal processor<strong>en</strong>, de capaciteit van lokale geheug<strong>en</strong>s van de processor<strong>en</strong>, de<br />

communicatieschema tuss<strong>en</strong> processor<strong>en</strong>, <strong>en</strong> de gebruikte protocols voor synchronisatie tuss<strong>en</strong><br />

processor<strong>en</strong>.<br />

Voorbeeld 1.1.1. Veronderstel dat we n exemplar<strong>en</strong> van e<strong>en</strong> rapport moet<strong>en</strong> uitprint<strong>en</strong> <strong>en</strong> dat het<br />

print<strong>en</strong> van één exemplaar één tijdse<strong>en</strong>heid vereist. Wanneer we slechts één printer ter beschikking<br />

hebb<strong>en</strong>, duurt het uitprint<strong>en</strong> van alle rapport<strong>en</strong> T ∗ (n) = n tijdse<strong>en</strong>hed<strong>en</strong>. Wanneer we twee<br />

printers ter beschikking hebb<strong>en</strong>, kan het uitprint<strong>en</strong> gebeur<strong>en</strong> in ⌈n/2⌉ tijd, door ⌈n/2⌉ printaanvrag<strong>en</strong><br />

naar de <strong>en</strong>e printer te stur<strong>en</strong> <strong>en</strong> ⌊n/2⌋ naar de andere. Algeme<strong>en</strong>, wanneer we p printers<br />

hebb<strong>en</strong>, kan het print<strong>en</strong> gebeur<strong>en</strong> in Tp(n) = ⌈n/p⌉ tijd.<br />

Het uitprint<strong>en</strong> van meerdere exemplar<strong>en</strong> van e<strong>en</strong> rapport is e<strong>en</strong> voorbeeld van e<strong>en</strong> taak die gemakkelijk<br />

efficiënt kan word<strong>en</strong> uitgevoerd door meerdere machines. Verschill<strong>en</strong>de instanties<br />

van de taak hang<strong>en</strong> niet van elkaar af, zodat ze e<strong>en</strong>voudigweg aan p verschill<strong>en</strong>de machines<br />

(hier printers) kunn<strong>en</strong> word<strong>en</strong> toegek<strong>en</strong>d. Als we ev<strong>en</strong>veel printers ter beschikking hebb<strong>en</strong> als er<br />

exemplar<strong>en</strong> te print<strong>en</strong> zijn, m.a.w. p = n, dan kunn<strong>en</strong> we het probleem oploss<strong>en</strong> in parallelle tijd<br />

Tp(n) = Θ(1), de tijd nodig om één <strong>en</strong>kel rapport te print<strong>en</strong> op één <strong>en</strong>kele printer. Wanneer we de<br />

uitvoeringstijd van de twee oplossing<strong>en</strong> vergelijk<strong>en</strong>: T ∗ (n) = n stapp<strong>en</strong> op één printer (voor de<br />

sequ<strong>en</strong>tiële oplossing) <strong>en</strong> Tp(n) = ⌈n/p⌉ stapp<strong>en</strong> op p printers (voor de parallelle oplossing), dan<br />

zi<strong>en</strong> we dat de parallelle oplossing e<strong>en</strong> factor p sneller is. M<strong>en</strong> zegt dat de parallelle oplossing<br />

e<strong>en</strong> versnelling Sp(n) = p over de sequ<strong>en</strong>tiële oplossing heeft.<br />

We noem<strong>en</strong> Tp(n) de parallelle uitvoeringstijd van e<strong>en</strong> algoritme op p processor<strong>en</strong> voor e<strong>en</strong><br />

probleem van grootte n. Merk op dat we de sequ<strong>en</strong>tiële uitvoeringstijd noter<strong>en</strong> als T ∗ (n), d.i.<br />

de uitvoeringstijd van het beste sequ<strong>en</strong>tiële algoritme voor het gegev<strong>en</strong> probleem.<br />

De versnelling (of speed-up) geeft e<strong>en</strong> maat voor de winst in uitvoeringstijd van het parallelle<br />

algoritme t.o.v. het sequ<strong>en</strong>tiële algoritme, <strong>en</strong> wordt gedefinieerd als<br />

Sp(n) = T ∗ (n)<br />

Tp(n) .<br />

In dit deel bestuder<strong>en</strong> we in welke mate computationele problem<strong>en</strong> kunn<strong>en</strong> word<strong>en</strong> versneld<br />

door meer dan één processor of machine te gebruik<strong>en</strong>, m.a.w. in welke mate we e<strong>en</strong> gegev<strong>en</strong><br />

taak kunn<strong>en</strong> parallelliser<strong>en</strong>. In het bov<strong>en</strong>staande voorbeeld, hadd<strong>en</strong> we e<strong>en</strong> sequ<strong>en</strong>tieel algoritme<br />

dat het probleem oploste in f(n) tijd, <strong>en</strong> e<strong>en</strong> parallel algoritme dat p machines gebruikte <strong>en</strong> het<br />

probleem oploste in ⌈ f(n)/p⌉ tijd. We kunn<strong>en</strong> niet hop<strong>en</strong> dat p processor<strong>en</strong> het probleem sneller<br />

dan dat kunn<strong>en</strong> oploss<strong>en</strong>, omdat we anders het sequ<strong>en</strong>tiële algoritme zoud<strong>en</strong> kunn<strong>en</strong> verbeter<strong>en</strong><br />

tot e<strong>en</strong> uitvoeringstijd kleiner dan f(n), nl. door de parallelle process<strong>en</strong> e<strong>en</strong> na e<strong>en</strong> op één <strong>en</strong>kele<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


1.1. <strong>Parallelle</strong> algoritm<strong>en</strong> ontwerp<strong>en</strong> <strong>en</strong> analyser<strong>en</strong> 3<br />

Algoritme 1.1 Zoek<strong>en</strong> van het grootste elem<strong>en</strong>t in e<strong>en</strong> array (sequ<strong>en</strong>tieel algoritme)<br />

Input: array (a1,...,an), l<strong>en</strong>gte n<br />

Output: de waarde van het grootste elem<strong>en</strong>t in a<br />

1: Stel m ← a1<br />

2: for i from 2 to n do<br />

3: if ai > m th<strong>en</strong><br />

4: Stel m ← ai<br />

5: return m<br />

processor te lat<strong>en</strong> lop<strong>en</strong>. De beste versnelling die we kunn<strong>en</strong> verwacht<strong>en</strong> bij het gebruik van<br />

p processor<strong>en</strong> is dus e<strong>en</strong> factor p.<br />

Bij het ontwerp<strong>en</strong> van e<strong>en</strong> parallel algoritme moet e<strong>en</strong> compromis word<strong>en</strong> gezocht tuss<strong>en</strong> de twee<br />

resources hardware <strong>en</strong> uitvoeringstijd. Meer hardware gebruik<strong>en</strong> kan leid<strong>en</strong> tot e<strong>en</strong> vermindering<br />

van de uitvoeringstijd met e<strong>en</strong> factor p, voor p processor<strong>en</strong>. Wanneer uitvoeringstijd e<strong>en</strong> hoge<br />

prioriteit heeft <strong>en</strong> we de middel<strong>en</strong> voor bijkom<strong>en</strong>de hardware hebb<strong>en</strong>, dan is het nuttig naar<br />

parallelle algoritm<strong>en</strong> te zoek<strong>en</strong>.<br />

E<strong>en</strong> mogelijke b<strong>en</strong>adering bij het ontwerp<strong>en</strong> van e<strong>en</strong> parallel algoritme is te start<strong>en</strong> met e<strong>en</strong> sequ<strong>en</strong>tieel<br />

algoritme voor het probleem <strong>en</strong> te onderzoek<strong>en</strong> of dit algoritme, of gedeelt<strong>en</strong> ervan, kan<br />

word<strong>en</strong> geparallelliseerd. In het algem<strong>en</strong>e geval zull<strong>en</strong> we ge<strong>en</strong> zo’n spectaculaire versnelling<br />

als bij het printervoorbeeld kunn<strong>en</strong> bekom<strong>en</strong>.<br />

Voorbeeld 1.1.2. Als voorbeeld behandel<strong>en</strong> we het probleem van het berek<strong>en</strong><strong>en</strong> van het grootste<br />

elem<strong>en</strong>t in e<strong>en</strong> array. E<strong>en</strong> e<strong>en</strong>voudig sequ<strong>en</strong>tieel algoritme hiervoor wordt gegev<strong>en</strong> in Algoritme<br />

1.1. Merk op dat dit algoritme inher<strong>en</strong>t sequ<strong>en</strong>tieel is, want elke vergelijking hangt af van<br />

alle voorafgaande vergelijking<strong>en</strong>.<br />

Veronderstel dat we e<strong>en</strong> onbeperkt aantal processor<strong>en</strong> ter beschikking hebb<strong>en</strong>. Hoe kan Algoritme<br />

1.1 word<strong>en</strong> geparallelliseerd? In stap 1 van het algoritme gebruik<strong>en</strong> we één processor om het<br />

maximum van twee elem<strong>en</strong>t<strong>en</strong> te vind<strong>en</strong>. Gebruik mak<strong>en</strong>d van ⌊n/2⌋ processor<strong>en</strong> kunn<strong>en</strong> we<br />

van ⌊n/2⌋ par<strong>en</strong> van elem<strong>en</strong>t<strong>en</strong> de maxima bepal<strong>en</strong>. In de volg<strong>en</strong>de stap kunn<strong>en</strong> we met behulp<br />

van ⌊n/4⌋ processor<strong>en</strong> de maxima van ⌊n/4⌋ par<strong>en</strong> bepal<strong>en</strong>, <strong>en</strong>zovoort.<br />

Hoeveel tijd kost dit parallelle algoritme? In elke stap wordt het aantal elem<strong>en</strong>t<strong>en</strong> waarvan het<br />

maximum moet word<strong>en</strong> bepaald, gehalveerd. Het algoritme voert dus t<strong>en</strong> hoogste ⌈log 2 n⌉ stapp<strong>en</strong><br />

uit, hetge<strong>en</strong> e<strong>en</strong> substantiële verbetering is teg<strong>en</strong>over het Θ(n) sequ<strong>en</strong>tiële algoritme. Bov<strong>en</strong>di<strong>en</strong><br />

hebb<strong>en</strong> we <strong>en</strong>kel ⌈n/2⌉ processor<strong>en</strong> nodig om het algoritme in parallelle tijd O(logn) uit<br />

te voer<strong>en</strong>. Op het eerste gezicht ziet het algoritme er goed uit: met e<strong>en</strong> lineair aantal processor<strong>en</strong><br />

kunn<strong>en</strong> we e<strong>en</strong> probleem dat lineaire sequ<strong>en</strong>tiële tijd vereist, oploss<strong>en</strong> in logaritmische parallelle<br />

tijd. Maar er is ook duidelijke inefficiëntie in het algoritme: in de eerste stap word<strong>en</strong> ongeveer<br />

n/2 processor<strong>en</strong> effectief gebruikt, in de tweede stap nog slechts ongeveer n/4, in de k-de stap<br />

nog slechts ongeveer n/2 k . Het overgrote deel van de processor<strong>en</strong> doet dus ge<strong>en</strong> werk gedur<strong>en</strong>de<br />

het algoritme. Dit is duidelijk e<strong>en</strong> verspilling van hardware.<br />

Het bov<strong>en</strong>staande voorbeeld geeft aan dat we parallelle algoritm<strong>en</strong> niet alle<strong>en</strong> moet<strong>en</strong> beoordel<strong>en</strong><br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


4 Hoofdstuk 1. Inleiding<br />

op basis van hun parallelle uitvoeringstijd <strong>en</strong> hun versnelling, maar ook op basis van het aantal<br />

processor<strong>en</strong> dat ze gebruik<strong>en</strong>. De kost Cp(n) van e<strong>en</strong> parallel algoritme is het product van het<br />

aantal processor<strong>en</strong> p <strong>en</strong> het aantal stapp<strong>en</strong> dat het algoritme uitvoert, m.a.w.<br />

Cp(n) = p × Tp(n).<br />

Merk op dat e<strong>en</strong> parallel algoritme met kost Cp(n) kan omgezet word<strong>en</strong> in e<strong>en</strong> sequ<strong>en</strong>tieel algoritme<br />

dat Θ(Cp(n)) uitvoeringstijd vraagt.<br />

Voorbeeld 1.1.3. Het parallelle algoritme uit Voorbeeld 1.1.2 heeft kost Cn(n) = Θ(nlogn),<br />

hetge<strong>en</strong> slechter is dan het sequ<strong>en</strong>tiële algoritme dat uitvoeringstijd (<strong>en</strong> dus kost) T ∗ (n) = Θ(n)<br />

heeft (aangezi<strong>en</strong> het n stapp<strong>en</strong> uitvoert op 1 processor). In term<strong>en</strong> van kost is het parallelle<br />

algoritme dus niet optimaal, omdat er e<strong>en</strong> ander algoritme bestaat dat minder kost vraagt.<br />

We noem<strong>en</strong> e<strong>en</strong> algoritme kost-optimaal als Cp(n) = Θ(T ∗ (n)). Zoals we verder zull<strong>en</strong> zi<strong>en</strong>,<br />

bestaan er techniek<strong>en</strong> die dikwijls toelat<strong>en</strong> om parallelle algoritm<strong>en</strong> kost-optimaal te mak<strong>en</strong>.<br />

1.2 Modell<strong>en</strong> van parallelle computers<br />

E<strong>en</strong> algeme<strong>en</strong> aanvaard model voor het ontwerp<strong>en</strong> <strong>en</strong> analyser<strong>en</strong> van sequ<strong>en</strong>tiële algoritm<strong>en</strong><br />

bestaat uit e<strong>en</strong> c<strong>en</strong>trale verwerkingse<strong>en</strong>heid, die verbond<strong>en</strong> is met e<strong>en</strong> random-access geheug<strong>en</strong>.<br />

De typische instructieset voor dit model omvat lez<strong>en</strong> uit <strong>en</strong> schrijv<strong>en</strong> naar het geheug<strong>en</strong>, ev<strong>en</strong>als<br />

elem<strong>en</strong>taire logische <strong>en</strong> rek<strong>en</strong>kundige bewerking<strong>en</strong>. Dit model heeft zijn welslag<strong>en</strong> te dank<strong>en</strong><br />

aan zijn e<strong>en</strong>voud <strong>en</strong>erzijds <strong>en</strong> aan het feit dat het de performantie van sequ<strong>en</strong>tiële algoritm<strong>en</strong> op<br />

computers van het von Neumann-type adequaat kan inschatt<strong>en</strong>.<br />

Jammer g<strong>en</strong>oeg is er voor parallelle berek<strong>en</strong>ing<strong>en</strong> ge<strong>en</strong> dergelijk algeme<strong>en</strong> aanvaard algoritmisch<br />

model beschikbaar. E<strong>en</strong> van de red<strong>en</strong><strong>en</strong> hiervoor is het feit dat de performantie van parallelle<br />

algoritm<strong>en</strong> afhankelijk is van e<strong>en</strong> complex geheel van factor<strong>en</strong> die machine-afhankelijk zijn.<br />

Deze factor<strong>en</strong> zijn onder meer de mate waarin berek<strong>en</strong>ing<strong>en</strong> kunn<strong>en</strong> geparallelliseerd word<strong>en</strong>, het<br />

toewijz<strong>en</strong> van processor<strong>en</strong> aan deeltak<strong>en</strong>, het plann<strong>en</strong> van tak<strong>en</strong> over verscheid<strong>en</strong>e processor<strong>en</strong>,<br />

aspect<strong>en</strong> van communicatie <strong>en</strong> synchronisatie.<br />

In de praktijk word<strong>en</strong> meerdere verschill<strong>en</strong>de modell<strong>en</strong> voor parallelle computers gebruikt.<br />

We kunn<strong>en</strong> bijvoorbeeld de complexiteit van de gebruikte processor<strong>en</strong> beperk<strong>en</strong>. Wanneer e<strong>en</strong><br />

parallel algoritme op hardware-niveau wordt geïmplem<strong>en</strong>teerd, kan het gebeur<strong>en</strong> dat we niet aan<br />

elke processor de algeme<strong>en</strong>heid van e<strong>en</strong> doorsnee-processor will<strong>en</strong> gev<strong>en</strong>. Bijvoorbeeld, bij het<br />

berek<strong>en</strong><strong>en</strong> van het maximum hebb<strong>en</strong> we <strong>en</strong>kel e<strong>en</strong> kleine gespecialiseerde poort nodig die het<br />

maximum van twee inputs kan berek<strong>en</strong><strong>en</strong>. Deze poort heeft zelfs ge<strong>en</strong> lokaal geheug<strong>en</strong> nodig; ze<br />

moet <strong>en</strong>kel de grootste van de twee inputs verder doorgev<strong>en</strong>. Modell<strong>en</strong> van parallelle computers<br />

die op dit fijne niveau van parallellisme werk<strong>en</strong>, word<strong>en</strong> circuits g<strong>en</strong>oemd, naar analogie met<br />

elektrische circuits.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


1.2. Modell<strong>en</strong> van parallelle computers 5<br />

Op e<strong>en</strong> minder fijn niveau van parallellisme kunn<strong>en</strong> we elke processor zi<strong>en</strong> als e<strong>en</strong> complete computer,<br />

die elk zijn eig<strong>en</strong> sequ<strong>en</strong>tiële algoritme kan uitvoer<strong>en</strong>. We sprek<strong>en</strong> dan van parallelle architectur<strong>en</strong>.<br />

Op dit niveau wordt het onderscheid tuss<strong>en</strong> de verschill<strong>en</strong>de modell<strong>en</strong> gemaakt op<br />

basis van de manier waarop de processor<strong>en</strong> met elkaar communicer<strong>en</strong>. In het PRAM-model hebb<strong>en</strong><br />

alle processor<strong>en</strong> e<strong>en</strong> geme<strong>en</strong>schappelijk geheug<strong>en</strong> dat voor communicatie gebruikt wordt.<br />

Bepaalde tak<strong>en</strong> kunn<strong>en</strong> goed word<strong>en</strong> opgelost door speciale types van netwerk<strong>en</strong>, zoals ring<strong>en</strong>,<br />

bom<strong>en</strong> of roosters.<br />

In sommige gevall<strong>en</strong> zijn de processor<strong>en</strong> minder sterk met elkaar gekoppeld. Geheug<strong>en</strong> kan<br />

gedistribueerd zijn, eerder dan gedeeld; elke processor heeft zijn eig<strong>en</strong> lokale geheug<strong>en</strong> <strong>en</strong> er<br />

is ge<strong>en</strong> globaal geheug<strong>en</strong>. Het kan gebeur<strong>en</strong> dat de processor<strong>en</strong> ge<strong>en</strong> geme<strong>en</strong>schappelijke klok<br />

del<strong>en</strong>, waardoor ze asynchroon moet<strong>en</strong> werk<strong>en</strong>. Het kan zijn dat we weinig k<strong>en</strong>nis of controle<br />

hebb<strong>en</strong> over het specifieke netwerk tuss<strong>en</strong> de processor<strong>en</strong>; d<strong>en</strong>k bijvoorbeeld aan het Internet.<br />

We sprek<strong>en</strong> dan van gedistribueerde architectur<strong>en</strong>. <strong>Algoritm<strong>en</strong></strong> voor dergelijke architectur<strong>en</strong><br />

zijn belangrijk in het kader van lokale netwerk<strong>en</strong> <strong>en</strong> het Internet.<br />

In de volg<strong>en</strong>de hoofdstukk<strong>en</strong> besprek<strong>en</strong> we deze modell<strong>en</strong> in detail.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


6 Hoofdstuk 1. Inleiding<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


Hoofdstuk 2<br />

Het gedeelde-geheug<strong>en</strong>model<br />

Het gedeelde-geheug<strong>en</strong>model is e<strong>en</strong> natuurlijke uitbreiding van het basis sequ<strong>en</strong>tiële RAMmodel.<br />

In dit model hebb<strong>en</strong> alle processor<strong>en</strong> toegang tot e<strong>en</strong> geme<strong>en</strong>schappelijk geheug<strong>en</strong>,<br />

waardoor ze met elkaar kunn<strong>en</strong> communicer<strong>en</strong>. E<strong>en</strong> speciaal geval is de Parallel Random-Access<br />

Machine (PRAM). In dit hoofdstuk besprek<strong>en</strong> we zowel het algem<strong>en</strong>e gedeelde-geheug<strong>en</strong>model<br />

als het PRAM-model, <strong>en</strong> gaan we ook in op het analyser<strong>en</strong> van de complexiteit van PRAMalgoritm<strong>en</strong>.<br />

7


8 Hoofdstuk 2. Het gedeelde-geheug<strong>en</strong>model<br />

2.1 Het gedeelde-geheug<strong>en</strong>model<br />

In het gedeelde-geheug<strong>en</strong>model hebb<strong>en</strong> meerdere processor<strong>en</strong> toegang tot één <strong>en</strong>kele gedeelde<br />

geheug<strong>en</strong>e<strong>en</strong>heid. Meer bepaald bestaat het gedeelde-geheug<strong>en</strong>model uit e<strong>en</strong> aantal processor<strong>en</strong>,<br />

die elk hun lokaal geheug<strong>en</strong> hebb<strong>en</strong> <strong>en</strong> die elk e<strong>en</strong> lokaal programma kunn<strong>en</strong> uitvoer<strong>en</strong>,<br />

waarbij communicatie tuss<strong>en</strong> de processor<strong>en</strong> gebeurt door het uitwissel<strong>en</strong> van gegev<strong>en</strong>s via e<strong>en</strong><br />

gedeeld geheug<strong>en</strong>. Elke processor wordt e<strong>en</strong>duidig geïd<strong>en</strong>tificeerd door e<strong>en</strong> index, het processornummer<br />

of processor-id g<strong>en</strong>oemd, die lokaal beschikbaar is <strong>en</strong> waarnaar in het programma<br />

van de processor dus kan verwez<strong>en</strong> word<strong>en</strong>. Het gedeelde geheug<strong>en</strong> wordt soms ook het globale<br />

geheug<strong>en</strong> g<strong>en</strong>oemd.<br />

Er zijn twee verschill<strong>en</strong>de manier<strong>en</strong> van werk<strong>en</strong> in het gedeelde-geheug<strong>en</strong>model. De eerste manier<br />

wordt synchroon g<strong>en</strong>oemd <strong>en</strong> hierbij werk<strong>en</strong> alle processor<strong>en</strong> synchroon, m.a.w. gestuurd<br />

door e<strong>en</strong> geme<strong>en</strong>schappelijke klok. Dit model wordt ook de parallel random-access machine<br />

(PRAM) g<strong>en</strong>oemd; we besprek<strong>en</strong> ze verder in de volg<strong>en</strong>de paragraaf.<br />

De tweede manier wordt asynchroon g<strong>en</strong>oemd <strong>en</strong> hierbij werk<strong>en</strong> de processor<strong>en</strong> elk gestuurd<br />

door hun eig<strong>en</strong> klok. In dit model is het de verantwoordelijkheid van de programmeur om waar<br />

nodig voor synchronisatiepunt<strong>en</strong> te zorg<strong>en</strong>. Meer bepaald, wanneer bepaalde data nodig is voor<br />

de berek<strong>en</strong>ing door e<strong>en</strong> bepaalde processor, dan moet de programmeur er voor zorg<strong>en</strong> dat de<br />

correcte waard<strong>en</strong> beschikbaar zijn – merk immers op dat de waarde van e<strong>en</strong> gedeelde variabele<br />

dynamisch wordt bepaald tijd<strong>en</strong>s de uitvoering van de programma’s van de verschill<strong>en</strong>de<br />

processor<strong>en</strong>.<br />

Aangezi<strong>en</strong> elke processor zijn eig<strong>en</strong> lokale programma kan uitvoer<strong>en</strong>, is het asynchrone gedeeldegeheug<strong>en</strong>model<br />

van het type multiple instruction multiple data (MIMD). Dit betek<strong>en</strong>t dat elke<br />

processor e<strong>en</strong> andere instructie kan uitvoer<strong>en</strong>, of e<strong>en</strong> berek<strong>en</strong>ing op andere data kan uitvoer<strong>en</strong>,<br />

<strong>en</strong> dit op elk willekeurig mom<strong>en</strong>t in de uitvoering van het programma. Voor e<strong>en</strong> gegev<strong>en</strong> algoritme,<br />

geeft de omvang van de gegev<strong>en</strong>s die getransfereerd word<strong>en</strong> tuss<strong>en</strong> het gedeelde geheug<strong>en</strong><br />

<strong>en</strong> de lokale geheug<strong>en</strong>s van de processor<strong>en</strong>, e<strong>en</strong> maat voor de communicatie vereist door het<br />

algoritme.<br />

We schrijv<strong>en</strong> parallelle algoritm<strong>en</strong> in het gedeelde-geheug<strong>en</strong>model zoals we dat voor e<strong>en</strong> sequ<strong>en</strong>tieel<br />

algoritme do<strong>en</strong>, met als bijkom<strong>en</strong>de bewerking<strong>en</strong>:<br />

• global read(x,y): het inlez<strong>en</strong> van e<strong>en</strong> gegev<strong>en</strong> x uit het globale geheug<strong>en</strong> naar de lokale<br />

variabele y;<br />

• global write(u,v): het wegschrijv<strong>en</strong> van de inhoud van de lokale variabele u naar de variabele<br />

v in het globale geheug<strong>en</strong>.<br />

In vele gevall<strong>en</strong> zull<strong>en</strong> we echter de volg<strong>en</strong>de verkorte notatie gebruik<strong>en</strong>:<br />

stel c ← a+b<br />

die staat voor:<br />

global read (a,x); global read (b,y)<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


2.1. Het gedeelde-geheug<strong>en</strong>model 9<br />

Algoritme 2.1 Berek<strong>en</strong><strong>en</strong> van matrix-vector-verm<strong>en</strong>igvuldiging<br />

Input: n×n matrix A <strong>en</strong> vector x; aantal processor<strong>en</strong> p met r = n/p geheel; processornummer i;<br />

Output: compon<strong>en</strong>t<strong>en</strong> y (i−1)r+1,...,yir van y = Ax in globale variabele<br />

1: global read (x, z)<br />

2: global read (A (i−1)r+1:ir,1:n, B)<br />

3: Berek<strong>en</strong> w ← Bz<br />

4: global write (w, y (i−1)r+1:ir)<br />

Algoritme 2.2 Berek<strong>en</strong><strong>en</strong> van matrix-vector-verm<strong>en</strong>igvuldiging (met verkorte notatie)<br />

Input: n×n matrix A <strong>en</strong> vector x; aantal processor<strong>en</strong> p met r = n/p geheel; processornummer i;<br />

Output: compon<strong>en</strong>t<strong>en</strong> y (i−1)r+1,...,yir van y = Ax in globale variabele<br />

1: Berek<strong>en</strong> y (i−1)r+1:ir ← A (i−1)r+1:ir,1:nx<br />

stel z ← x+y<br />

global write (z, c)<br />

met a,b,c gedeelde variabel<strong>en</strong>, <strong>en</strong> x,y,z lokale variabel<strong>en</strong>.<br />

Voorbeeld 2.1.1 (Matrix-vector-verm<strong>en</strong>igvuldiging). Beschouw het verm<strong>en</strong>igvuldig<strong>en</strong> van e<strong>en</strong><br />

n×n matrix A met e<strong>en</strong> vector x van orde n, die beid<strong>en</strong> in het gedeelde geheug<strong>en</strong> opgeslag<strong>en</strong> zijn.<br />

Veronderstel dat we over p processor<strong>en</strong> Pi beschikk<strong>en</strong>, met p ≤ n <strong>en</strong> r = n/p geheel, <strong>en</strong> dat we<br />

in het asynchroon model werk<strong>en</strong>.<br />

E<strong>en</strong> e<strong>en</strong>voudig parallel algoritme bestaat in het opsplits<strong>en</strong> van A in p blokk<strong>en</strong> A (i) van r rij<strong>en</strong>,<br />

waarbij elke processor Pi de vector x <strong>en</strong> e<strong>en</strong> blok A (i) uit het gedeeld geheug<strong>en</strong> leest <strong>en</strong> het<br />

product A (i) x berek<strong>en</strong>t. Dit levert r compon<strong>en</strong>t<strong>en</strong> van de resultaatvector.<br />

Algoritme 2.1 geeft de pseudocode voor processor Pi. Merk op dat alle processor<strong>en</strong> in stap 1<br />

tegelijkertijd toegang moet<strong>en</strong> hebb<strong>en</strong> tot de globale variabele x. Daar<strong>en</strong>teg<strong>en</strong> zull<strong>en</strong> twee processor<strong>en</strong><br />

nooit tegelijkertijd naar dezelfde globale geheug<strong>en</strong>plaats prober<strong>en</strong> te schrijv<strong>en</strong>.<br />

Met de eerder vermelde verkorte notatie bekom<strong>en</strong> we de pseudocode zoals getoond in Algoritme<br />

2.2.<br />

De parallelle tijd van dit algoritme is Tp(n) = Θ(n 2 /p). De kost is Cp(n) = pΘ(n 2 /p) = Θ(n 2 ),<br />

hetge<strong>en</strong> precies de tijd van het sequ<strong>en</strong>tiële algoritme is. Het algoritme is dus kost-optimaal.<br />

E<strong>en</strong> belangrijk aspect van dit algoritme is het feit dat de processor<strong>en</strong> hun activiteit<strong>en</strong> niet hoev<strong>en</strong><br />

te synchroniser<strong>en</strong> – dit is te dank<strong>en</strong> aan de manier waarop de berek<strong>en</strong>ing<strong>en</strong> gepartitioneerd<br />

werd<strong>en</strong>. Door de matrix op te splits<strong>en</strong> in blokk<strong>en</strong> van rij<strong>en</strong> zijn de berek<strong>en</strong>ing<strong>en</strong> die door de<br />

verschill<strong>en</strong>de processor<strong>en</strong> gebeur<strong>en</strong>, onafhankelijk van elkaar.<br />

Als we daar<strong>en</strong>teg<strong>en</strong> de matrix zoud<strong>en</strong> opsplits<strong>en</strong> in blokk<strong>en</strong> van kolomm<strong>en</strong>, m.a.w. als A =<br />

(A (1) ,...,A (r) ) <strong>en</strong> x = (x (1) ,...,x (r) ), dan wordt het product y = Ax gegev<strong>en</strong> door y = A (1) x (1) +<br />

···+A (r) x (r) . Elke processor Pi kan dus z (i) = A (i) x (i) berek<strong>en</strong><strong>en</strong>, na het inlez<strong>en</strong> van A (i) <strong>en</strong> x (i)<br />

uit het gedeelde geheug<strong>en</strong>. Maar ge<strong>en</strong> <strong>en</strong>kele processor mag beginn<strong>en</strong> met het berek<strong>en</strong><strong>en</strong> van<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


10 Hoofdstuk 2. Het gedeelde-geheug<strong>en</strong>model<br />

de som z (1) + ···+ z (r) vooraleer gegarandeerd is dat alle processor<strong>en</strong> de berek<strong>en</strong>ing van hun z (i)<br />

beëindigd hebb<strong>en</strong>. Er is m.a.w. e<strong>en</strong> expliciete synchronisatie nodig: het programma van elke<br />

processor moet e<strong>en</strong> synchronisatiepunt bevatt<strong>en</strong> na de berek<strong>en</strong>ing van z (i) = A (i) x (i) , om ervoor<br />

te zorg<strong>en</strong> dat de processor<strong>en</strong> synchroniser<strong>en</strong> vooraleer verder te gaan met de uitvoering van het<br />

programma.<br />

2.2 De Parallel Random-Access Machine (PRAM)<br />

In deze paragraaf conc<strong>en</strong>trer<strong>en</strong> we ons op de Parallel Access-Random Machine (PRAM), die<br />

zowat het standaardmodel voor parallelle algoritm<strong>en</strong> in het gedeelde-geheug<strong>en</strong>model geword<strong>en</strong><br />

is. Dit model veralgeme<strong>en</strong>t de Random-Access Machine (RAM), het model dat voor sequ<strong>en</strong>tiële<br />

algoritm<strong>en</strong> gebruikt wordt. We beschrijv<strong>en</strong> beide modell<strong>en</strong> hier, zonder echter e<strong>en</strong> precieze<br />

formele definitie te gev<strong>en</strong>.<br />

2.2.1 Het PRAM-model<br />

Het RAM-model bestaat uit e<strong>en</strong> c<strong>en</strong>trale verwerkingse<strong>en</strong>heid (CPU) met e<strong>en</strong> random-accessgeheug<strong>en</strong><br />

eraan verbond<strong>en</strong>. De CPU kan rek<strong>en</strong>kundige <strong>en</strong> logische bewerking<strong>en</strong> uitvoer<strong>en</strong> op<br />

e<strong>en</strong> set registers, waarvan de inhoud kan word<strong>en</strong> gelad<strong>en</strong> uit <strong>en</strong> geschrev<strong>en</strong> naar het geheug<strong>en</strong><br />

via random-access-adressering. Elke bewerking vereist één tijdse<strong>en</strong>heid.<br />

Het PRAM-model bestaat uit meerdere RAM-processor<strong>en</strong>, met één extra gedeeld random-accessgeheug<strong>en</strong>,<br />

waartoe alle processor<strong>en</strong> toegang hebb<strong>en</strong>. De processor<strong>en</strong> zijn gesynchroniseerd<br />

door e<strong>en</strong> globale klok, <strong>en</strong> elke processor voert één stap uit tijd<strong>en</strong>s elke klokcyclus.<br />

<strong>Algoritm<strong>en</strong></strong> ontwikkeld in het PRAM-model zijn meestal van het type single instruction multiple<br />

data (SIMD). Dit betek<strong>en</strong>t dat alle processor<strong>en</strong> hetzelfde programma uitvoer<strong>en</strong>, zodanig<br />

dat, op elke tijdse<strong>en</strong>heid, de actieve processor<strong>en</strong> dezelfde instructie uitvoer<strong>en</strong>, doorgaans wel<br />

op verschill<strong>en</strong>de data. Merk echter op dat deze beperking niet inher<strong>en</strong>t door het PRAM-model<br />

zelf opgelegd wordt. Het PRAM-model laat toe om verschill<strong>en</strong>de programma’s op verschill<strong>en</strong>de<br />

processor<strong>en</strong> uit te voer<strong>en</strong>, uiteraard op voorwaarde dat de processor<strong>en</strong> synchroon kunn<strong>en</strong> werk<strong>en</strong>.<br />

Aan de pseudocode voeg<strong>en</strong> we nu ook e<strong>en</strong> parallelle lus toe, die zal toelat<strong>en</strong> om e<strong>en</strong> blok code<br />

in parallel op meerdere processor<strong>en</strong> uit te voer<strong>en</strong>:<br />

for i from 1 to n pardo<br />

{Blok code}<br />

Hierbij wordt het aantal gebruikte processor<strong>en</strong> niet nader gespecificeerd, <strong>en</strong> wordt impliciet verondersteld<br />

dat hun aantal onbeperkt is. De parallelle tijd nodig om deze lus uit te voer<strong>en</strong> is het<br />

maximum van de tijd gebruikt in één van de n stapp<strong>en</strong> (in plaats van de som, zoals het op e<strong>en</strong><br />

sequ<strong>en</strong>tiële machine zou zijn). De kost is het aantal stapp<strong>en</strong> in de lus, maal de kost van één stap.<br />

Voorbeeld 2.2.1. Beschouw het initialiser<strong>en</strong> van elk elem<strong>en</strong>t van e<strong>en</strong> array met e<strong>en</strong> waarde. Gebruik<br />

mak<strong>en</strong>d van p = n processor<strong>en</strong> kan dit met e<strong>en</strong> factor n word<strong>en</strong> versneld:<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


2.2. De Parallel Random-Access Machine (PRAM) 11<br />

Algoritme 2.3 Parallel zoek<strong>en</strong> van e<strong>en</strong> elem<strong>en</strong>t in e<strong>en</strong> niet-gesorteerde array<br />

Input: waarde x, array (a1,...,an), l<strong>en</strong>gte n<br />

Output: true als er e<strong>en</strong> i bestaat waarvoor x = ai, anders false<br />

1: Stel f ← false<br />

2: for i from 1 to n pardo<br />

3: if x = ai th<strong>en</strong><br />

4: Stel f ← true<br />

5: return f<br />

for i from 1 to n pardo<br />

Stel a[i] ← 0<br />

De parallelle tijd van dit stuk code is Tn(n) = Θ(1). De kost is Cn(n) = Θ(n), zodat dit stuk code<br />

kost-optimaal is.<br />

2.2.2 Geheug<strong>en</strong>modell<strong>en</strong> voor PRAM<br />

Voorbeeld 2.2.2. Beschouw het parallel zoek<strong>en</strong> van e<strong>en</strong> elem<strong>en</strong>t in e<strong>en</strong> niet-gesorteerde array.<br />

Het sequ<strong>en</strong>tiële algoritme neemt tijd Θ(n). Algoritme 2.3 geeft de pseudocode voor het parallelle<br />

algoritme. Dit algoritme loopt op n processor<strong>en</strong> in constante parallelle tijd. De kost is Θ(n),<br />

hetge<strong>en</strong> optimaal is.<br />

Merk op dat het algoritme veronderstelt dat de processor<strong>en</strong> gelijktijdig toegang tot het geheug<strong>en</strong><br />

hebb<strong>en</strong>. In eerste instantie wordt de vergelijking x = ai op alle processor<strong>en</strong> gelijktijdig uitgevoerd,<br />

hetge<strong>en</strong> vereist dat alle processor<strong>en</strong> gelijktijdig toegang moet<strong>en</strong> hebb<strong>en</strong> tot de variabele x.<br />

Verder moet<strong>en</strong> alle processor<strong>en</strong> waarvoor de vergelijking x = ai als resultaat true geeft, gelijktijdig<br />

kunn<strong>en</strong> schrijv<strong>en</strong> naar de variabele f .<br />

We kunn<strong>en</strong> er niet zomaar van uitgaan dat gelijktijdige activiteit<strong>en</strong> zoals in Algoritme 2.3 in de<br />

praktijk mogelijk zijn. Het implem<strong>en</strong>ter<strong>en</strong> van gelijktijdig lez<strong>en</strong> <strong>en</strong> schrijv<strong>en</strong> in hardware is e<strong>en</strong><br />

dure aangeleg<strong>en</strong>heid. Bov<strong>en</strong>di<strong>en</strong> kunn<strong>en</strong> in het geval van gelijktijdig schrijv<strong>en</strong> ook logische conflict<strong>en</strong><br />

optred<strong>en</strong>. Immers, wat gebeurt er wanneer meerdere processor<strong>en</strong> verschill<strong>en</strong>de waard<strong>en</strong><br />

in dezelfde geheug<strong>en</strong>plaats prober<strong>en</strong> te schrijv<strong>en</strong>? Om dit soort situaties te modeller<strong>en</strong>, bestaan<br />

er meerdere variant<strong>en</strong> van het PRAM-model:<br />

• Exclusive Read (ER): de waarde van e<strong>en</strong> variabele kan maar door één processor gelijktijdig<br />

word<strong>en</strong> gelez<strong>en</strong>;<br />

• Concurr<strong>en</strong>t Read (CR): de waarde van e<strong>en</strong> variabele kan door meerdere processor<strong>en</strong><br />

gelijktijdig word<strong>en</strong> gelez<strong>en</strong>;<br />

• Exclusive Write (EW): de waarde van e<strong>en</strong> variabele kan maar door één processor gelijktijdig<br />

word<strong>en</strong> geschrev<strong>en</strong>;<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


12 Hoofdstuk 2. Het gedeelde-geheug<strong>en</strong>model<br />

Algoritme 2.4 Parallel zoek<strong>en</strong> van de positie van e<strong>en</strong> elem<strong>en</strong>t in e<strong>en</strong> niet-gesorteerde array<br />

Input: waarde x, array (a1,...,an), l<strong>en</strong>gte n<br />

Output: e<strong>en</strong> index ℓ waarvoor x = aℓ indi<strong>en</strong> deze bestaat, anders −1<br />

1: Stel ℓ ← −1<br />

2: for i from 1 to n pardo<br />

3: if x = ai th<strong>en</strong><br />

4: Stel ℓ ← i<br />

5: return ℓ<br />

• Concurr<strong>en</strong>t Write (CW): meerdere processor<strong>en</strong> kunn<strong>en</strong> gelijktijdig e<strong>en</strong> waarde naar e<strong>en</strong><br />

variabele schrijv<strong>en</strong>.<br />

Op die manier bekom<strong>en</strong> we vier verschill<strong>en</strong>de PRAM-modell<strong>en</strong>:<br />

• EREW: het meest restrictieve model;<br />

• CRCW: het minst restrictieve model;<br />

• CREW: het meest gebruikte gem<strong>en</strong>gde model;<br />

• ERCW: e<strong>en</strong> weinig gebruikt gem<strong>en</strong>gd model.<br />

Voorbeeld 2.2.3. Algoritme 2.3 is e<strong>en</strong> CRCW algoritme. Het is CR omwille van de gelijktijdige<br />

leestoegang tot x <strong>en</strong> het is CW omwille van de gelijktijdige schrijftoegang tot f .<br />

Wanneer we e<strong>en</strong> CW algoritme uitvoer<strong>en</strong>, kan het gebeur<strong>en</strong> dat verscheid<strong>en</strong>e processor<strong>en</strong> verschill<strong>en</strong>de<br />

waard<strong>en</strong> naar dezelfde variabele prober<strong>en</strong> te schrijv<strong>en</strong>.<br />

Voorbeeld 2.2.4. Veronderstel dat we Algoritme 2.3 will<strong>en</strong> aanpass<strong>en</strong> zodanig dat het ook de<br />

plaats teruggeeft waar x gevond<strong>en</strong> werd. Algoritme 2.4 geeft de pseudocode voor dit aangepaste<br />

algoritme. Wanneer x meer dan één keer voorkomt in de array, dan wordt de opdracht ℓ ← i in<br />

parallel door meerdere processor<strong>en</strong> uitgevoerd voor verschill<strong>en</strong>de waard<strong>en</strong> van i.<br />

We onderscheid<strong>en</strong> meerdere modell<strong>en</strong> voor het oploss<strong>en</strong> van schrijfconflict<strong>en</strong>:<br />

• CW in prioriteit: De processor<strong>en</strong> krijg<strong>en</strong> verschill<strong>en</strong>de prioriteit<strong>en</strong> toegek<strong>en</strong>d, <strong>en</strong> bij conflict<br />

is het de processor met de hoogste prioriteit waarvan de waarde in de variabele geschrev<strong>en</strong><br />

wordt.<br />

• CW in overe<strong>en</strong>stemming: Alle processor<strong>en</strong> die e<strong>en</strong> waarde naar e<strong>en</strong> variabele schrijv<strong>en</strong>,<br />

moet<strong>en</strong> dezelfde waarde schrijv<strong>en</strong>, anders faalt de schrijfbewerking.<br />

• willekeurig CW: E<strong>en</strong> willekeurige processor van dieg<strong>en</strong>e die e<strong>en</strong> waarde naar de variabele<br />

will<strong>en</strong> schrijv<strong>en</strong>, schrijft effectief zijn waarde naar de variabele.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


2.2. De Parallel Random-Access Machine (PRAM) 13<br />

Algoritme 2.5 Probleem van cache-coher<strong>en</strong>tie<br />

Stel x ← 0<br />

for i from 1 to n pardo<br />

if i = n th<strong>en</strong><br />

Stel x ← 1<br />

else<br />

Stel ai ← x<br />

Voorbeeld 2.2.5. Merk op dat Algoritme 2.3 e<strong>en</strong> algoritme met “CW in overe<strong>en</strong>stemming” is,<br />

aangezi<strong>en</strong> elke processor dezelfde waarde naar de variabele probeert te schrijv<strong>en</strong>. Algoritme 2.4<br />

daar<strong>en</strong>teg<strong>en</strong> werkt alle<strong>en</strong> in het model “CW in prioriteit” of “willekeurig CW”, aangezi<strong>en</strong> het<br />

verschill<strong>en</strong>de waard<strong>en</strong> naar dezelfde variabele kan prober<strong>en</strong> schrijv<strong>en</strong>; het werkt in het EWmodel<br />

wanneer alle elem<strong>en</strong>t<strong>en</strong> in de array verschill<strong>en</strong>d zijn.<br />

Merk op dat, zelfs wanneer we ons beperk<strong>en</strong> tot het EW-model, er problem<strong>en</strong> kunn<strong>en</strong> zijn met<br />

gelijktijdige leesbewerking<strong>en</strong>.<br />

Voorbeeld 2.2.6. Beschouw de code in Algoritme 2.5. Welke waard<strong>en</strong> bevat de array a na het<br />

uitvoer<strong>en</strong> van deze code? Alhoewel slechts één processor, nl. processor n, naar de variabele x<br />

schrijft, prober<strong>en</strong> alle andere processor<strong>en</strong> wel de waarde van x te lez<strong>en</strong>. Maar wat is de waarde<br />

van x? Wanneer de processor<strong>en</strong> lokale kopieën van x gebruik<strong>en</strong>, dan zal de array null<strong>en</strong> bevatt<strong>en</strong>,<br />

ook al verandert processor n de waarde van x in het globale geheug<strong>en</strong>.<br />

Dit wordt het probleem van cache-coher<strong>en</strong>tie g<strong>en</strong>oemd. Wanneer alle processor<strong>en</strong> de waarde<br />

van e<strong>en</strong> variabele x in het globale geheug<strong>en</strong> gebruik<strong>en</strong>, dan zal het resultaat afhang<strong>en</strong> van de<br />

willekeurige volgorde waarin de processor<strong>en</strong> toegang krijg<strong>en</strong> tot x. Met dergelijke problem<strong>en</strong><br />

moet in de praktijk zeker rek<strong>en</strong>ing word<strong>en</strong> gehoud<strong>en</strong>; in deze cursus vermijd<strong>en</strong> we ze door code<br />

te schrijv<strong>en</strong> die ze vermijdt.<br />

2.2.3 Semigroep-problem<strong>en</strong><br />

Voorbeeld 2.2.7 (Veralgeme<strong>en</strong>de som van e<strong>en</strong> rij getall<strong>en</strong>). Hoe snel kunn<strong>en</strong> we e<strong>en</strong> reeks<br />

getall<strong>en</strong> sommer<strong>en</strong> op e<strong>en</strong> EREW PRAM; m.a.w. gegev<strong>en</strong> e<strong>en</strong> array a van l<strong>en</strong>gte n, hoe snel<br />

kunn<strong>en</strong> we a1 + ···+an berek<strong>en</strong><strong>en</strong>? Dit probleem behoort tot e<strong>en</strong> familie van problem<strong>en</strong> die<br />

allemaal van dezelfde gedaante zijn: voor e<strong>en</strong> gegev<strong>en</strong> binaire associatieve bewerking ⊕ w<strong>en</strong>s<strong>en</strong><br />

we ∑ n i=1 ai te berek<strong>en</strong><strong>en</strong>. Dit probleem is gek<strong>en</strong>d als het semigroep-probleem, aangezi<strong>en</strong> e<strong>en</strong><br />

verzameling elem<strong>en</strong>t<strong>en</strong> sam<strong>en</strong> met e<strong>en</strong> associatieve binaire bewerking e<strong>en</strong> semigroep g<strong>en</strong>oemd<br />

wordt. Andere problem<strong>en</strong> van deze gedaante zijn het berek<strong>en</strong><strong>en</strong> van het maximum, waarbij<br />

⊕ = max, of het product, waarbij ⊕ = ×, van e<strong>en</strong> reeks van n getall<strong>en</strong>.<br />

Eerder zag<strong>en</strong> we reeds twee algoritm<strong>en</strong> voor het bepal<strong>en</strong> van het maximum, het <strong>en</strong>e sequ<strong>en</strong>tieel<br />

<strong>en</strong> het andere parallel. Het sequ<strong>en</strong>tiële algoritme had uitvoeringstijd Θ(n); het parallelle<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


14 Hoofdstuk 2. Het gedeelde-geheug<strong>en</strong>model<br />

Algoritme 2.6 Berek<strong>en</strong><strong>en</strong> van de veralgeme<strong>en</strong>de som van e<strong>en</strong> rij getall<strong>en</strong> (sequ<strong>en</strong>tieel algoritme)<br />

Input: array (a1,...,an), l<strong>en</strong>gte n<br />

Output: de waarde ∑ n i=1 ai<br />

1: Stel s ← a1<br />

2: for i from 2 to n do<br />

3: Stel s ← s ⊕ ai<br />

4: return s<br />

Algoritme 2.7 Berek<strong>en</strong><strong>en</strong> van de veralgeme<strong>en</strong>de som van e<strong>en</strong> rij getall<strong>en</strong> (parallel algoritme)<br />

Input: array a met n = 2 k getall<strong>en</strong>, p = n processor<strong>en</strong>, processornummer i<br />

Output: som s = ∑ n i=1 ai<br />

1: Stel bi ← ai<br />

2: for h from 1 to log 2 n do<br />

3: if i ≤ n/2 h th<strong>en</strong><br />

4: Stel bi ← b2i−1 ⊕ b2i<br />

5: if i = 1 th<strong>en</strong><br />

6: Stel s ← b1<br />

algoritme had uitvoeringstijd Θ(logn) <strong>en</strong> kost Θ(nlogn). Beide algoritm<strong>en</strong> kunn<strong>en</strong> word<strong>en</strong> veralgeme<strong>en</strong>d<br />

voor e<strong>en</strong> willekeurige binaire associatieve bewerking ⊕ die in constante tijd kan<br />

gebeur<strong>en</strong>.<br />

Algoritme 2.6 geeft de pseudocode voor het sequ<strong>en</strong>tiële algoritme. Voor het parallelliser<strong>en</strong> van<br />

dit algoritme gebruik<strong>en</strong> we dezelfde strategie als voor het parallelliser<strong>en</strong> van Algoritme 1.1.<br />

Veronderstel dat we e<strong>en</strong> PRAM met p = n processor<strong>en</strong> P1,...,Pn hebb<strong>en</strong>.<br />

Elke processor berek<strong>en</strong>t de (veralgeme<strong>en</strong>de) som van twee getall<strong>en</strong>; deze somm<strong>en</strong> word<strong>en</strong> weer<br />

twee aan twee opgeteld, elk door andere processor; dit proces wordt herhaald totdat de totale<br />

som bekom<strong>en</strong> is. Algoritme 2.7 geeft de pseudocode voor processor Pi.<br />

Merk op dat het PRAM-model synchroon werkt, m.a.w. in elke tijdse<strong>en</strong>heid kan de processor<br />

ofwel e<strong>en</strong> opdracht uitvoer<strong>en</strong>, ofwel niets do<strong>en</strong>. Bijvoorbeeld, de voorwaarde van de if-opdracht<br />

in lijn 3 van het parallelle algoritme is slechts op e<strong>en</strong> beperkt aantal processor<strong>en</strong> voldaan, zodat<br />

de andere processor<strong>en</strong> niets do<strong>en</strong> tijd<strong>en</strong>s de tijdse<strong>en</strong>heid waarop lijn 4 uitgevoerd wordt.<br />

Dit algoritme heeft parallelle tijd Tp(n) = Θ(logn) <strong>en</strong> kost Cp(n) = pΘ(logn) = Θ(nlogn).<br />

Aangezi<strong>en</strong> dit probleem in sequ<strong>en</strong>tiële tijd T ∗ (n) = Θ(n) kan opgelost word<strong>en</strong>, is het parallelle<br />

algoritme dus niet kost-optimaal.<br />

2.2.4 Kost-optimaliser<strong>en</strong> van PRAM-algoritm<strong>en</strong><br />

Voorbeeld 2.2.8 (Veralgeme<strong>en</strong>de som van e<strong>en</strong> rij getall<strong>en</strong>). Om de kost van Algoritme 2.7 te<br />

verbeter<strong>en</strong> moet<strong>en</strong> we ofwel de parallelle uitvoeringstijd ofwel het aantal processor<strong>en</strong> verminde-<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


2.3. Het werk-tijd-paradigma 15<br />

r<strong>en</strong>. Dit laatste houdt in dat we e<strong>en</strong> waarde voor p zoek<strong>en</strong> waarvoor Cp(n) = Θ(T ∗ (n)), m.a.w.<br />

waarvoor p × Θ(logn) = Θ(n). Dus p = Θ( n<br />

logn ).<br />

In het aangepaste algoritme berek<strong>en</strong>t elke processor dan (sequ<strong>en</strong>tieel) de sommatie van Θ(logn)<br />

elem<strong>en</strong>t<strong>en</strong>, hetge<strong>en</strong> parallelle tijd Θ(logn) kost. Vervolg<strong>en</strong>s wordt de som van deze p deelsomm<strong>en</strong><br />

in parallel berek<strong>en</strong>d (analoog aan het eerdere algoritme). Dit kost parallelle tijd Θ(log p) =<br />

Θ(log( n<br />

logn ))) = Θ(logn). De totale parallelle tijd voor het aangepaste algoritme is dus Tp(n) =<br />

Θ(logn).<br />

De kost is Cp(n) = Θ( n<br />

logn )×Θ(logn) = Θ(n) = Θ(T ∗ (n)), m.a.w. het algoritme is kost-optimaal.<br />

Merk op dat de optimale Θ(logn) tijd uit het eerdere algoritme behoud<strong>en</strong> blijft.<br />

2.3 Het werk-tijd-paradigma<br />

De beschrijving van e<strong>en</strong> parallel algoritme bevat doorgaans talrijke details, waardoor soms de<br />

ess<strong>en</strong>tie van het algoritme minder duidelijk wordt. Het PRAM-model is reeds e<strong>en</strong> manier om<br />

details bij het het beschrijv<strong>en</strong> van parallelle algoritm<strong>en</strong> te vere<strong>en</strong>voudig<strong>en</strong>. In deze pararaaf<br />

besprek<strong>en</strong> we e<strong>en</strong> paradigma dat hierbij nog meer zal help<strong>en</strong>.<br />

Het werk-tijd-paradigma (WT-paradigma) geeft informele richtlijn<strong>en</strong> voor e<strong>en</strong> beschrijving<br />

van parallelle algoritm<strong>en</strong> in twee niveau’s met e<strong>en</strong> top-down-b<strong>en</strong>adering. Het bov<strong>en</strong>ste niveau<br />

is e<strong>en</strong> pres<strong>en</strong>tati<strong>en</strong>iveau <strong>en</strong> vermijdt specifieke details van het algoritme. Het onderste niveau<br />

volgt e<strong>en</strong> algeme<strong>en</strong> scheduling-principe <strong>en</strong> resulteert in e<strong>en</strong> volledige PRAM-beschrijving van<br />

het algoritme.<br />

2.3.1 Het WT-pres<strong>en</strong>tati<strong>en</strong>iveau<br />

Het WT-pres<strong>en</strong>tati<strong>en</strong>iveau levert e<strong>en</strong> abstracte beschrijving van e<strong>en</strong> parallel algoritme als e<strong>en</strong><br />

reeks parallelle stapp<strong>en</strong>. Het algoritme bestaat dan uit e<strong>en</strong> e<strong>en</strong> sequ<strong>en</strong>tie van tijdse<strong>en</strong>hed<strong>en</strong>,<br />

waarbij elke tijdse<strong>en</strong>heid bestaat uit e<strong>en</strong> willekeurig aantal parallelle bewerking<strong>en</strong>. Er word<strong>en</strong><br />

hier ge<strong>en</strong> details gegev<strong>en</strong> over het aantal processor<strong>en</strong>, de werkverdeling over de verschill<strong>en</strong>de<br />

processor<strong>en</strong>, e.d. In deze beschrijving wordt de eerder vermelde parallelle for-lus gebruikt.<br />

De complexiteit van e<strong>en</strong> algoritme in WT-pres<strong>en</strong>tatie wordt beschrev<strong>en</strong> door de parallelle uitvoeringstijd<br />

T(n) die het aantal tijdse<strong>en</strong>hed<strong>en</strong> voorstelt, <strong>en</strong> het werk W(n) dat bepaald wordt<br />

door het totale aantal uitgevoerde bewerking<strong>en</strong>.<br />

Merk op dat e<strong>en</strong> parallel algoritme met werk W(n) kan omgezet word<strong>en</strong> in e<strong>en</strong> sequ<strong>en</strong>tieel algoritme<br />

met uitvoeringstijd Θ(W(n)). We noem<strong>en</strong> e<strong>en</strong> algoritme werk-optimaal als W(n) =<br />

Θ(T ∗ (n)).<br />

Voorbeeld 2.3.1 (Veralgeme<strong>en</strong>de som van e<strong>en</strong> rij getall<strong>en</strong>). Beschouw<strong>en</strong> we opnieuw het probleem<br />

van het sommer<strong>en</strong> van e<strong>en</strong> rij getall<strong>en</strong>. Gebruik mak<strong>en</strong>d van de parallelle for-lus kan<br />

Algoritme 2.7 ook beschrev<strong>en</strong> word<strong>en</strong> met de pseudocode uit Algoritme 2.8.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


16 Hoofdstuk 2. Het gedeelde-geheug<strong>en</strong>model<br />

Algoritme 2.8 Berek<strong>en</strong><strong>en</strong> van de veralgeme<strong>en</strong>de som van e<strong>en</strong> rij getall<strong>en</strong> (WT-pres<strong>en</strong>tatie)<br />

Input: array a met n = 2 k getall<strong>en</strong><br />

Output: som s = ∑ n i=1 ai<br />

1: for i from 1 to n pardo<br />

2: Stel bi ← ai<br />

3: for h from 1 to log 2 n do<br />

4: for i from 1 to n/2 h pardo<br />

5: Stel bi ← b2i−1 ⊕ b2i<br />

6: Stel s ← b1<br />

Het aantal tijdse<strong>en</strong>hed<strong>en</strong> nodig voor dit algoritme is log 2 n+2, zodat de uitvoeringstijd T(n) =<br />

Θ(logn). Het werk wordt bepaald door<br />

Het algoritme is dus werk-optimaal.<br />

log 2n W(n) = n+<br />

∑<br />

h=1<br />

2.3.2 Het WT-scheduling-niveau<br />

n<br />

+ 1 = Θ(n).<br />

2h In het WT-scheduling-niveau wordt de volledige PRAM-specificatie van e<strong>en</strong> algoritme (in WTpres<strong>en</strong>tatie)<br />

uitgewerkt, tot alle implem<strong>en</strong>tatiedetails met p processor<strong>en</strong>.<br />

Door gebruik te mak<strong>en</strong> van e<strong>en</strong> algeme<strong>en</strong> scheduling-principe bekomt m<strong>en</strong> voor e<strong>en</strong> algoritme<br />

in WT-specificatie met T(n) tijdse<strong>en</strong>hed<strong>en</strong> <strong>en</strong> W(n) werk doorgaans e<strong>en</strong> p-PRAM-algoritme met<br />

parallelle uitvoeringstijd Tp(n) ≤ ⌊ W(n)<br />

p ⌋+T(n) <strong>en</strong> kost Cp(n) = p×Tp(n) = O(W(n)+ pT(n)).<br />

Noter<strong>en</strong> we daartoe door Wi(n) het aantal bewerking<strong>en</strong> in tijdse<strong>en</strong>heid i, voor 1 ≤ i ≤ T(n).<br />

Deze Wi(n) bewerking<strong>en</strong> word<strong>en</strong> in ≤ ⌈ Wi(n)<br />

p ⌉ parallelle stapp<strong>en</strong> gesimuleerd op p processor<strong>en</strong>,<br />

voor alle 1 ≤ i ≤ T(n). Dit geeft e<strong>en</strong> p-PRAM-algoritme waarbij het aantal parallelle stapp<strong>en</strong><br />

≤ ∑i⌈ Wi(n) Wi(n)<br />

p ⌉ ≤ ∑i(⌊ p ⌋+1) ≤ ⌊W(n)<br />

p ⌋+T(n).<br />

Om deze algem<strong>en</strong>e werkwijze te implem<strong>en</strong>ter<strong>en</strong> moet<strong>en</strong> eerst <strong>en</strong> vooral de Wi(n), ∀i, berek<strong>en</strong>d<br />

word<strong>en</strong>, hetge<strong>en</strong> meestal triviaal is. Vervolg<strong>en</strong>s moet<strong>en</strong> de bewerking<strong>en</strong> toegek<strong>en</strong>d word<strong>en</strong> aan<br />

processor<strong>en</strong>, m.a.w. voor elke parallelle stap <strong>en</strong> voor elke processor Pk moet nagegaan word<strong>en</strong> of<br />

de processor actief is, <strong>en</strong> zo ja, welke bewerking<strong>en</strong> hij moet uitvoer<strong>en</strong><br />

Voorbeeld 2.3.2 (Veralgeme<strong>en</strong>de som van e<strong>en</strong> rij getall<strong>en</strong>). We beschouw<strong>en</strong> de WT-scheduling<br />

van Algoritme 2.8. Onderstel dat we beschikk<strong>en</strong> over e<strong>en</strong> PRAM met p = 2 q ≤ n = 2 k processor<strong>en</strong><br />

P1,...,Pp, <strong>en</strong> zij ℓ = n/p = 2 k−q . De rij a wordt verdeeld in p deelrij<strong>en</strong> van elk ℓ elem<strong>en</strong>t<strong>en</strong>,<br />

waarbij processor Pr deelrij a ℓ(r−1)+1,...,aℓr behandelt.<br />

Voor elke waarde van h wordt de berek<strong>en</strong>ing van de elem<strong>en</strong>t<strong>en</strong> bi zo gelijkmatig mogelijk verdeeld<br />

over de p processor<strong>en</strong>. Merk op dat het aantal mogelijke parallelle bewerking<strong>en</strong> gegev<strong>en</strong><br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


2.3. Het werk-tijd-paradigma 17<br />

Algoritme 2.9 Berek<strong>en</strong><strong>en</strong> van de veralgeme<strong>en</strong>de som van e<strong>en</strong> rij getall<strong>en</strong> (WT-scheduling)<br />

Input: array a met n = 2 k getall<strong>en</strong>; p = 2 q ≤ n processor<strong>en</strong>; ℓ = n/p; processornummer r<br />

Output: som s = ∑ n i=1 ai<br />

1: for j = 1 to ℓ do<br />

2: Stel b ℓ(r−1)+ j ← a ℓ(r−1)+ j<br />

3: for h from 1 to log 2 n do<br />

4: if k − h − q ≥ 0 th<strong>en</strong><br />

5: for j from 2 k−h−q (r − 1)+1 to 2 k−h−q r do<br />

6: Stel b j ← b2 j−1 ⊕ b2 j<br />

7: else if r ≤ 2 k−h th<strong>en</strong><br />

8: Stel br ← b2r−1 ⊕ b2r<br />

9: if r = 1 th<strong>en</strong><br />

10: Stel s ← b1<br />

wordt door n/2 h = 2 k−h . Als 2 k−h ≥ p = 2 q , dus als k − h − q ≥ 0, dan kunn<strong>en</strong> de bewerking<strong>en</strong><br />

gelijkmatig verdeeld word<strong>en</strong> over p processor<strong>en</strong>. Anders word<strong>en</strong> ze verdeeld over de 2 k−h<br />

“eerste” processor<strong>en</strong>. Algoritme 2.9 geeft de pseudocode voor dit PRAM-algoritme.<br />

De parallelle uitvoeringstijd van dit algoritme wordt gegev<strong>en</strong> door<br />

<br />

n<br />

Tp(n) = O<br />

p +<br />

log 2n ⌈ n<br />

2hp ⌉<br />

<br />

n<br />

= O + logn .<br />

p<br />

∑<br />

h=1<br />

<br />

W(n)<br />

Merk op dat Tp(n) = O p + T(n) , zoals voorspeld door het WT-scheduling-principe. De<br />

kost van dit algoritme is Cp(n) = p × Tp(n) = O(n+ plogn).<br />

In het vervolg zull<strong>en</strong> we PRAM-algoritm<strong>en</strong> doorgaans <strong>en</strong>kel in hun WT-pres<strong>en</strong>tatie besprek<strong>en</strong>.<br />

Het weglat<strong>en</strong> van de details van het WT-scheduling niveau wordt gemotiveerd door het feit dat<br />

deze uitwerking doorgaans ge<strong>en</strong> nieuwe ideeën vereist, maar eerder bestaat uit programmeerdetails<br />

die de beschrijving van het algoritme veel ingewikkelder mak<strong>en</strong>.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


18 Hoofdstuk 2. Het gedeelde-geheug<strong>en</strong>model<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


Hoofdstuk 3<br />

Het netwerkmodel<br />

In dit hoofdstuk besprek<strong>en</strong> we parallelle computers die kunn<strong>en</strong> gemodelleerd word<strong>en</strong> als e<strong>en</strong><br />

netwerk. We behandel<strong>en</strong> zowel de circuits, die bestaan uit processor<strong>en</strong> met zeer beperkte mogelijkhed<strong>en</strong>,<br />

als de meer algem<strong>en</strong>e interconnecti<strong>en</strong>etwerk<strong>en</strong>. We zi<strong>en</strong> welke netwerktopologieën<br />

interessant kunn<strong>en</strong> zijn voor het parallel oploss<strong>en</strong> van problem<strong>en</strong>. Bov<strong>en</strong>di<strong>en</strong> bestuder<strong>en</strong> we ook<br />

<strong>en</strong>kele standaard communicatiepatron<strong>en</strong> in de veelgebruikte interconnecti<strong>en</strong>etwerk<strong>en</strong>.<br />

19


20 Hoofdstuk 3. Het netwerkmodel<br />

3.1 Het netwerkmodel<br />

E<strong>en</strong> netwerk kan beschouwd word<strong>en</strong> als e<strong>en</strong> graaf G = (V,E), waarbij elke top vi ∈ V e<strong>en</strong><br />

processor Pi voorstelt, <strong>en</strong> elke boog (vi,vj) ∈ E e<strong>en</strong> communicatielink tuss<strong>en</strong> Pi <strong>en</strong> Pj voorstelt.<br />

Elke processor heeft zijn eig<strong>en</strong> lokale geheug<strong>en</strong>, <strong>en</strong> er is ge<strong>en</strong> geme<strong>en</strong>schappelijk geheug<strong>en</strong><br />

beschikbaar.<br />

Communicatie tuss<strong>en</strong> de processor<strong>en</strong> gebeurt via de beschikbare communicatielinks. In de pseudocode<br />

gebruik<strong>en</strong> we dan ook volg<strong>en</strong>de bijkom<strong>en</strong>de opdracht<strong>en</strong> voor het aangev<strong>en</strong> van communicatie:<br />

• s<strong>en</strong>d(X,i): De processor z<strong>en</strong>dt e<strong>en</strong> kopie van data X naar processor Pi <strong>en</strong> gaat daarna<br />

onmiddellijk verder met het uitvoer<strong>en</strong> van de volg<strong>en</strong>de instructie.<br />

• receive(Y , j): De processor schort de uitvoering van zijn programma op totdat data van<br />

processor Pj ontvang<strong>en</strong> is. Daarna slaat hij deze data op in e<strong>en</strong> variabele Y <strong>en</strong> gaat dan<br />

verder met de uitvoering van zijn programma.<br />

Ook in het netwerkmodel beschouw<strong>en</strong> we twee verschill<strong>en</strong>de manier<strong>en</strong> van werk<strong>en</strong>, nl. synchroon<br />

<strong>en</strong> asynchroon. Meest gebruikt is echter het asynchrone netwerkmodel.<br />

De processor<strong>en</strong> in e<strong>en</strong> asynchroon netwerk coördiner<strong>en</strong> hun activiteit<strong>en</strong> door boodschapp<strong>en</strong> uit<br />

te wissel<strong>en</strong>; dit schema wordt het message-passing model g<strong>en</strong>oemd.<br />

Merk echter op dat twee communicer<strong>en</strong>de processor<strong>en</strong> niet noodzakelijk rechtstreeks verbond<strong>en</strong><br />

zijn. Het proces van het bezorg<strong>en</strong> van e<strong>en</strong> bericht van de afz<strong>en</strong>der naar de bestemmeling wordt<br />

routing g<strong>en</strong>oemd.<br />

3.2 Circuits <strong>en</strong> systolische algoritm<strong>en</strong><br />

E<strong>en</strong> voorbeeld van parallelle algoritm<strong>en</strong> in het synchrone netwerkmodel zijn de zgn. systolische<br />

algoritm<strong>en</strong> die werk<strong>en</strong> op circuits.<br />

Circuits bestaan uit processor<strong>en</strong> met beperkte mogelijkhed<strong>en</strong>. Dergelijke processor wordt e<strong>en</strong><br />

poort g<strong>en</strong>oemd. E<strong>en</strong> poort heeft inputkanal<strong>en</strong>, waarop e<strong>en</strong> e<strong>en</strong>voudige bewerking gebeurt, waarvan<br />

het resultaat naar de outputkanal<strong>en</strong> gestuurd wordt. Voorbeeld<strong>en</strong> van circuits zijn de sorteernetwerk<strong>en</strong><br />

die we in Hoofdstuk 5 zull<strong>en</strong> besprek<strong>en</strong>, <strong>en</strong> de systolische netwerk<strong>en</strong>, waarvan we<br />

hier e<strong>en</strong> toepassing behandel<strong>en</strong>.<br />

In e<strong>en</strong> systolisch algoritme werk<strong>en</strong> de processor<strong>en</strong> volledig synchroon. Per tijdse<strong>en</strong>heid ontvangt<br />

elke processor gegev<strong>en</strong>s van bepaalde bur<strong>en</strong>, op deze gegev<strong>en</strong>s doet hij e<strong>en</strong> lokale berek<strong>en</strong>ing,<br />

<strong>en</strong> vervolg<strong>en</strong>s stuurt hij gegev<strong>en</strong>s door naar bepaalde bur<strong>en</strong>.<br />

Voorbeeld 3.2.1 (Matrixverm<strong>en</strong>igvuldiging). We beschouw<strong>en</strong> het berek<strong>en</strong><strong>en</strong> van het product<br />

C = AB van twee n×n matrices A <strong>en</strong> B. Veronderstel dat we e<strong>en</strong> tweedim<strong>en</strong>sionaal n×n rooster<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


3.3. Interconnecti<strong>en</strong>etwerk<strong>en</strong> 21<br />

van poort<strong>en</strong> ter beschikking hebb<strong>en</strong>. Elke processor Pi, j heeft twee inputkanal<strong>en</strong>, kom<strong>en</strong>de van<br />

zijn linkerbuur Pi−1, j <strong>en</strong> van zijn bov<strong>en</strong>buur Pi, j−1. Verder heeft Pi, j twee outputkanal<strong>en</strong>, gaande<br />

naar zijn rechterbuur Pi+1, j <strong>en</strong> zijn onderbuur Pi, j+1.<br />

E<strong>en</strong> mogelijk systolisch algoritme bestaat erin de rij<strong>en</strong> van A synchroon, maar met e<strong>en</strong> verschuiving,<br />

van links naar rechts door de rij<strong>en</strong> van het rooster te stur<strong>en</strong>, terwijl de kolomm<strong>en</strong> van B<br />

synchroon, <strong>en</strong> ook met verschuiving, van bov<strong>en</strong> naar onder door de kolomm<strong>en</strong> van het rooster<br />

gestuurd word<strong>en</strong>. Wanneer processor Pi, j de inputwaard<strong>en</strong> Ai,ℓ <strong>en</strong> Bℓ, j ontvang<strong>en</strong> heeft, dan berek<strong>en</strong>t<br />

hij Ci, j ← Ci, j +Ai,ℓBℓ, j, <strong>en</strong> stuurt vervolg<strong>en</strong>s de inputwaarde Ai,ℓ door naar zijn rechterbuur<br />

<strong>en</strong> de inputwaarde Bℓ, j naar zijn onderbuur. Na O(n) dergelijke stapp<strong>en</strong> bevat elke processor Pi, j<br />

het correcte matrixelem<strong>en</strong>t Ci, j van het matrixproduct C = AB.<br />

Het aantal processor<strong>en</strong> is p = n 2 . De parallelle uitvoeringstijd van dit algoritme is Tp(n) = Θ(n).<br />

De kost van dit algoritme is Cp(n) = Θ(n 3 ).<br />

3.3 Interconnecti<strong>en</strong>etwerk<strong>en</strong><br />

3.3.1 Netwerktopologieën<br />

E<strong>en</strong> verzameling processor<strong>en</strong> met voorgeschrev<strong>en</strong> statische communicatiekanal<strong>en</strong> wordt e<strong>en</strong> interconnecti<strong>en</strong>etwerk<br />

g<strong>en</strong>oemd. Zoals reeds vermeld kunn<strong>en</strong> we de communicatiekanal<strong>en</strong> voorstell<strong>en</strong><br />

als bog<strong>en</strong> in e<strong>en</strong> graaf waarvan de topp<strong>en</strong> de processor<strong>en</strong> zijn. We sprek<strong>en</strong> van netwerktopologieën<br />

om bepaalde families van graf<strong>en</strong> aan te duid<strong>en</strong>.<br />

Voor het evaluer<strong>en</strong> van netwerktopologieën word<strong>en</strong> e<strong>en</strong> aantal parameters gebruikt. De grootste<br />

afstand tuss<strong>en</strong> twee processor<strong>en</strong> in het netwerk noem<strong>en</strong> we de diameter van het netwerk.<br />

E<strong>en</strong> kleine diameter in het netwerk betek<strong>en</strong>t doorgaans snelle communicatie. De graad van<br />

e<strong>en</strong> processor is het aantal communicatiekanal<strong>en</strong> van de processor<strong>en</strong>; de grootste graad van e<strong>en</strong><br />

processor in het netwerk wordt ook wel de graad van het netwerk g<strong>en</strong>oemd. De connectiviteit<br />

van het netwerk is het kleinste aantal topp<strong>en</strong> of bog<strong>en</strong> waarvan de verwijdering het netwerk<br />

niet-sam<strong>en</strong>hang<strong>en</strong>d maakt.<br />

Bijvoorbeeld, we kunn<strong>en</strong> de processor<strong>en</strong> verbind<strong>en</strong> in de stertopologie, waarbij alle processor<strong>en</strong><br />

verbond<strong>en</strong> zijn met één c<strong>en</strong>trale processor. In de stertopologie is elke processor hoogst<strong>en</strong>s twee<br />

stapp<strong>en</strong> verwijderd van elke andere processor. De stertopologie heeft diameter 2. Bov<strong>en</strong>di<strong>en</strong><br />

gebruikt de stertopologie slechts n communicatiekanal<strong>en</strong> om n + 1 processor<strong>en</strong> te verbind<strong>en</strong>,<br />

hetge<strong>en</strong> het minimum is.<br />

E<strong>en</strong> negatief punt is dat de stertopologie e<strong>en</strong> zeer lage connectiviteit heeft: het uitvall<strong>en</strong> van één<br />

<strong>en</strong>kele processor (nl. de c<strong>en</strong>trale processor) verbreekt het ganse netwerk <strong>en</strong> maakt communicatie<br />

tuss<strong>en</strong> alle andere processor<strong>en</strong> onmogelijk. Dergelijk gedrag is in vele situaties ontoelaatbaar;<br />

d<strong>en</strong>k bijvoorbeeld aan het uitvall<strong>en</strong> van het Internet door het uitvall<strong>en</strong> van één <strong>en</strong>kele machine.<br />

E<strong>en</strong> ander probleem ontstaat wanneer teveel processor<strong>en</strong> terzelfdertijd prober<strong>en</strong> te communicer<strong>en</strong>.<br />

Aangezi<strong>en</strong> alle communicatie door de c<strong>en</strong>trale processor moet gebeur<strong>en</strong>, is de snelheid<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


22 Hoofdstuk 3. Het netwerkmodel<br />

van deze <strong>en</strong>e processor e<strong>en</strong> bottl<strong>en</strong>eck voor het ganse netwerk. M.a.w. topp<strong>en</strong> van grote graad<br />

(processor<strong>en</strong> met veel incid<strong>en</strong>te communicatiekanal<strong>en</strong>) kan ook e<strong>en</strong> nadeel zijn.<br />

Als we de connectiviteit will<strong>en</strong> verbeter<strong>en</strong>, moet<strong>en</strong> we communicatiekanal<strong>en</strong> toevoeg<strong>en</strong>. Wanneer<br />

we alle mogelijke verbinding<strong>en</strong> toevoeg<strong>en</strong>, dan bekom<strong>en</strong> we e<strong>en</strong> topologie die correspondeert<br />

met de complete graaf Kn.<br />

E<strong>en</strong> voordeel van Kn is zijn kleine diameter van 1 <strong>en</strong> dus het ontbrek<strong>en</strong> van <strong>en</strong>ige bottl<strong>en</strong>eck<br />

in de communicatie tuss<strong>en</strong> processor<strong>en</strong>. We betal<strong>en</strong> echter e<strong>en</strong> hoge prijs voor dit netwerk: we<br />

gebruik<strong>en</strong> n(n − 1)/2 communicatiekanal<strong>en</strong> om n processor<strong>en</strong> te verbind<strong>en</strong>.<br />

Het is dus nuttig om naar intermediaire architectur<strong>en</strong> te kijk<strong>en</strong>, zoals bom<strong>en</strong>, rij<strong>en</strong>, roosters <strong>en</strong><br />

hyperkubuss<strong>en</strong>.<br />

De stertopologie is e<strong>en</strong> voorbeeld van e<strong>en</strong> boom, <strong>en</strong> netwerk<strong>en</strong> word<strong>en</strong> soms op natuurlijke wijze<br />

op bom<strong>en</strong> gebaseerd. D<strong>en</strong>k bijvoorbeeld aan de manier waarop we het maximum berek<strong>en</strong>d<strong>en</strong><br />

door gebruik te mak<strong>en</strong> van e<strong>en</strong> binaire boom.<br />

Bom<strong>en</strong> zijn sam<strong>en</strong>hang<strong>en</strong>d met e<strong>en</strong> minimum aan bog<strong>en</strong>, hetge<strong>en</strong> betek<strong>en</strong>t dat het verwijder<strong>en</strong><br />

van e<strong>en</strong> top of e<strong>en</strong> boog h<strong>en</strong> onmiddellijk niet-sam<strong>en</strong>hang<strong>en</strong>d maakt.<br />

Positief aan bom<strong>en</strong> is dat er bom<strong>en</strong> bestaan met topp<strong>en</strong> van kleine graad <strong>en</strong> met kleine diameter.<br />

Bijvoorbeeld, e<strong>en</strong> binaire boom, waar elke top hoogst<strong>en</strong>s graad 3 heeft, laat toe om n topp<strong>en</strong> te<br />

verbind<strong>en</strong> met e<strong>en</strong> diameter van 2log 2 n.<br />

3.3.2 Rij <strong>en</strong> ring<br />

E<strong>en</strong> andere manier om n processor<strong>en</strong> te verbind<strong>en</strong> met e<strong>en</strong> klein aantal verbinding<strong>en</strong>, is de rij<br />

van processor<strong>en</strong>, <strong>en</strong> de variant van de ring van processor<strong>en</strong>. Beid<strong>en</strong> kom<strong>en</strong> in de praktijk voor;<br />

bijvoorbeeld e<strong>en</strong> Ethernet is e<strong>en</strong> rijtopologie, terwijl e<strong>en</strong> ‘tok<strong>en</strong> ring’ e<strong>en</strong> ringtopologie is.<br />

E<strong>en</strong> rij van processor<strong>en</strong> bestaat uit p processor<strong>en</strong> P1,...,Pp die in e<strong>en</strong> lineaire rij verbond<strong>en</strong><br />

zijn, m.a.w. Pi is verbond<strong>en</strong> met de voorgaande processor Pi−1 <strong>en</strong> met de volg<strong>en</strong>de processor Pi+1<br />

(wanneer die bestaan). De diameter van dergelijke rij is p − 1 <strong>en</strong> zijn maximumgraad is 2.<br />

E<strong>en</strong> ring van processor<strong>en</strong> is e<strong>en</strong> lineaire rij van processor<strong>en</strong> waarbij de eerste processor P1 ook<br />

met de laatste processor Pp rechtstreeks verbond<strong>en</strong> is. De diameter van de ring is ⌊p/2⌋ <strong>en</strong> zijn<br />

maximumgraad is 2.<br />

De connectiviteit van de ringtopologie is lichtjes hoger dan die van de stertopologie <strong>en</strong> de rijtopologie.<br />

Na het uitvall<strong>en</strong> van e<strong>en</strong> processor in e<strong>en</strong> ring, is het netwerk nog steeds sam<strong>en</strong>hang<strong>en</strong>d,<br />

m.a.w. elke processor kan communicer<strong>en</strong> met elke andere processor. Wanneer echter twee nietnaburige<br />

processor<strong>en</strong> uitvall<strong>en</strong>, dan is het netwerk niet meer sam<strong>en</strong>hang<strong>en</strong>d.<br />

E<strong>en</strong> nadeel van zowel rij als ring is het feit dat hun diameter Θ(n) is, waardoor ze <strong>en</strong>kel bruikbaar<br />

zijn voor kleine waard<strong>en</strong> van n, zoals in ‘local area’ netwerk<strong>en</strong> (LAN).<br />

Voorbeeld 3.3.1 (Matrix-vector-verm<strong>en</strong>igvuldiging). Zij gegev<strong>en</strong> e<strong>en</strong> n × n matrix A <strong>en</strong> e<strong>en</strong><br />

vector x van orde n. We behandel<strong>en</strong> het berek<strong>en</strong><strong>en</strong> van het matrix-vector-product y = Ax op e<strong>en</strong><br />

ring van p processor<strong>en</strong>, waarbij p ≤ n. Onderstel dat p e<strong>en</strong> deler van n is, <strong>en</strong> stel r = n/p.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


3.3. Interconnecti<strong>en</strong>etwerk<strong>en</strong> 23<br />

Algoritme 3.1 Berek<strong>en</strong><strong>en</strong> van matrix-vector-verm<strong>en</strong>igvuldiging op ring<br />

Input: processornummer i; aantal processor<strong>en</strong> p; r = n/p geheel; deelmatrix B = A (i) =<br />

A 1:n,(i−1)r+1:ir; deelvector w = x (i) = x (i−1)r+1:ir<br />

Output: Pi berek<strong>en</strong>t A (1) x (1) + ··· + A (i) x (i) , <strong>en</strong> geeft dit resultaat naar rechts door; na afloop<br />

bevat P1 het resultaat Ax<br />

1: Berek<strong>en</strong> z ← Bw<br />

2: if i = 1 th<strong>en</strong><br />

3: Stel y ← 0<br />

4: else<br />

5: receive (y, links)<br />

6: Stel y ← y+z<br />

7: s<strong>en</strong>d (y, rechts)<br />

8: if i = 1 th<strong>en</strong><br />

9: receive (y, links)<br />

We splits<strong>en</strong> A op in p blokk<strong>en</strong> A (i) van grootte n × r, <strong>en</strong> x in p stukk<strong>en</strong> x (i) van l<strong>en</strong>gte r. Elke<br />

processor Pi berek<strong>en</strong>t z (i) = A (i) x (i) , voor 1 ≤ i ≤ p. Vervolg<strong>en</strong>s bepal<strong>en</strong> we de som z (1) + ···+<br />

z (p) , door de partiële somm<strong>en</strong> in wijzerzin doorhe<strong>en</strong> de ring te lat<strong>en</strong> circuler<strong>en</strong>. Algoritme 3.1<br />

geeft de pseudocode voor processor Pi.<br />

Elke processor begint met het berek<strong>en</strong><strong>en</strong> van zijn stuk van de matrix-vector-verm<strong>en</strong>igvuldiging<br />

<strong>en</strong> slaat het resultaat op in e<strong>en</strong> lokale variabele z (stap 1). In stap 2 initialiseert processor P1 de<br />

vector y op 0, terwijl alle andere processor<strong>en</strong> de uitvoering van hun programma opschort<strong>en</strong> <strong>en</strong><br />

wacht<strong>en</strong> tot ze data van hun linkerbuur ontvang<strong>en</strong>. Processor P1 stelt y ← A (1) x (1) <strong>en</strong> stuurt dit<br />

resultaat door naar zijn rechterbuur (lijn 6 <strong>en</strong> 7). Op dat mom<strong>en</strong>t ontvangt P2 de waarde A (1) x (1)<br />

<strong>en</strong> gaat verder met de uitvoering van zijn programma door de waarde y ← A (1) x (1) + A (2) x (2)<br />

te berek<strong>en</strong><strong>en</strong> <strong>en</strong> door te stur<strong>en</strong> naar zijn rechterbuur (lijn 6 <strong>en</strong> 7). Op die manier berek<strong>en</strong>t elke<br />

processor Pi gaandeweg zijn partieelsom y ← A (1) x (1) + ···+A (i) x (i) . Uiteindelijk berek<strong>en</strong>t Pp<br />

het gew<strong>en</strong>ste resultaat y ← Ax <strong>en</strong> stuurt dit door naar zijn rechterbuur P1. Dit verklaart de laatste<br />

if-opdracht, waar P1 nog het resultaat van zijn linkerbuur Pp moet ontvang<strong>en</strong>.<br />

Besprek<strong>en</strong> we de performantie van dit algoritme. De parallelle tijd nodig voor de berek<strong>en</strong>ing<strong>en</strong><br />

is Θ(n 2 /p). Bij de communicatie tuss<strong>en</strong> twee processor<strong>en</strong> moet telk<strong>en</strong>s e<strong>en</strong> vector van orde n<br />

doorgestuurd word<strong>en</strong>. Verder moet P1 wacht<strong>en</strong> tot wanneer Pp de som A (1) x (1) + ···+A (p) x (p)<br />

berek<strong>en</strong>d heeft, vooraleer hij zijn laatste bewerking kan uitvoer<strong>en</strong>; deze accumulatie van de som<br />

vraagt p stapp<strong>en</strong>. De totale tijd nodig voor de communicatie is dus Θ(np). M.a.w. de totale<br />

parallelle uitvoeringstijd van het algoritme is<br />

Tp(n) = Θ(n 2 /p+np).<br />

Gelet op de sequ<strong>en</strong>tiële uitvoeringstijd T ∗ (n) = Θ(n2 ) voor dit probleem, levert dit dus e<strong>en</strong><br />

versnelling<br />

Θ(n<br />

Sp(n) =<br />

2 )<br />

Θ(n2 p<br />

= Θ(<br />

/p+np) 1+ p2 /n ).<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


24 Hoofdstuk 3. Het netwerkmodel<br />

De kost van het algoritme is<br />

(a) Q0 (b) Q1 (c) Q2 (d) Q3 Q4<br />

Figuur 3.1: De hyperkubuss<strong>en</strong> t.e.m. dim<strong>en</strong>sie 4<br />

Cp(n) = pΘ(n 2 /p+np) = Θ(n 2 + np 2 ),<br />

zodat het algoritme kost-optimaal is voor p = Θ( √ n).<br />

3.3.3 Rooster<br />

E<strong>en</strong> veralgem<strong>en</strong>ing van de rijtopologie is het rooster (of mesh), dat p = m 2 processor<strong>en</strong> in e<strong>en</strong><br />

m×m tweedim<strong>en</strong>sionale loodrechte roosterstructuur plaatst, waarbij elke processor verbond<strong>en</strong> is<br />

met zijn onmiddellijke bur<strong>en</strong> (bov<strong>en</strong>, onder, links <strong>en</strong> rechts), m.a.w. Pi, j is verbond<strong>en</strong> met Pi±1, j<br />

<strong>en</strong> Pi, j±1 (waar die bestaan). Net zoals bij de rijtopologie, kan het rooster geslot<strong>en</strong> word<strong>en</strong> tot<br />

e<strong>en</strong> torus (of rooster met wrap-around), door de bov<strong>en</strong>ste processor van elke kolom te verbind<strong>en</strong><br />

met de onderste, <strong>en</strong> de laatste processor van elke rij te verbind<strong>en</strong> met de eerste. In de jar<strong>en</strong> 1980<br />

ontwierp Inmos e<strong>en</strong> chip met 4 links, transputer g<strong>en</strong>oemd, die dus perfect geschikt was voor het<br />

bouw<strong>en</strong> van e<strong>en</strong> rooster- of torustopologie.<br />

De diameter van e<strong>en</strong> rooster met p = m 2 processor<strong>en</strong> is 2 √ p − 2, dus Θ( √ p). De maximale<br />

graad van elke processor is 4. Het aantal verbinding<strong>en</strong> is 2m(m − 1) = Θ(p). De connectiviteit<br />

is 2.<br />

Deze topologie heeft verscheid<strong>en</strong>e eig<strong>en</strong>schapp<strong>en</strong> die haar aantrekkelijk mak<strong>en</strong>. Ze is e<strong>en</strong>voudig,<br />

regulier <strong>en</strong> uitbreidbaar. Bov<strong>en</strong>di<strong>en</strong> zijn er verscheid<strong>en</strong>e toepassing<strong>en</strong> waarbij de berek<strong>en</strong>ing<strong>en</strong><br />

op natuurlijke wijze in e<strong>en</strong> roosterstructuur gebeur<strong>en</strong>. Maar gelet op de grote diameter, zal e<strong>en</strong><br />

berek<strong>en</strong>ing met niet-triviale communicatiestapp<strong>en</strong> doorgaans Ω( √ p) parallelle stapp<strong>en</strong> vereis<strong>en</strong>.<br />

3.3.4 Hyperkubus<br />

E<strong>en</strong> andere populaire topologie is de hyperkubus. E<strong>en</strong> nuldim<strong>en</strong>sionale hyperkubus is één <strong>en</strong>kele<br />

processor. E<strong>en</strong> d-dim<strong>en</strong>sionale hyperkubus Qd, met d > 0, bestaat uit twee kopieën van<br />

e<strong>en</strong> (d − 1)-dim<strong>en</strong>sionale hyperkubus Qd−1, waarbij de corresponder<strong>en</strong>de topp<strong>en</strong> uit elke kopie<br />

verbond<strong>en</strong> word<strong>en</strong>. Figuur 3.1 toont alle hyperkubuss<strong>en</strong> t.e.m. dim<strong>en</strong>sie 4.<br />

De topp<strong>en</strong> in e<strong>en</strong> d-dim<strong>en</strong>sionale hyperkubus kunn<strong>en</strong> gelabeld word<strong>en</strong> met e<strong>en</strong> binaire string van<br />

d bits, op de volg<strong>en</strong>de manier. De twee topp<strong>en</strong> van de e<strong>en</strong>dim<strong>en</strong>sionale hyperkubus word<strong>en</strong> met 0<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


3.3. Interconnecti<strong>en</strong>etwerk<strong>en</strong> 25<br />

010<br />

110 111<br />

100<br />

011<br />

000 001<br />

Figuur 3.2: Labeling van de hyperkubus van dim<strong>en</strong>sie 3<br />

101<br />

0 1 0 1 0 1 0 0 1 0<br />

1 1 0 1 0 1 1 0 1 0<br />

1 1 1 1 0 1 1 1 1 0<br />

1 1 1 0 0 1 1 1 1 1<br />

1 1 1 0 1<br />

Figuur 3.3: Het verz<strong>en</strong>d<strong>en</strong> op e<strong>en</strong> hyperkubus<br />

<strong>en</strong> 1 gelabeld. De labels voor de d-dim<strong>en</strong>sionale hyperkubus word<strong>en</strong> dan recursief opgesteld.<br />

Veronderstel dat we reeds elke top van de (d −1)-dim<strong>en</strong>sionale hyperkubus gelabeld hebb<strong>en</strong> met<br />

string van d − 1 bits. De d-dim<strong>en</strong>sionale hyperkubus bestaat uit twee kopieën van de (d − 1)dim<strong>en</strong>sionale<br />

hyperkubus; geef de <strong>en</strong>e kopie label 0 <strong>en</strong> de andere label 1. Het label van e<strong>en</strong><br />

top in de d-dim<strong>en</strong>sionale hyperkubus bestaat uit de concat<strong>en</strong>atie van 0 of 1 (afhankelijk van de<br />

deelkubus waartoe hij behoort) <strong>en</strong> zijn label in de deelkubus. Figuur 3.2 toont de labeling van<br />

de driedim<strong>en</strong>sionale hyperkubus. Merk op dat twee processor<strong>en</strong> die in precies één coördinaat<br />

verschill<strong>en</strong>, rechtstreeks verbond<strong>en</strong> zijn door e<strong>en</strong> communicatiekanaal.<br />

Aangezi<strong>en</strong> verschill<strong>en</strong>de labels corresponder<strong>en</strong> met verschill<strong>en</strong>de topp<strong>en</strong>, kunn<strong>en</strong> we hieruit afleid<strong>en</strong><br />

dat de d-dim<strong>en</strong>sionale hyperkubus p = 2 d topp<strong>en</strong> bevat. De graad van elke top is d; de<br />

hyperkubus is dus e<strong>en</strong> reguliere graaf van graad d.<br />

De diameter van de hyperkubus is d = log 2 p, hetge<strong>en</strong> impliceert dat we e<strong>en</strong> boodschap van elke<br />

top naar om het ev<strong>en</strong> welke andere top kunn<strong>en</strong> stur<strong>en</strong> in hoogst<strong>en</strong>s d stapp<strong>en</strong>.<br />

Voorbeeld 3.3.2. E<strong>en</strong> e<strong>en</strong>voudig routing-algoritme is gebaseerd op het feit dat twee processor<strong>en</strong><br />

die in precies één coördinaat verschill<strong>en</strong>, rechtstreeks verbond<strong>en</strong> zijn door e<strong>en</strong> communicatiekanaal.<br />

Hierdoor kunn<strong>en</strong> we e<strong>en</strong> boodschap van processor Pi naar processor Pj stur<strong>en</strong> door het<br />

label i bit per bit in het label j te verander<strong>en</strong>. Bijvoorbeeld, om in de vijfdim<strong>en</strong>sionale hyperkubus<br />

e<strong>en</strong> boodschap van 01010 naar 11101 te stur<strong>en</strong>, kunn<strong>en</strong> we dit rout<strong>en</strong> over 01010, 11010,<br />

11110, 11100, 11101.<br />

Dit e<strong>en</strong>voudige routing-algoritme kan echter tot problem<strong>en</strong> leid<strong>en</strong>, wanneer meerdere boodschapp<strong>en</strong><br />

tegelijkertijd onderweg zijn. Bijvoorbeeld, beschouw het verstur<strong>en</strong> van e<strong>en</strong> boodschap<br />

van 01010 naar 11101 <strong>en</strong> e<strong>en</strong> boodschap van 10010 naar 11110. Figuur 3.3 illustreert het verz<strong>en</strong>-<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


26 Hoofdstuk 3. Het netwerkmodel<br />

dingsproces. Hieruit blijkt dat er in de tweede stap twee boodschapp<strong>en</strong> op 11010 zijn, die over<br />

dezelfde boog moet<strong>en</strong> verdergestuurd word<strong>en</strong>. Wanneer we zoals gebruikelijk veronderstell<strong>en</strong><br />

dat slechts één boodschap tegelijk over e<strong>en</strong> kanaal kan verstuurd word<strong>en</strong>, wordt e<strong>en</strong> van de boodschapp<strong>en</strong><br />

hier vertraagd. Meer geavanceerde algoritm<strong>en</strong> zijn nodig om dergelijke problem<strong>en</strong> te<br />

verhelp<strong>en</strong>.<br />

De hyperkubus is e<strong>en</strong> populaire topologie omwille van zijn regulariteit, zijn kleine diameter, zijn<br />

verscheid<strong>en</strong>e interessante graaf-theoretische eig<strong>en</strong>schapp<strong>en</strong>, <strong>en</strong> het feit dat vele berek<strong>en</strong>ing<strong>en</strong><br />

snel <strong>en</strong> e<strong>en</strong>voudig op e<strong>en</strong> hyperkubus kunn<strong>en</strong> word<strong>en</strong> uitgevoerd.<br />

E<strong>en</strong> bijkom<strong>en</strong>de red<strong>en</strong> is het feit dat andere netwerk<strong>en</strong> er e<strong>en</strong>voudig kunn<strong>en</strong> op gesimuleerd word<strong>en</strong>.<br />

Bepaalde netwerk<strong>en</strong>, zoals rij<strong>en</strong>, kunn<strong>en</strong> ingebed word<strong>en</strong> als deelgraf<strong>en</strong> van de hyperkubus.<br />

Andere netwerk<strong>en</strong>, zoals bom<strong>en</strong>, kunn<strong>en</strong> efficiënt gesimuleerd word<strong>en</strong> op de hyperkubus, als<br />

we toelat<strong>en</strong> dat bog<strong>en</strong> ‘verwijd’ word<strong>en</strong> <strong>en</strong> dat topp<strong>en</strong> van de hyperkubus meerdere topp<strong>en</strong> uit<br />

het oorspronkelijke netwerk simuler<strong>en</strong>. <strong>Algoritm<strong>en</strong></strong> voor de hyperkubus kunn<strong>en</strong> dus dikwijls<br />

aangepast word<strong>en</strong> om ook op andere architectur<strong>en</strong> te werk<strong>en</strong>.<br />

E<strong>en</strong> nadeel van het hyperkubusnetwerk is dat het duur is om het uit te breid<strong>en</strong>, omdat nieuwe<br />

connecties aan elke processor moet<strong>en</strong> word<strong>en</strong> toegevoegd wanneer we de dim<strong>en</strong>sie van de hyperkubus<br />

verhog<strong>en</strong>. Hyperkubuss<strong>en</strong> word<strong>en</strong> dus op hun beurt ingebed in netwerk<strong>en</strong> die e<strong>en</strong>voudiger<br />

in hardware te realiser<strong>en</strong> zijn.<br />

In de onderstaande voorbeeld<strong>en</strong> ontwerp<strong>en</strong> we synchrone algoritm<strong>en</strong> voor <strong>en</strong>kele e<strong>en</strong>voudige<br />

problem<strong>en</strong> op de hyperkubus.<br />

Voorbeeld 3.3.3 (Sommer<strong>en</strong> van e<strong>en</strong> rij op de hyperkubus). Zij gegev<strong>en</strong> e<strong>en</strong> rij (a0,...,an−1)<br />

met n = 2d elem<strong>en</strong>t<strong>en</strong>, waarbij elke ai opgeslag<strong>en</strong> is in het lokale geheug<strong>en</strong> van processor Pi van<br />

e<strong>en</strong> (synchrone) d-dim<strong>en</strong>sionale hyperkubus Qd. Gevraagd is de som s = ∑ n−1<br />

i=0 ai te berek<strong>en</strong><strong>en</strong><br />

<strong>en</strong> op te slaan op processor P0.<br />

Het algoritme voor de berek<strong>en</strong>ing van s is rechtlijnig. Het bestaat uit d iteraties. De eerste iteratie<br />

berek<strong>en</strong>t de somm<strong>en</strong> van par<strong>en</strong> elem<strong>en</strong>t<strong>en</strong> tuss<strong>en</strong> processor<strong>en</strong> waarvan de indices in de meest<br />

significante bitpositie verschill<strong>en</strong>. Deze somm<strong>en</strong> word<strong>en</strong> opgeslag<strong>en</strong> in de (d − 1)-dim<strong>en</strong>sionale<br />

deelhyperkubus waarvan de meest significante adresbit gelijk aan 0 is. De andere iteraties gebeur<strong>en</strong><br />

op gelijkaardige wijze.<br />

Algoritme 3.2 geeft de pseudocode voor processor Pi. Daarbij noter<strong>en</strong> we door i (ℓ) de index<br />

i waarbij van bit ℓ het complem<strong>en</strong>t g<strong>en</strong>om<strong>en</strong> werd. De instructie ai ← ai + a i (ℓ) vereist twee<br />

deelstapp<strong>en</strong>. In de eerste deelstap kopieert processor Pi de waarde a i (ℓ) van processor P i (ℓ) via de<br />

link tuss<strong>en</strong> Pi <strong>en</strong> P i (ℓ). In de tweede deelstap berek<strong>en</strong>t processor Pi de waarde ai + a i (ℓ) <strong>en</strong> slaat<br />

het resultaat op in ai.<br />

Dit algoritme vereist d = log 2 n parallelle stapp<strong>en</strong>.<br />

Voorbeeld 3.3.4 (Broadcast op de hyperkubus). Beschouw het probleem van het doorstur<strong>en</strong><br />

van e<strong>en</strong> item x van processor P0 naar alle andere processor<strong>en</strong> Pi van e<strong>en</strong> hyperkubus met p processor<strong>en</strong>,<br />

waarbij p = 2 d .<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


3.4. Communicatie-algoritm<strong>en</strong> 27<br />

Algoritme 3.2 Sommer<strong>en</strong> van e<strong>en</strong> rij op e<strong>en</strong> synchrone hyperkubus<br />

Input: rij (a0,...,an−1; n = 2d ; elke ai is opgesplag<strong>en</strong> op processor Pi van e<strong>en</strong> synchrone hyperkubus<br />

Qd<br />

Output: som s = ∑ n−1<br />

i=0 ai op P0<br />

1: for ℓ from d − 1 to 0 do<br />

2: if 0 ≤ i ≤ 2ℓ − 1 th<strong>en</strong><br />

3: Stel ai ← ai + ai (ℓ)<br />

Algoritme 3.3 Broadcast op e<strong>en</strong> synchrone hyperkubus<br />

Input: synchrone hyperkubus Qd met p = 2 d processor<strong>en</strong>; processor P0 heeft e<strong>en</strong> item x in zijn<br />

register d0<br />

Output: elke processor Pi heeft e<strong>en</strong> kopie van item x in zijn register di<br />

1: for ℓ from 0 to d − 1 do<br />

2: if 0 ≤ i ≤ 2 ℓ − 1 th<strong>en</strong><br />

3: Stel d i (ℓ) ← di<br />

E<strong>en</strong> e<strong>en</strong>voudige strategie kan gevolgd word<strong>en</strong> om dit probleem op te loss<strong>en</strong>. We werk<strong>en</strong> opwaarts<br />

vanaf de laagste dim<strong>en</strong>sie naar de hoogste dim<strong>en</strong>sie in de hyperkubus, in d iteraties, als volgt.<br />

Tijd<strong>en</strong>s de eerste iteratie z<strong>en</strong>dt P0 e<strong>en</strong> kopie van x naar P1. Tijd<strong>en</strong>s de tweede iteratie z<strong>en</strong>d<strong>en</strong> P0<br />

<strong>en</strong> P1 kopies van x naar P2 <strong>en</strong> P3 respectievelijk, gebruik mak<strong>en</strong>d van de links tuss<strong>en</strong> P0 <strong>en</strong> P2 <strong>en</strong><br />

tuss<strong>en</strong> P1 <strong>en</strong> P3.<br />

Algoritme 3.3 geeft de pseudocode voor dit algoritme. Net zoals in Algoritme 3.2 heeft de<br />

instructie d i (ℓ) ← di twee deelstapp<strong>en</strong>. In de eerste deelstap wordt e<strong>en</strong> kopie van het register di<br />

van processor Pi naar processor P i (ℓ) gekopieerd via de link tuss<strong>en</strong> Pi <strong>en</strong> P i (ℓ). In de tweede<br />

deelstap ontvangt processor P i (ℓ) de kopie <strong>en</strong> slaat ze op in zijn register d i (ℓ).<br />

Ook dit algoritme vereist d = log 2 p parallelle stapp<strong>en</strong>.<br />

Bov<strong>en</strong>staande algoritm<strong>en</strong> voor de hyperkubus behor<strong>en</strong> tot de klasse van g<strong>en</strong>ormaliseerde algoritm<strong>en</strong>.<br />

De hyperkubusalgoritm<strong>en</strong> in deze klasse gebruik<strong>en</strong> in elke tijdse<strong>en</strong>heid één dim<strong>en</strong>sie<br />

van de hyperkubus, zodanig dat ope<strong>en</strong>volg<strong>en</strong>de dim<strong>en</strong>sies in ope<strong>en</strong>volg<strong>en</strong>de tijdse<strong>en</strong>hed<strong>en</strong> gebruikt<br />

word<strong>en</strong>. Bov<strong>en</strong>staande algoritm<strong>en</strong> behor<strong>en</strong> zelfs tot de meer gespecialiseerde klass<strong>en</strong> van<br />

volledig g<strong>en</strong>ormaliseerde algoritm<strong>en</strong>, dit zijn g<strong>en</strong>ormaliseerde algoritm<strong>en</strong> met de bijkom<strong>en</strong>de<br />

voorwaarde dat elk van de d dim<strong>en</strong>sies van de hyperkubus in sequ<strong>en</strong>tie gebruikt wordt (ofwel in<br />

stijg<strong>en</strong>de volgorde, zoals bij het voorbeeld van broadcasting, ofwel in dal<strong>en</strong>de volgorde, zoals<br />

bij het voorbeeld van het sommer<strong>en</strong> van e<strong>en</strong> rij).<br />

3.4 Communicatie-algoritm<strong>en</strong><br />

Zoals reeds vermeld wissel<strong>en</strong> processor<strong>en</strong> in het netwerkmodel gegev<strong>en</strong>s uit door onderlinge<br />

communicatie via verbinding<strong>en</strong>. Deze communicatie heeft e<strong>en</strong> grote invloed op de efficiëntie van<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


28 Hoofdstuk 3. Het netwerkmodel<br />

parallelle algoritm<strong>en</strong> in het netwerkmodel, omdat bij de gegev<strong>en</strong>suitwisseling communicatievertraging<strong>en</strong><br />

kunn<strong>en</strong> ontstaan. Er zijn <strong>en</strong>kele veelvoorkom<strong>en</strong>de basispatron<strong>en</strong> van interprocessorcommunicatie,<br />

die gebruikt word<strong>en</strong> als bouwst<strong>en</strong><strong>en</strong> voor e<strong>en</strong> veelheid van parallelle algoritm<strong>en</strong>.<br />

In deze paragraaf introducer<strong>en</strong> we <strong>en</strong>kele standaard communicatiepatron<strong>en</strong> <strong>en</strong> besprek<strong>en</strong> hun efficiënte<br />

implem<strong>en</strong>tatie op standaard netwerktopologieën (zoals ring, rooster met wrap-around <strong>en</strong><br />

hyperkubus).<br />

We noter<strong>en</strong> door p het aantal processor<strong>en</strong> <strong>en</strong> door m de l<strong>en</strong>gte van de uit te wissel<strong>en</strong> gegev<strong>en</strong>s.<br />

We veronderstell<strong>en</strong> dat de verbinding<strong>en</strong> tuss<strong>en</strong> de processor<strong>en</strong> bidirectioneel zijn, m.a.w. dat<br />

twee rechtstreeks verbond<strong>en</strong> processor<strong>en</strong> tegelijkertijd boodschapp<strong>en</strong> van grootte m naar elkaar<br />

kunn<strong>en</strong> stur<strong>en</strong>. Verder veronderstell<strong>en</strong> we dat e<strong>en</strong> processor slechts op e<strong>en</strong> van zijn verbinding<strong>en</strong><br />

tegelijk e<strong>en</strong> boodschap kan stur<strong>en</strong>. Analoog kan e<strong>en</strong> processor maar op e<strong>en</strong> van zijn verbinding<strong>en</strong><br />

tegelijk e<strong>en</strong> boodschap ontvang<strong>en</strong>. Maar e<strong>en</strong> processor kan wel tegelijkertijd op e<strong>en</strong> van van zijn<br />

verbinding<strong>en</strong> e<strong>en</strong> boodschap stur<strong>en</strong> <strong>en</strong> op e<strong>en</strong> andere verbinding e<strong>en</strong> boodschap ontvang<strong>en</strong>.<br />

Voor veel van de hier beschrev<strong>en</strong> bewerking<strong>en</strong> bestaan duale <strong>en</strong> andere aanverwante bewerking<strong>en</strong><br />

die zeer analoog aan de oorspronkelijke bewerking<strong>en</strong> kunn<strong>en</strong> word<strong>en</strong> uitgevoerd. De duale van<br />

e<strong>en</strong> communicatiebewerking is het teg<strong>en</strong>overgestelde van de oorspronkelijke bewerking <strong>en</strong> kan<br />

uitgevoerd word<strong>en</strong> door de richting <strong>en</strong> de volgorde van de boodschapp<strong>en</strong> in de oorspronkelijke<br />

bewerking om te ker<strong>en</strong>. Waar toepasselijk zull<strong>en</strong> we dergelijke bewerking<strong>en</strong> vermeld<strong>en</strong>.<br />

3.4.1 One-to-all broadcast<br />

In e<strong>en</strong> one-to-all-broadcast of single-node-broadcast stuurt één processor e<strong>en</strong> id<strong>en</strong>tieke boodschap<br />

naar elke andere processor. Aanvankelijk heeft <strong>en</strong>kel de bronprocessor de boodschap van<br />

grootte m; na de broadcast zijn er p kopieën van de boodschap, nl. e<strong>en</strong> kopie op elke processor.<br />

De duale bewerking hiervan is e<strong>en</strong> single-node accumulation. Hierbij heeft elke processor<br />

aanvankelijk e<strong>en</strong> boodschap van grootte m. Eén van de processor<strong>en</strong> (de bronprocessor) verzamelt<br />

deze informatie van alle andere processor<strong>en</strong> <strong>en</strong> bundelt die tot één boodschap van grootte m (via<br />

e<strong>en</strong> associatieve operator). Merk op dat de sam<strong>en</strong>gevoegde informatie na de bewerking grootte m<br />

heeft. Dit betek<strong>en</strong>t dat single-node accumulation kan word<strong>en</strong> gebruikt om de som, het product,<br />

het maximum of het minimum van e<strong>en</strong> rij getall<strong>en</strong>, of elke andere paarsgewijze bewerking op<br />

e<strong>en</strong> rij elem<strong>en</strong>t<strong>en</strong> uit te voer<strong>en</strong>.<br />

Deze communicatiepatron<strong>en</strong> word<strong>en</strong> o.m. gebruikt in parallelle algoritm<strong>en</strong> voor matrix-vectorverm<strong>en</strong>igvuldiging,<br />

Gauss-eliminatie, het bepal<strong>en</strong> van kortste pad<strong>en</strong>, het inproduct van vector<strong>en</strong>.<br />

One-to-all broadcast op e<strong>en</strong> ring<br />

De bronprocessor stuurt zijn boodschap naar zijn twee bur<strong>en</strong>, in twee ope<strong>en</strong>volg<strong>en</strong>de stapp<strong>en</strong>.<br />

Elke processor ontvangt e<strong>en</strong> boodschap op e<strong>en</strong> van zijn verbinding<strong>en</strong> <strong>en</strong> stuurt deze door naar<br />

zijn buur op de andere verbinding. Dit proces wordt herhaald totdat alle processor<strong>en</strong> e<strong>en</strong> kopie<br />

van de boodschap ontvang<strong>en</strong> hebb<strong>en</strong>.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


3.4. Communicatie-algoritm<strong>en</strong> 29<br />

Dit ganse proces vereist ⌈p/2⌉ stapp<strong>en</strong> <strong>en</strong> de totale communicatietijd is Θ(mp).<br />

One-to-all broadcast op e<strong>en</strong> rooster met wraparound<br />

Elke rij <strong>en</strong> kolom van e<strong>en</strong> vierkant rooster met p processor<strong>en</strong> kan beschouwd word<strong>en</strong> als e<strong>en</strong><br />

ring met √ p processor<strong>en</strong>. Verscheid<strong>en</strong>e communicatie-algoritm<strong>en</strong> voor e<strong>en</strong> rooster zijn dan ook<br />

e<strong>en</strong>voudige uitbreiding<strong>en</strong> van hun teg<strong>en</strong>hangers op e<strong>en</strong> ring. Typisch bestaat dergelijk algoritme<br />

uit twee fas<strong>en</strong>. In de eerste fase gebeurt de communicatie op e<strong>en</strong> of meerdere rij<strong>en</strong>, die als ring<br />

beschouwd word<strong>en</strong>. Dit wordt e<strong>en</strong> rijrotatie g<strong>en</strong>oemd. In de tweede fase word<strong>en</strong> de kolomm<strong>en</strong><br />

op dezelfde manier behandeld. Dit wordt e<strong>en</strong> kolomrotatie g<strong>en</strong>oemd.<br />

Concreet is ook het algoritme voor one-to-all broadcast op e<strong>en</strong> rooster met √ p rij<strong>en</strong> <strong>en</strong> √ p<br />

kolomm<strong>en</strong> gebaseerd op het bov<strong>en</strong>staande algoritme voor one-to-all braodcast op e<strong>en</strong> ring. In<br />

fase 1 stuurt de bronprocessor de boodschap naar de andere ( √ p − 1) processor<strong>en</strong> op zijn rij,<br />

via e<strong>en</strong> one-to-all broadcast. In fase 2 verspreidt elk van deze processor<strong>en</strong> de boodschap via e<strong>en</strong><br />

one-to-all broadcast over zijn kolom. Op het einde van fase 2 heeft elke processor e<strong>en</strong> kopie van<br />

de oorspronkelijke boodschap.<br />

De communicatietijd van de rijrotatie op de rij van de bronprocessor is Θ(m √ p), nl. de tijd nodig<br />

voor e<strong>en</strong> one-to-all broadcast op e<strong>en</strong> ring van √ p processor<strong>en</strong>. In de tweede fase gebeur<strong>en</strong> alle<br />

kolomrotaties in parallel, zodat deze fase precies ev<strong>en</strong>veel tijd neemt als de eerste fase. De totale<br />

communicatietijd van deze one-to-all broadcast is dus Θ(m √ p).<br />

Merk op dat dit algoritme kan veralgeme<strong>en</strong>d word<strong>en</strong> naar e<strong>en</strong> meerdim<strong>en</strong>sionaal rooster. Bijvoorbeeld,<br />

in e<strong>en</strong> driedim<strong>en</strong>sionaal rooster word<strong>en</strong> de 3√ p processor<strong>en</strong> van elke dim<strong>en</strong>sie als<br />

ring<strong>en</strong> beschouwd. Door de procedure voor e<strong>en</strong> ring in drie fas<strong>en</strong> toe te pass<strong>en</strong>, e<strong>en</strong>maal in elke<br />

dim<strong>en</strong>sie, bekom<strong>en</strong> we e<strong>en</strong> algoritme voor one-to-all broadcast op e<strong>en</strong> drie-dim<strong>en</strong>sionaal rooster<br />

met communicatietijd Θ(m 3√ p).<br />

One-to-all broadcast op e<strong>en</strong> hyperkubus<br />

In het bijzonder is e<strong>en</strong> hyperkubus van dim<strong>en</strong>sie d te beschouw<strong>en</strong> als e<strong>en</strong> d-dim<strong>en</strong>sionaal rooster<br />

met twee processor<strong>en</strong> in elke dim<strong>en</strong>sie. Het algoritme voor e<strong>en</strong> rooster kan dus word<strong>en</strong> uitgebreid<br />

naar e<strong>en</strong> hyperkubus, waarbij het proces in d fas<strong>en</strong> gebeurt, e<strong>en</strong>maal in elke dim<strong>en</strong>sie van de<br />

hyperkubus. Elke stap is e<strong>en</strong> one-to-all broadcast op e<strong>en</strong> ring met twee processor<strong>en</strong>, hetge<strong>en</strong><br />

uiteindelijk e<strong>en</strong> e<strong>en</strong>voudige uitwisseling van boodschapp<strong>en</strong> tuss<strong>en</strong> twee rechtstreeks verbond<strong>en</strong><br />

processor<strong>en</strong> is.<br />

Merk op dat de volgorde waarin de verschill<strong>en</strong>de fases de dim<strong>en</strong>sies doorlop<strong>en</strong>, onbelangrijk<br />

is. E<strong>en</strong> mogelijke volgorde bestaat erin te start<strong>en</strong> met de uitwisseling in de hoogste dim<strong>en</strong>sie,<br />

m.a.w. e<strong>en</strong> uitwisseling tuss<strong>en</strong> twee processor<strong>en</strong> waarvan de label in hun meest significante bit<br />

verschill<strong>en</strong>, <strong>en</strong> in ope<strong>en</strong>volg<strong>en</strong>de lagere dim<strong>en</strong>sies te werk<strong>en</strong> in de volg<strong>en</strong>de stapp<strong>en</strong>.<br />

Het aantal stapp<strong>en</strong> is Θ(log p), met p = 2 d . De totale communicatietijd is Θ(mlog p).<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


30 Hoofdstuk 3. Het netwerkmodel<br />

3.4.2 All-to-all broadcast<br />

E<strong>en</strong> all-to-all broadcast of multinode broadcast is e<strong>en</strong> veralgem<strong>en</strong>ing van de one-to-all broadcast,<br />

waarbij elke processor gelijktijdig e<strong>en</strong> one-to-all broadcast uitvoert. E<strong>en</strong> processor stuurt<br />

dezelfde boodschap van grootte m naar alle andere processor<strong>en</strong>, maar verschill<strong>en</strong>de processor<strong>en</strong><br />

stur<strong>en</strong> verschill<strong>en</strong>de boodschapp<strong>en</strong>. De duale bewerking is multinode accumulation, waarbij<br />

elke processor de bestemming is van e<strong>en</strong> single-node accumulation.<br />

Deze communicatiepatron<strong>en</strong> word<strong>en</strong> o.m. gebruikt bij parallelle algoritm<strong>en</strong> voor matrixbewerking<strong>en</strong>,<br />

zoals matrixverm<strong>en</strong>igvuldiging, <strong>en</strong> bij reductie <strong>en</strong> het bepal<strong>en</strong> van prefixsomm<strong>en</strong>.<br />

E<strong>en</strong> e<strong>en</strong>voudige manier om e<strong>en</strong> all-to-all broadcast uit te voer<strong>en</strong> bestaat in het uitvoer<strong>en</strong> van<br />

p one-to-all broadcasts, één die in elke processor start. Wanneer dit e<strong>en</strong>voudigweg rechtlijnig<br />

geïmplem<strong>en</strong>teerd wordt, leidt deze b<strong>en</strong>adering op sommige architectur<strong>en</strong> tot e<strong>en</strong> communicatietijd<br />

van p maal de tijd voor e<strong>en</strong> one-to-all broadcast. Maar dikwijls is het mogelijk om de<br />

communicatieverbinding<strong>en</strong> van het netwerk efficiënter te gebruik<strong>en</strong> <strong>en</strong> de one-to-all broadcasts<br />

gelijktijdig te lat<strong>en</strong> uitvoer<strong>en</strong>. Daarbij probeert m<strong>en</strong> ook om boodschapp<strong>en</strong> die over hetzelfde<br />

pad gestuurd word<strong>en</strong>, sam<strong>en</strong> te voeg<strong>en</strong> tot één <strong>en</strong>kele boodschap (met als grootte de som van<br />

groottes van de individuele boodschapp<strong>en</strong>) <strong>en</strong> dus tegelijkertijd te stur<strong>en</strong>.<br />

All-to-all broadcast op e<strong>en</strong> ring<br />

In het eerder gezi<strong>en</strong>e algoritme voor one-to-all broadcast op e<strong>en</strong> ring zijn slechts twee communicatieverbinding<strong>en</strong><br />

terzelfdertijd actief tijd<strong>en</strong>s elke stap. Bij all-to-all broadcast kunn<strong>en</strong> alle<br />

verbinding<strong>en</strong> de ganse tijd actief gehoud<strong>en</strong> word<strong>en</strong>, omdat we er voor kunn<strong>en</strong> zorg<strong>en</strong> dat elke<br />

processor op elk mom<strong>en</strong>t informatie heeft die hij kan doorgev<strong>en</strong>. Dit werkt als volgt.<br />

In de eerste stap stuurt elke processor Pi zijn eig<strong>en</strong> boodschap door naar zijn buur Pi+1. In de<br />

volg<strong>en</strong>de stapp<strong>en</strong> stuurt processor Pi alle binn<strong>en</strong>kom<strong>en</strong>de boodschapp<strong>en</strong> van zijn andere buur<br />

Pi−1 door naar Pi+1. Dit duurt totdat alle boodschapp<strong>en</strong> overal verspreid zijn. Dit algoritme is te<br />

beschouw<strong>en</strong> als e<strong>en</strong> soort pipelining van meerdere one-to-all broadcasts.<br />

Doordat de communicatie circulair in één richting verloopt, ontvangt elke processor de p − 1<br />

vereiste boodschapp<strong>en</strong> van de andere processor<strong>en</strong> in p − 1 stapp<strong>en</strong>. De totale communicatietijd<br />

is dus Θ(mp).<br />

All-to-all broadcast op e<strong>en</strong> rooster met wraparound<br />

Ook hier is het algoritme gebaseerd op het algoritme voor all-to-all broadcast op e<strong>en</strong> ring <strong>en</strong><br />

werkt het in twee fas<strong>en</strong>.<br />

In fase 1 doet elke processor Pi, j e<strong>en</strong> all-to-all broadcast van zijn eig<strong>en</strong> boodschap op rij i. Op<br />

die manier verzamelt elke processor de √ p boodschapp<strong>en</strong> van grootte m van zijn eig<strong>en</strong> rij. Vervolg<strong>en</strong>s<br />

word<strong>en</strong> op elke processor de binn<strong>en</strong>gekom<strong>en</strong> boodschapp<strong>en</strong> sam<strong>en</strong>gesteld tot e<strong>en</strong> boodschap<br />

van m √ p lang. In fase 2 doet elke processor Pi, j dan e<strong>en</strong> all-to-all broadcast van zijn<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


3.4. Communicatie-algoritm<strong>en</strong> 31<br />

sam<strong>en</strong>gestelde boodschap op kolom j. Hierdoor verzamelt elke processor alle p boodschapp<strong>en</strong><br />

die zich oorspronkelijk elk op hun eig<strong>en</strong> processor bevond<strong>en</strong>.<br />

Het aantal stapp<strong>en</strong> in fase 1 is Θ( √ p) <strong>en</strong> de totale communicatietijd van fase 1 is Θ(m √ p). Ook<br />

in fase 2 is het aantal stapp<strong>en</strong> Θ( √ p), maar aangezi<strong>en</strong> de boodschapp<strong>en</strong> nu grootte m √ p hebb<strong>en</strong>,<br />

is de totale communicatietijd van fase 2 Θ(m √ p × √ p). De totale communicatietijd van beide<br />

fas<strong>en</strong> sam<strong>en</strong> is dus Θ(mp).<br />

Merk op dat het algoritme ook te veralgem<strong>en</strong><strong>en</strong> is voor e<strong>en</strong> d-dim<strong>en</strong>sionaal rooster of voor e<strong>en</strong><br />

hyperkubus (als oef<strong>en</strong>ing).<br />

3.4.3 Single-node scatter<br />

In e<strong>en</strong> one-to-all personalized communication of single-node scatter z<strong>en</strong>dt één <strong>en</strong>kele processor<br />

e<strong>en</strong> gepersonaliseerde boodschap van grootte m naar elke andere processor. Deze bewerking<br />

verschilt van e<strong>en</strong> one-to-all broadcast in de zin dat de bronprocessor hier aanvankelijk p verschill<strong>en</strong>de<br />

boodschapp<strong>en</strong> heeft, nl. e<strong>en</strong> unieke boodschap bestemd voor elke processor. Bov<strong>en</strong>di<strong>en</strong><br />

wordt bij single-node scatter ge<strong>en</strong> data gedupliceerd.<br />

De duale bewerking is single-node gather, waarbij één <strong>en</strong>kele processor e<strong>en</strong> unieke boodschap<br />

van elke andere processor ontvangt. Voor elke netwerktopologie kan de procedure voor singl<strong>en</strong>ode<br />

gather bekom<strong>en</strong> word<strong>en</strong> uit die voor single-node scatter door de richting <strong>en</strong> de volgorde<br />

van de boodschapp<strong>en</strong> om te ker<strong>en</strong>. Merk ook op dat e<strong>en</strong> gather-bewerking verschilt van e<strong>en</strong><br />

accumulation-bewerking doordat ze de ontvang<strong>en</strong> data niet combineert of reduceert.<br />

De complexiteit van single-node scatter op de verschill<strong>en</strong>de topologieën is gelijkaardig aan die<br />

van all-to-all broadcast. In all-to-all broadcast ontvangt elke processor e<strong>en</strong> boodschap van m(p−<br />

1), terwijl in single-node scatter de bronprocessor p−1 boodschapp<strong>en</strong> van grootte m doorstuurt.<br />

Omwille van deze grote gelijk<strong>en</strong>is tuss<strong>en</strong> we single-node scatter <strong>en</strong> all-to-all broadcast besprek<strong>en</strong><br />

we hier <strong>en</strong>kel e<strong>en</strong> algoritme voor e<strong>en</strong> hyperkubus, <strong>en</strong> lat<strong>en</strong> de algoritm<strong>en</strong> voor e<strong>en</strong> ring <strong>en</strong> e<strong>en</strong><br />

rooster met wraparound als oef<strong>en</strong>ing.<br />

Single-node scatter op e<strong>en</strong> hyperkubus<br />

Het achterligg<strong>en</strong>de idee van het algoritme is als volgt. Oorspronkelijk heeft de bronprocessor<br />

alle p boodschapp<strong>en</strong>. In de eerste communicatiestap stuurt de bronprocessor de helft van zijn<br />

boodschapp<strong>en</strong> door naar e<strong>en</strong> van zijn bur<strong>en</strong>. In de volg<strong>en</strong>de communicatiestapp<strong>en</strong> stuurt elke<br />

processor die reeds gegev<strong>en</strong>s heeft, de helft ervan door naar e<strong>en</strong> van zijn bur<strong>en</strong>.<br />

Merk op dat de links in e<strong>en</strong> hyperkubus met p processor<strong>en</strong> in e<strong>en</strong> zekere dim<strong>en</strong>sie twee deelhyperkubuss<strong>en</strong><br />

met p/2 processor<strong>en</strong> verbind<strong>en</strong>. In elke communicatiestap beweegt data van de <strong>en</strong>e<br />

deelhyperkubus naar de andere. De gegev<strong>en</strong>s die e<strong>en</strong> processor heeft vooraleer de communicatie<br />

in e<strong>en</strong> zekere dim<strong>en</strong>sie te start<strong>en</strong>, bestaan voor de helft uit gegev<strong>en</strong>s die bedoeld zijn voor e<strong>en</strong><br />

processor uit de andere deelhyperkubus. In elke stap houdt e<strong>en</strong> communicer<strong>en</strong>de processor de<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


32 Hoofdstuk 3. Het netwerkmodel<br />

helft van zijn gegev<strong>en</strong>s, nl. deg<strong>en</strong>e die bedoeld zijn voor e<strong>en</strong> processor in zijn eig<strong>en</strong> deelhyperkubus<br />

moet<strong>en</strong> blijv<strong>en</strong>; de andere helft stuurt hij naar zijn buur in de andere deelhyperkubus.<br />

Er zijn log 2p communicatiestapp<strong>en</strong>, elk corresponder<strong>en</strong>d met e<strong>en</strong> van de dim<strong>en</strong>sies van de hyperkubus.<br />

In elke stap wordt de grootte van de doorgestuurde sam<strong>en</strong>gestelde boodschap gehalveerd.<br />

De totale communicatietijd is dus gegev<strong>en</strong> door Θ(∑ log 2 p p<br />

i=1 2i m), of dus Θ(mp). Merk op dat dit<br />

hetzelfde is als de totale communicatietijd van e<strong>en</strong> all-to-all broadcast in e<strong>en</strong> hyperkubus van<br />

dezelfde dim<strong>en</strong>sie.<br />

3.4.4 Total exchange<br />

In e<strong>en</strong> all-to-all personalized communication of total exchange stuurt elke processor e<strong>en</strong> verschill<strong>en</strong>de<br />

boodschap van grootte m naar elke andere processor. Anders dan in e<strong>en</strong> all-to-all<br />

broadcast stuurt elke processor verschill<strong>en</strong>de boodschapp<strong>en</strong> naar verschill<strong>en</strong>de processor<strong>en</strong>.<br />

Deze bewerking wordt o.m. gebruikt in parallelle algoritm<strong>en</strong> voor matrixtranspositie.<br />

Total exchange op e<strong>en</strong> ring<br />

In stap 1 z<strong>en</strong>dt elke processor Pi al zijn boodschapp<strong>en</strong>, als e<strong>en</strong> sam<strong>en</strong>gestelde boodschap met<br />

l<strong>en</strong>gte m(p − 1), naar Pi+1. Voor elke processor Pi is één van de boodschapp<strong>en</strong> uit de ontvang<strong>en</strong><br />

sam<strong>en</strong>gestelde boodschap bestemd voor Pi; deze heeft dus reeds zijn doel bereikt <strong>en</strong> kan uit de<br />

sam<strong>en</strong>gestelde boodschap verwijderd word<strong>en</strong>. In stap 2 stuurt elke Pi de rest van de ontvang<strong>en</strong><br />

sam<strong>en</strong>gestelde boodschap, die nu l<strong>en</strong>gte m(p − 2) heeft, door naar Pi+1. Na p − 1 dergelijke<br />

stapp<strong>en</strong> zijn alle boodschapp<strong>en</strong> op hun bestemming.<br />

De totale communicatietijd wordt gegev<strong>en</strong> door Θ(∑ p−1<br />

i=1 m(p − i)) = Θ(mp2 ).<br />

Total exchange op e<strong>en</strong> hyperkubus<br />

Zoals bij eerdere communicatie-algoritm<strong>en</strong> op e<strong>en</strong> hyperkubus, wordt in log p stapp<strong>en</strong> telk<strong>en</strong>s<br />

data uitgewisseld in e<strong>en</strong> andere dim<strong>en</strong>sie van de hyperkubus. In elke stap heeft elke processor<br />

p boodschapp<strong>en</strong> van l<strong>en</strong>gte m elk; de helft daarvan wordt doorgestuurd naar e<strong>en</strong> buur, <strong>en</strong><br />

vervang<strong>en</strong> door de helft van die buur.<br />

De totale communicatietijd is Θ(mplog p).<br />

3.5 Gedistribueerde algoritm<strong>en</strong><br />

Begin 1999 ontcijferde e<strong>en</strong> netwerk van zowat 100 000 PCs op het Internet e<strong>en</strong> in DES gecodeerde<br />

boodschap in minder dan e<strong>en</strong> dag, wat het lot bezegelde van e<strong>en</strong> 25 jaar oude regeringsstandaard<br />

voor <strong>en</strong>cryptie. DES is de afkorting van “Data Encryption Standard”, het is nu vervang<strong>en</strong><br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


3.5. Gedistribueerde algoritm<strong>en</strong> 33<br />

door AES, de “Advanced Encryption Standard”. De aanval was niet gebaseerd op gesofisticeerde<br />

wiskundige eig<strong>en</strong>schapp<strong>en</strong> van het DES-coderingsschema, maar wel op brute kracht. DES<br />

gebruikt e<strong>en</strong> sleutel van 56 bits, m.a.w. er zijn slechts 2 56 mogelijke sleutels om te controler<strong>en</strong>.<br />

E<strong>en</strong> typische PC op dat mom<strong>en</strong>t kon zo’n 2 miljo<strong>en</strong> sleutels in één seconde uitprober<strong>en</strong>, zodat<br />

één PC ongeveer 2 56 /(2 × 10 2 ) second<strong>en</strong>, of ongeveer 1000 jaar, nodig zou gehad hebb<strong>en</strong> om<br />

alle sleutels te prober<strong>en</strong>. Wanneer 100 000 PCs in parallel op dit probleem werk<strong>en</strong>, wordt deze<br />

tijd gereduceerd tot ongeveer 4 dag<strong>en</strong>.<br />

Gelijkaardige gedistribueerde project<strong>en</strong> zijn inmiddels opgezet voor tak<strong>en</strong> zoals het factoriser<strong>en</strong><br />

van grote getall<strong>en</strong> (e<strong>en</strong> andere bezigheid die interessant is voor crypto-analyst<strong>en</strong>), het zoek<strong>en</strong><br />

van grote priemtweeling<strong>en</strong>, <strong>en</strong> zelfs voor het zoek<strong>en</strong> naar buit<strong>en</strong>aardse intellig<strong>en</strong>tie (het SETI<br />

project).<br />

Al deze project<strong>en</strong> verton<strong>en</strong> e<strong>en</strong> typische eig<strong>en</strong>schap van gedistribueerde berek<strong>en</strong>ing: de taak die<br />

moet uitgevoerd word<strong>en</strong>, parallelliseert goed. De taak is op te brek<strong>en</strong> in zeer onafhankelijke<br />

deeltak<strong>en</strong>, waarbij weinig communicatie tuss<strong>en</strong> de deeltak<strong>en</strong> nodig is. Bijvoorbeeld, in het DESproject<br />

werd<strong>en</strong> de sleutels opgesplitst in grote blokk<strong>en</strong>, die uitgedeeld werd<strong>en</strong> aan verschill<strong>en</strong>de<br />

processor<strong>en</strong>.<br />

De belangrijkste vraag in gedistribueerde berek<strong>en</strong>ing<strong>en</strong> is niet zozeer of, <strong>en</strong> hoe, e<strong>en</strong> probleem<br />

parallelliseert, maar wel hoe de grote hoeveelheid processor<strong>en</strong> e<strong>en</strong> gedistribueerde berek<strong>en</strong>ing<br />

kan opzett<strong>en</strong> <strong>en</strong> handhav<strong>en</strong> in e<strong>en</strong> onbetrouwbare <strong>en</strong> soms zelfs vijandige omgeving. Wat moet<br />

er gebeur<strong>en</strong> wanneer e<strong>en</strong> PC die gewerkt heeft op e<strong>en</strong> bepaald blok sleutels, ge<strong>en</strong> resultaat teruggeeft?<br />

Is de communicatie verlor<strong>en</strong> gegaan of is de computer afgeslot<strong>en</strong>? Gev<strong>en</strong> we het blok<br />

sleutels aan e<strong>en</strong> andere processor, of wacht<strong>en</strong> we? Wat wanneer één van de PCs gekraakt werd<br />

<strong>en</strong> nu opzettelijk verkeerde resultat<strong>en</strong> teruggeeft? Kunn<strong>en</strong> we herk<strong>en</strong>n<strong>en</strong> wanneer dit gebeurt?<br />

En wie is “we”?<br />

In alle voorbeeld<strong>en</strong> die we tot nu toe vermeld hebb<strong>en</strong>, is er één c<strong>en</strong>trale processor die de tak<strong>en</strong><br />

uitbesteedt (ook “farming” g<strong>en</strong>oemd) aan beschikbare werkers <strong>en</strong> die de ganse berek<strong>en</strong>ing beheert.<br />

In het algeme<strong>en</strong> will<strong>en</strong> we echter niet veronderstell<strong>en</strong> dat er noodzakelijk e<strong>en</strong> aangestelde<br />

leider is. Bijvoorbeeld, ARPANET, de voorganger van het Internet, was door het US Departm<strong>en</strong>t<br />

of Def<strong>en</strong>se in 1969 opgericht als e<strong>en</strong> gedec<strong>en</strong>traliseerd communicati<strong>en</strong>etwerk teg<strong>en</strong> mogelijke<br />

nucleaire aanvall<strong>en</strong>. Zelfs wanneer sommige servers in het Internet uitvall<strong>en</strong>, is er nog steeds<br />

communicatie mogelijk. Wanneer de hoofdcomputer in e<strong>en</strong> gec<strong>en</strong>traliseerd netwerk uitvalt, stort<br />

het hele netwerk in elkaar.<br />

We zi<strong>en</strong> dus dat de studie van gedistribueerde algoritm<strong>en</strong> gestuurd wordt door vrag<strong>en</strong> die betrekking<br />

hebb<strong>en</strong> op basiscommunicatie tuss<strong>en</strong> de processor<strong>en</strong> die het gedistribueerde netwerk<br />

vorm<strong>en</strong>.<br />

Er zijn meerdere modell<strong>en</strong> van gedistribueerd berek<strong>en</strong><strong>en</strong>. Meestal wordt verondersteld dat de<br />

processor<strong>en</strong> slechts losweg gekoppeld (“loosely coupled”) zijn, m.a.w. er is informatie over kanal<strong>en</strong><br />

tuss<strong>en</strong> par<strong>en</strong> processor<strong>en</strong>, maar verder wordt ge<strong>en</strong> informatie gedeeld. In het bijzonder is<br />

er ge<strong>en</strong> sprake van e<strong>en</strong> globale toestand, zoals in e<strong>en</strong> gec<strong>en</strong>traliseerd algoritme. Occasioneel kan<br />

het echter zinvol zijn om te veronderstell<strong>en</strong> dat alle processor<strong>en</strong> synchroon kunn<strong>en</strong> werk<strong>en</strong>, via<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


34 Hoofdstuk 3. Het netwerkmodel<br />

toegang tot e<strong>en</strong> globale klok. Zulke netwerk<strong>en</strong> word<strong>en</strong> synchroon g<strong>en</strong>oemd. Wanneer we niet<br />

veronderstell<strong>en</strong> dat er e<strong>en</strong> globale klok is, dan noem<strong>en</strong> we het netwerk asynchroon.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


Hoofdstuk 4<br />

Ontwerptechniek<strong>en</strong> voor parallelle<br />

algoritm<strong>en</strong><br />

De taak van het ontwerp<strong>en</strong> van parallelle algoritm<strong>en</strong> levert uitdaging<strong>en</strong> die heel wat moeilijker<br />

zijn dan in het geval van sequ<strong>en</strong>tiële algoritm<strong>en</strong>. Het ontbrek<strong>en</strong> van één welbepaalde methodologie<br />

wordt gecomp<strong>en</strong>seerd door e<strong>en</strong> verzameling techniek<strong>en</strong> <strong>en</strong> paradigma’s die effectief geblek<strong>en</strong><br />

zijn bij het behandel<strong>en</strong> van e<strong>en</strong> breede waaier aan problem<strong>en</strong>. In dit hoofdstuk introducer<strong>en</strong> we<br />

<strong>en</strong>kele van deze techniek<strong>en</strong> <strong>en</strong> pass<strong>en</strong> ze toe op e<strong>en</strong> reeks combinatorische problem<strong>en</strong>, die vaak<br />

op zichzelf reeds interessant zijn <strong>en</strong> die daarnaast ook optred<strong>en</strong> als deelproblem<strong>en</strong> in tal van andere<br />

berek<strong>en</strong>ing<strong>en</strong>. Het is belangrijk op te merk<strong>en</strong> dat de hier besprok<strong>en</strong> techniek<strong>en</strong> eerder als<br />

algem<strong>en</strong>e richtlijn<strong>en</strong> voor het ontwerp<strong>en</strong> van parallelle algoritm<strong>en</strong> di<strong>en</strong><strong>en</strong> te word<strong>en</strong> gezi<strong>en</strong>, <strong>en</strong><br />

niet zozeer als e<strong>en</strong> handleiding van pasklare recept<strong>en</strong>.<br />

35


36 Hoofdstuk 4. Ontwerptechniek<strong>en</strong> voor parallelle algoritm<strong>en</strong><br />

4.1 Pipelining / Sorter<strong>en</strong> & Priemzeef<br />

4.1.1 Techniek van pipelining<br />

Bij de techniek van pipelining wordt e<strong>en</strong> taak T opgebrok<strong>en</strong> in e<strong>en</strong> sequ<strong>en</strong>tie van deeltak<strong>en</strong><br />

t1,...,tm die na mekaar uit te voer<strong>en</strong> zijn, op zodanige manier dat, wanneer deeltaak t1 afgewerkt<br />

is, er kan begonn<strong>en</strong> word<strong>en</strong> met de sequ<strong>en</strong>tie voor e<strong>en</strong> nieuwe taak T ′ , die aan hetzelfde tempo<br />

verdergaat. De deeltak<strong>en</strong> word<strong>en</strong> door verschill<strong>en</strong>de processor<strong>en</strong> (of process<strong>en</strong>) uitgevoerd. Dit<br />

proces is gelijkaardig aan de werking van e<strong>en</strong> lop<strong>en</strong>de band in e<strong>en</strong> productiesysteem.<br />

De techniek van pipelining is bruikbaar in o.m. de volg<strong>en</strong>de situaties:<br />

• wanneer meer dan één instantie van het volledige probleem moet word<strong>en</strong> opgelost;<br />

• wanneer er e<strong>en</strong> reeks gegev<strong>en</strong>s te verwerk<strong>en</strong> is, <strong>en</strong> elk gegev<strong>en</strong> meerdere bewerking<strong>en</strong><br />

vereist;<br />

• wanneer de informatie voor het start<strong>en</strong> van het volg<strong>en</strong>de proces voorwaarts kan word<strong>en</strong><br />

doorgegev<strong>en</strong> alvor<strong>en</strong>s het proces al zijn interne bewerking<strong>en</strong> afgewerkt heeft.<br />

Merk op dat systolische algoritm<strong>en</strong>, waarvan we in Paragraaf 3.2 e<strong>en</strong> voorbeeld zag<strong>en</strong>, ook<br />

dikwijls steun<strong>en</strong> op het principe van pipelining. We illustrer<strong>en</strong> de techniek van pipelining nog<br />

aan de hand van twee bijkom<strong>en</strong>de voorbeeld<strong>en</strong>.<br />

4.1.2 Sorter<strong>en</strong> via pipelining<br />

Zij gegev<strong>en</strong> e<strong>en</strong> rij van n getall<strong>en</strong>, ev<strong>en</strong>als e<strong>en</strong> rij van n processor<strong>en</strong> Pi (“slaves”) <strong>en</strong> één aparte<br />

processor P0 (“master”) die verbond<strong>en</strong> is met P1.<br />

Het algoritme werkt als volgt. Processor P0 stuurt gegev<strong>en</strong>s naar processor P1. Elke processor Pi<br />

ontvangt telk<strong>en</strong>s e<strong>en</strong> getal van processor Pi−1, houdt de kleinste van alle ontvang<strong>en</strong> getall<strong>en</strong> bij,<br />

<strong>en</strong> stuurt de andere getall<strong>en</strong> door naar processor Pi+1. Wanneer alle getall<strong>en</strong> doorgestuurd zijn,<br />

bevat elke processor het correcte getal uit de gesorteerde rij.<br />

Om de gesorteerde rij terug sam<strong>en</strong> te stell<strong>en</strong>, stuurt elke processor zijn getal naar zijn linkerbuur,<br />

<strong>en</strong> vervolg<strong>en</strong>s stuurt hij alle getall<strong>en</strong> die van de rechterbuur binn<strong>en</strong>kom<strong>en</strong> door naar de linkerbuur.<br />

Algoritme 4.1 geeft de pseudocode van dit algoritme voor processor Pi.<br />

Met p = n+1, heeft dit algoritme parallelle uitvoeringstijd Tp(n) = Θ(n) <strong>en</strong> kost Cp(n) = Θ(n 2 ).<br />

Merk op dat dit algoritme e<strong>en</strong> parallelle versie van sorter<strong>en</strong> door tuss<strong>en</strong>voeg<strong>en</strong> is.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


4.1. Pipelining / Sorter<strong>en</strong> & Priemzeef 37<br />

Algoritme 4.1 Sorter<strong>en</strong> via pipelining<br />

Input: rij van n processor<strong>en</strong> P1,...,Pn <strong>en</strong> e<strong>en</strong> master P0; processornummer i > 0; rij van n getall<strong>en</strong><br />

op P0<br />

Output: de gesorteerde rij op master P0<br />

1: receive (x, Pi−1)<br />

2: for j from 2 to n − i do<br />

3: receive (y, Pi−1)<br />

4: if y < x th<strong>en</strong><br />

5: s<strong>en</strong>d (x, Pi+1)<br />

6: Stel x ← y<br />

7: else<br />

8: s<strong>en</strong>d (y, Pi+1)<br />

9: s<strong>en</strong>d (x, Pi−1)<br />

10: for j from 2 to n − i do<br />

11: receive (y, Pi+1)<br />

12: s<strong>en</strong>d (y, Pi−1)<br />

Algoritme 4.2 Priemzeef van Eratosth<strong>en</strong>es (sequ<strong>en</strong>tieel algoritme)<br />

Input: e<strong>en</strong> positief geheel getal n<br />

Output: (p2,..., pn) met pi true als i priem, anders false<br />

1: for i from 2 to n do<br />

2: Stel pi ← true<br />

3: for i from 2 to √ n do<br />

4: if pi th<strong>en</strong><br />

5: for j from i 2 to n step i do<br />

6: Stel pi ← false<br />

4.1.3 Priemzeef via pipeling<br />

De priemzeef van Eratosth<strong>en</strong>es voor het bepal<strong>en</strong> van alle priemgetall<strong>en</strong> kleiner dan of gelijk aan n<br />

start met de rij 2,...,n. Eerst word<strong>en</strong> alle echte veelvoud<strong>en</strong> van 2 geschrapt, vervolg<strong>en</strong>s alle echte<br />

veelvoud<strong>en</strong> van 3, van 5, <strong>en</strong>z. voor alle overblijv<strong>en</strong>de getall<strong>en</strong>, tot aan √ n. Algoritme 4.2 geeft<br />

de pseudocode voor e<strong>en</strong> sequ<strong>en</strong>tiële uitwerking van dit idee. De sequ<strong>en</strong>tiële uitvoeringstijd is<br />

T(n) = O(n 2 ).<br />

Merk op dat het schrapp<strong>en</strong> van de veelvoud<strong>en</strong> iets is wat in parallel kan gebeur<strong>en</strong>, meer bepaald<br />

via pipelining. Het algoritme via pipelining werkt als volgt. Elke processor houdt het eerste<br />

binn<strong>en</strong>kom<strong>en</strong>de getal bij, verwijdert de veelvoud<strong>en</strong> hiervan uit de doorkom<strong>en</strong>de rij <strong>en</strong> stuurt de<br />

niet-veelvoud<strong>en</strong> door naar zijn rechterbuur.<br />

Anders dan bij het sorteerprobleem wet<strong>en</strong> we nu niet op voorhand hoeveel getall<strong>en</strong> elke processor<br />

zal ontvang<strong>en</strong>. Dit kunn<strong>en</strong> we oploss<strong>en</strong> door e<strong>en</strong> speciaal getal (“terminator”) aan het einde van<br />

de rij toe te voeg<strong>en</strong>, dat aangeeft dat de rij t<strong>en</strong> einde is.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


38 Hoofdstuk 4. Ontwerptechniek<strong>en</strong> voor parallelle algoritm<strong>en</strong><br />

Algoritme 4.3 Priemzeef van Eratosth<strong>en</strong>es (parallel algoritme met pipelining)<br />

Input: rij van n processor<strong>en</strong> P1,...,Pn <strong>en</strong> e<strong>en</strong> master P0; processornummer i > 0; rij getall<strong>en</strong><br />

(2,...,n,−1) op P0<br />

Output: processor Pi bevat het i-de priemgetal<br />

1: receive (x, Pi−1)<br />

2: for j from 1 to n do<br />

3: receive (y, Pi−1)<br />

4: if y = −1 th<strong>en</strong><br />

5: break<br />

6: if ymod x = 0 th<strong>en</strong><br />

7: s<strong>en</strong>d (y, Pi+1)<br />

Algoritme 4.3 geeft de pseudocode voor het algoritme voor processor Pi.<br />

4.2 Gebalanceerde bom<strong>en</strong> / Prefixsomm<strong>en</strong><br />

4.2.1 Techniek van gebalanceerde bom<strong>en</strong><br />

Het eerder gezi<strong>en</strong>e PRAM-algoritme voor het berek<strong>en</strong><strong>en</strong> van de som van n getall<strong>en</strong> (Algoritme<br />

2.7) is gebaseerd op e<strong>en</strong> gebalanceerde binaire boom, waarvan de blader<strong>en</strong> de gegev<strong>en</strong> n getall<strong>en</strong><br />

bevatt<strong>en</strong> <strong>en</strong> waarvan de interne topp<strong>en</strong> optelling<strong>en</strong> voorstell<strong>en</strong>. Dit algoritme is e<strong>en</strong> voorbeeld<br />

van de algem<strong>en</strong>e ontwerpstrategie van het opbouw<strong>en</strong> van e<strong>en</strong> gebalanceerde binaire boom<br />

op de inputelem<strong>en</strong>t<strong>en</strong> <strong>en</strong> het voorwaarts <strong>en</strong> achterwaarts doorlop<strong>en</strong> van deze boom van <strong>en</strong> naar<br />

de wortel. E<strong>en</strong> interne top u houdt doorgaans informatie bij omtr<strong>en</strong>t de gegev<strong>en</strong>s die opgeslag<strong>en</strong><br />

zijn in de blader<strong>en</strong> van de deelboom met wortel u. Het welslag<strong>en</strong> van deze strategie hangt gedeeltelijk<br />

af van het bestaan van e<strong>en</strong> snelle manier om de informatie opgeslag<strong>en</strong> in e<strong>en</strong> interne top te<br />

bepal<strong>en</strong> uit de informatie opgeslag<strong>en</strong> in zijn blader<strong>en</strong>. Als tweede voorbeeld van het gebruik van<br />

deze ontwerpstrategie besprek<strong>en</strong> we hier het probleem van het bepal<strong>en</strong> van de prefixsomm<strong>en</strong> van<br />

n getall<strong>en</strong>.<br />

4.2.2 Wat zijn prefixsomm<strong>en</strong>?<br />

Veronderstel dat we de prijz<strong>en</strong> op de financiële markt analyser<strong>en</strong> <strong>en</strong> dat we de hoogste waardering<br />

van e<strong>en</strong> bepaald aandeel w<strong>en</strong>s<strong>en</strong> op te volg<strong>en</strong>. Gegev<strong>en</strong> is e<strong>en</strong> lijst met dagelijkse afsluitwaard<strong>en</strong><br />

van het aandeel. Voor elke dag will<strong>en</strong> we de hoogste waard<strong>en</strong> k<strong>en</strong>n<strong>en</strong> die het aandeel tot die<br />

dag reeds bereikt heeft. We kunn<strong>en</strong> Algoritme 2.7 gebruik<strong>en</strong> om het maximum voor elke dag<br />

te berek<strong>en</strong><strong>en</strong>, maar aangezi<strong>en</strong> we het algoritme apart zoud<strong>en</strong> uitvoer<strong>en</strong> voor elke dag, is deze<br />

manier van werk<strong>en</strong> inefficiënt.<br />

We kunn<strong>en</strong> ook andere problem<strong>en</strong> bed<strong>en</strong>k<strong>en</strong> waarbij, in plaats van één finaal resultaat, ook de<br />

deelresultat<strong>en</strong> tot op elk punt gevraagd zijn. Voorbeeld<strong>en</strong> hiervan zijn de partiële deelsomm<strong>en</strong><br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


4.2. Gebalanceerde bom<strong>en</strong> / Prefixsomm<strong>en</strong> 39<br />

Algoritme 4.4 Sequ<strong>en</strong>tieel algoritme voor het berek<strong>en</strong><strong>en</strong> van de prefixsomm<strong>en</strong><br />

Input: array (a1,...,an), l<strong>en</strong>gte n<br />

Output: de waarde sk = ∑ k i=1 ai, voor 1 ≤ k ≤ n<br />

1: Stel s1 = a1<br />

2: for i from 2 to n do<br />

3: Stel si ← si−1 ⊕ ai<br />

bij het berek<strong>en</strong><strong>en</strong> van gemiddeld<strong>en</strong>, of de voorafberek<strong>en</strong>ing van de overdracht<strong>en</strong> bij het optell<strong>en</strong><br />

van twee getall<strong>en</strong>.<br />

Zoals in het geval van de semigroep-algoritm<strong>en</strong>, hebb<strong>en</strong> we ook bij dit soort problem<strong>en</strong> e<strong>en</strong><br />

binaire associatieve operator ⊕ op e<strong>en</strong> vaste set. Het probleem van de parallelle prefixsomm<strong>en</strong><br />

bestaat erin alle waard<strong>en</strong> sk = ∑ k i=1 ai te berek<strong>en</strong><strong>en</strong> voor 1 ≤ k ≤ n, waarbij sk de k-de prefix<br />

g<strong>en</strong>oemd wordt.<br />

Wanneer de berek<strong>en</strong>ing van ⊕ van twee elem<strong>en</strong>t<strong>en</strong> efficiënt kan gebeur<strong>en</strong> (hetge<strong>en</strong> het geval is<br />

voor de meeste praktische toepassing<strong>en</strong>), dan kunn<strong>en</strong> de prefix<strong>en</strong> in O(n) sequ<strong>en</strong>tiële tijd word<strong>en</strong><br />

berek<strong>en</strong>d, door te steun<strong>en</strong> op de eig<strong>en</strong>schap si = si−1 ⊕ ai, voor 2 ≤ i ≤ n. Algoritme 4.4 geeft<br />

de pseudocode. Merk op dat dit algoritme inher<strong>en</strong>t sequ<strong>en</strong>tieel is.<br />

4.2.3 Berek<strong>en</strong><strong>en</strong> van prefixsomm<strong>en</strong> in het PRAM-model<br />

Gebruik mak<strong>en</strong>d van e<strong>en</strong> gebalanceerde binaire boom kunn<strong>en</strong> we e<strong>en</strong> snel parallel algoritme<br />

voor het berek<strong>en</strong><strong>en</strong> van de prefixsomm<strong>en</strong> opstell<strong>en</strong>. Elke interne top staat voor het uitvoer<strong>en</strong> van<br />

de bewerking ⊕ op zijn kinder<strong>en</strong> tijd<strong>en</strong>s het voorwaarts doorlop<strong>en</strong> van de boom. Dit betek<strong>en</strong>t<br />

dat elke top v de som bevat van de getall<strong>en</strong> opgeslag<strong>en</strong> in de blader<strong>en</strong> van de deelboom met<br />

wortel v. Tijd<strong>en</strong>s het achterwaarts doorlop<strong>en</strong> van de boom word<strong>en</strong> de prefixsomm<strong>en</strong> berek<strong>en</strong>d<br />

van de topp<strong>en</strong> op gegev<strong>en</strong> hoogte in de boom.<br />

E<strong>en</strong> recursieve formulering van het algoritme wordt gegev<strong>en</strong> in Algoritme 4.5.<br />

Voor inputs van grootte n = 2 k vereist het algoritme 2k + 1 tijdse<strong>en</strong>hed<strong>en</strong>: tijd<strong>en</strong>s de eerste<br />

k tijdse<strong>en</strong>hed<strong>en</strong> beweegt de berek<strong>en</strong>ing van de blader<strong>en</strong> van de boom (die a1,...,an bevatt<strong>en</strong>)<br />

naar de wortel; tijd<strong>en</strong>s de laatste k tijdse<strong>en</strong>hed<strong>en</strong> doorlop<strong>en</strong> we de boom in omgekeerde volgorde<br />

<strong>en</strong> berek<strong>en</strong><strong>en</strong> de prefixsomm<strong>en</strong> door gebruik te mak<strong>en</strong> van de data die in de eerste k tijdse<strong>en</strong>hed<strong>en</strong><br />

werd berek<strong>en</strong>d. Merk op dat het ganse algoritme in-place kan word<strong>en</strong> uitgevoerd <strong>en</strong> dat we de<br />

extra variabel<strong>en</strong> <strong>en</strong>kel invoer<strong>en</strong> voor de duidelijkheid.<br />

Volg<strong>en</strong>de stelling bewijst de correctheid <strong>en</strong> de complexiteit van het algoritme in WT-pres<strong>en</strong>tatie.<br />

Stelling 4.2.1. Algoritme 4.5 is e<strong>en</strong> EREW PRAM-algoritme dat de prefixsomm<strong>en</strong> van n getall<strong>en</strong><br />

berek<strong>en</strong>t in parallelle tijd T(n) = Θ(logn) <strong>en</strong> W(n) = Θ(n) bewerking<strong>en</strong>.<br />

Bewijs: Ge<strong>en</strong> <strong>en</strong>kele stap in het algoritme vereist de mogelijkheid voor concurr<strong>en</strong>t read of concurr<strong>en</strong>t<br />

write, zodat het algoritme dus werkt in het EREW PRAM-model.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


40 Hoofdstuk 4. Ontwerptechniek<strong>en</strong> voor parallelle algoritm<strong>en</strong><br />

Algoritme 4.5 Berek<strong>en</strong>ing van prefixsomm<strong>en</strong> op PRAM (recursieve formulering)<br />

Input: rij (a1,...,an) met n = 2 ℓ , p = n processor<strong>en</strong><br />

Output: sk = ∑ k i=1 ai, voor 1 ≤ k ≤ n<br />

1: if n = 1 th<strong>en</strong><br />

2: Stel s1 ← a1<br />

3: return<br />

4: for i from 1 to n/2 pardo<br />

5: Stel bi ← a2i−1 ⊕ a2i<br />

6: Berek<strong>en</strong> recursief prefixsomm<strong>en</strong> (c1...,c n/2) van (b1,...,b n/2)<br />

7: for i from 1 to n pardo<br />

8: case i = 1: Stel s1 ← a1<br />

9: case i ev<strong>en</strong>: Stel si ← c i/2<br />

10: case i onev<strong>en</strong>: Stel si ← c (i−1)/2 ⊕ ai<br />

We bewijz<strong>en</strong> de correctheid van het algoritme door inductie, waarbij we veronderstell<strong>en</strong> dat de<br />

inputgrootte n = 2 ℓ is. Het basisgeval k = 0 wordt correct behandeld door de eerste if-opdracht<br />

van het algoritme. Onderstel nu dat het algoritme correct werkt voor alle rij<strong>en</strong> van l<strong>en</strong>gte 2 k met<br />

k > 0. We bewijz<strong>en</strong> dat het algoritme correct werkt voor alle rij<strong>en</strong> van l<strong>en</strong>gte n = 2 k+1 .<br />

Weg<strong>en</strong>s de inductiehypothese bevatt<strong>en</strong> de variabel<strong>en</strong> (c1...,c n/2), berek<strong>en</strong>d in de recursieve<br />

stap van het algoritme, de prefixsomm<strong>en</strong> van de rij (b1,...,b n/2), waarbij bi ← a2i−1 ⊕ a2i, voor<br />

1 ≤ i ≤ n/2. Meer bepaald is c j = c1 ⊕ c2 ⊕ ··· ⊕ c j, <strong>en</strong> dus c j = a1 ⊕ a2 ⊕ ··· ⊕ a2 j−1 ⊕ a2 j.<br />

M.a.w. c j bevat precies de prefixsomm<strong>en</strong> s2 j, voor 1 ≤ j ≤ n/2. Dus, voor i ev<strong>en</strong>, zij i = 2 j,<br />

hebb<strong>en</strong> we dat si = c i/2.<br />

Anders is ofwel i = 1, ofwel i = 2 j+ 1, voor zekere 1 ≤ j ≤ n/2 − 1. Het geval i = 1 is triviaal.<br />

Voor het geval i = 2 j+ 1, hebb<strong>en</strong> we dat si = s2 j+1 = s2 j ⊕ a2 j+1 = c (i−1)/2 ⊕ ai.<br />

M.a.w. alle gevall<strong>en</strong> word<strong>en</strong> correct afgehandeld in de case-opdracht van het algoritme. Hieruit<br />

volgt dat het algoritme correct werkt.<br />

Vervolg<strong>en</strong>s besprek<strong>en</strong> we de complexiteit van het algoritme. De if-opdracht <strong>en</strong> de twee parallelle<br />

for-luss<strong>en</strong> nem<strong>en</strong> elk Θ(1) parallelle tijd <strong>en</strong> vrag<strong>en</strong> Θ(n) bewerking<strong>en</strong>. De parallelle uitvoeringstijd<br />

T(n) <strong>en</strong> het werk W(n) van het algoritme word<strong>en</strong> dus bepaald voor de volg<strong>en</strong>de recurr<strong>en</strong>te<br />

betrekking<strong>en</strong>:<br />

T(n) = T(n/2)+Θ(1)<br />

W(n) = W(n/2)+Θ(n)<br />

De oplossing<strong>en</strong> van deze recurr<strong>en</strong>te betrekking<strong>en</strong> zijn:<br />

Het algoritme is dus werk-optimaal.<br />

T(n) = Θ(logn)<br />

W(n) = Θ(n)<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


4.2. Gebalanceerde bom<strong>en</strong> / Prefixsomm<strong>en</strong> 41<br />

Algoritme 4.6 Berek<strong>en</strong>ing van prefixsomm<strong>en</strong> op PRAM (niet-recursieve formulering)<br />

Input: rij (a1,...,an) met n = 2 ℓ<br />

Output: tabel C: c0,k = sk = ∑ k j=1 a j (1 ≤ k ≤ n)<br />

1: for i from 1 to n pardo<br />

2: Stel b0,i ← ai<br />

3: for h from 1 to log 2 n do<br />

4: for j from 1 to n/2 h pardo<br />

5: Stel bh, j ← bh−1,2 j ⊕ bh−1,2 j+1<br />

6: for h from log 2 n to 0 do<br />

7: for j from 1 to n/2 h pardo<br />

8: case j = 1: Stel ch,0 ← bh,0<br />

9: case j ev<strong>en</strong>: Stel ch, j ← c h+1, j/2<br />

10: case j onev<strong>en</strong>: Stel ch, j ← c h+1,( j−1)/2 ⊕ bh, j<br />

Tot slot besprek<strong>en</strong> we e<strong>en</strong> niet-recursieve versie van Algoritme 4.5. Daarbij gebruik<strong>en</strong> we twee<br />

hulpvariabel<strong>en</strong> voor het bijhoud<strong>en</strong> van de gebalanceerde boom. De tabel (bh, j), met 0 ≤ h ≤<br />

log 2 n <strong>en</strong> 1 ≤ j ≤ n/2 h , wordt opgebouwd tijd<strong>en</strong>s het voorwaarts doorlop<strong>en</strong> van de boom. De<br />

tabel (ch, j) met 0 ≤ h ≤ log 2 n <strong>en</strong> 1 ≤ j < n/2 h , wordt opgebouwd tijd<strong>en</strong>s het achterwaarts<br />

doorlop<strong>en</strong> van de boom. Merk op dat deze hulpvariabel<strong>en</strong> niet echt nodig zijn <strong>en</strong> dat het algoritme<br />

in-place kan word<strong>en</strong> uitgevoerd.<br />

4.2.4 Berek<strong>en</strong><strong>en</strong> van prefixsomm<strong>en</strong> op e<strong>en</strong> rooster<br />

We veronderstell<strong>en</strong> dat de rij getall<strong>en</strong> verdeeld is over de rij<strong>en</strong> van het rooster. Dan kunn<strong>en</strong> de<br />

prefixsomm<strong>en</strong> als volgt berek<strong>en</strong>d word<strong>en</strong>. Elke rij van het rooster doet e<strong>en</strong> rijrotatie; hierdoor<br />

bevat elke rechtse processor van e<strong>en</strong> rij de som van de getall<strong>en</strong> op zijn rij. Vervolg<strong>en</strong>s doet de<br />

rechterkolom van het rooster e<strong>en</strong> kolomrotatie, hetge<strong>en</strong> ervoor zorgt dat deze processor<strong>en</strong> de<br />

correcte prefixsom bevatt<strong>en</strong>. Dan stuurt elke rechtse processor van e<strong>en</strong> rij zijn prefixsom naar<br />

zijn onderbuur. Tot slot doet elke rij (behalve de eerste) weer e<strong>en</strong> rijrotatie. Hierdoor bevat<br />

uiteindelijk elke processor de correcte prefixsom.<br />

Beschouw<strong>en</strong> we de performantie van dit algoritme. Zij p = n. De parallelle uitvoeringstijd is<br />

Tp(n) = Θ( √ p) = Θ( √ n). De kost is Cp(n) = Θ(p 3/2 ) = Θ(n 3/2 ). M.a.w. het algoritme is niet<br />

kost-optimaal.<br />

Om het algoritme te optimaliser<strong>en</strong> bepal<strong>en</strong> we de waarde van p waarvoor p 3/2 = n, of m.a.w.<br />

p = n 2/3 . Dan hebb<strong>en</strong> we e<strong>en</strong> rooster van n 1/3 × n 1/3 processor<strong>en</strong>, <strong>en</strong> elke processor verwerkt<br />

n 1/3 elem<strong>en</strong>t<strong>en</strong> sequ<strong>en</strong>tieel. De parallelle uitvoeringstijd van dit aangepaste algoritme is Tp(n) =<br />

Θ( √ p+n 1/3 ) = Θ(n 1/3 ). De kost is Cp(n) = Θ(p × n 1/3 ) = Θ(n), <strong>en</strong> het aangepaste algoritme<br />

is dus kost-optimaal.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


42 Hoofdstuk 4. Ontwerptechniek<strong>en</strong> voor parallelle algoritm<strong>en</strong><br />

4.2.5 Berek<strong>en</strong><strong>en</strong> van prefixsomm<strong>en</strong> op e<strong>en</strong> hyperkubus<br />

Zij gegev<strong>en</strong> e<strong>en</strong> rij (a0,...,an−1) met n = 2 d elem<strong>en</strong>t<strong>en</strong>, waarbij elke ak opgeslag<strong>en</strong> is in het<br />

lokale geheug<strong>en</strong> van processor Pk van e<strong>en</strong> hyperkubus Qd. Gevraagd is de prefixsom sk = ∑ k i=0 ai<br />

te berek<strong>en</strong><strong>en</strong> <strong>en</strong> op te slaan in Pk, voor alle 0 ≤ k < n.<br />

Het algoritme volgt de gebruikelijke werkwijze op de hyperkubus, nl. via communicatie in elke<br />

dim<strong>en</strong>sie, gaande van de laagste naar de hoogste dim<strong>en</strong>sie. Elke processor Pk houdt twee waard<strong>en</strong><br />

xk <strong>en</strong> yk bij. Initieel krijg<strong>en</strong> xk <strong>en</strong> yk beid<strong>en</strong> de waarde ak. Beschouw<strong>en</strong> we nu stap i uit het<br />

algoritme. Zij processor<strong>en</strong> Pk <strong>en</strong> Pℓ bur<strong>en</strong> in dim<strong>en</strong>sie i, k < ℓ. Dan wissel<strong>en</strong> Pk <strong>en</strong> Pℓ hun<br />

waard<strong>en</strong> yk <strong>en</strong> yℓ uit. Processor Pk houdt zijn oorspronkelijke waarde van xk <strong>en</strong> vervangt yk door<br />

yk ⊕yℓ. Processor Pℓ vervangt zijn waarde van xℓ door xℓ ⊕yk <strong>en</strong> vervangt ook yℓ door yk ⊕yℓ. Na<br />

d = log 2 n stapp<strong>en</strong>, e<strong>en</strong> in elke dim<strong>en</strong>sie, bevat elke xk uiteindelijk de gevraagde prefixsom sk.<br />

4.3 Partitionering / Merge<br />

4.3.1 Techniek van partitioner<strong>en</strong><br />

De techniek van partitioner<strong>en</strong> bestaat in<br />

(1) het opsplits<strong>en</strong> van het gegev<strong>en</strong> probleem in p onafhankelijke deelproblem<strong>en</strong> die ongeveer<br />

ev<strong>en</strong> groot zijn, waarbij p het aantal beschikbare processor<strong>en</strong> is, <strong>en</strong><br />

(2) het oploss<strong>en</strong> in parallel van deze deelproblem<strong>en</strong>.<br />

In zijn e<strong>en</strong>voudigste vorm bestaat deze strategie in het opsplits<strong>en</strong> van de inputgegev<strong>en</strong>s in p nietoverlapp<strong>en</strong>de<br />

stukk<strong>en</strong>, gevolgd door het in parallel oploss<strong>en</strong> van de deelproblem<strong>en</strong> geassocieerd<br />

met deze p stukk<strong>en</strong>. In de meeste gevall<strong>en</strong> zal het opsplits<strong>en</strong> van het probleem in onafhankelijke<br />

deelproblem<strong>en</strong> echter niet zo e<strong>en</strong>voudig zijn.<br />

We illustrer<strong>en</strong> deze techniek bij het merg<strong>en</strong> van twee gesorteerde rij<strong>en</strong>. Zij A = (a1,...,an)<br />

<strong>en</strong> B = (b1,...,bn) twee niet-dal<strong>en</strong>de rij<strong>en</strong> van elem<strong>en</strong>t<strong>en</strong> uit e<strong>en</strong> geord<strong>en</strong>d universum S. We<br />

beschouw<strong>en</strong> het probleem van het sam<strong>en</strong>voeg<strong>en</strong> van deze twee rij<strong>en</strong> tot één <strong>en</strong>kele gesorteerde<br />

rij C = (c1,...,c2n). Er zijn e<strong>en</strong>voudige sequ<strong>en</strong>tiële algoritm<strong>en</strong> voor dit probleem die lineaire<br />

tijd vereis<strong>en</strong>. Onze bedoeling hier is het opstell<strong>en</strong> van e<strong>en</strong> parallelle oplossing die gebaseerd is<br />

op het partitioner<strong>en</strong> van rij<strong>en</strong> A <strong>en</strong> B in meerdere par<strong>en</strong> van deelrij<strong>en</strong> op zodanige manier dat we<br />

de gesorteerde rij C kunn<strong>en</strong> bekom<strong>en</strong> door in parallel de par<strong>en</strong> van deelrij<strong>en</strong> te merg<strong>en</strong>.<br />

4.3.2 E<strong>en</strong> e<strong>en</strong>voudig merge-algoritme<br />

We beginn<strong>en</strong> met <strong>en</strong>kele definities. Zij X = (x1,...,xn) e<strong>en</strong> rij elem<strong>en</strong>t<strong>en</strong> uit het universum S.<br />

Zij x ∈ S. De rank van x in X, g<strong>en</strong>oteerd als rank(x : X) is het aantal elem<strong>en</strong>t<strong>en</strong> van X dat<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


4.3. Partitionering / Merge 43<br />

kleiner dan of gelijk is aan x. Zij Y = (y1,...,yk) e<strong>en</strong> willekeurige rij van elem<strong>en</strong>t<strong>en</strong> uit S. Het<br />

rank<strong>en</strong> van Y in X is het probleem van het bepal<strong>en</strong> van de rij rank(Y : X) = (r1,...,rk), waarbij<br />

ri = rank(yi : X).<br />

Zonder verlies van algeme<strong>en</strong>heid kunn<strong>en</strong> we veronderstell<strong>en</strong> dat alle elem<strong>en</strong>t<strong>en</strong> die in de gegev<strong>en</strong><br />

rij<strong>en</strong> A <strong>en</strong> B optred<strong>en</strong>, verschill<strong>en</strong>d zijn. Meer bepaald komt ge<strong>en</strong> <strong>en</strong>kele elem<strong>en</strong>t van A voor in B.<br />

Het probleem van merg<strong>en</strong> kan word<strong>en</strong> beschouwd als het bepal<strong>en</strong> van de rank van elk elem<strong>en</strong>t x<br />

uit A <strong>en</strong> B in de rij A ∪ B. Als rank(x : A ∪ B) = i, dan is ci = x, waarbij ci het i-de elem<strong>en</strong>t van<br />

de gew<strong>en</strong>ste gesorteerde rij is. Aangezi<strong>en</strong> rank(x : A ∪ B) = rank(x : A)+rank(x : B), kunn<strong>en</strong><br />

we het probleem van merg<strong>en</strong> oploss<strong>en</strong> door de twee gehele rij<strong>en</strong> rank(A : B) <strong>en</strong> rank(B : A) te<br />

bepal<strong>en</strong>.<br />

We beschrijv<strong>en</strong> nu e<strong>en</strong> algoritme om rank(B : A) te bepal<strong>en</strong>. Hetzelfde algoritme kan gebruikt<br />

word<strong>en</strong> om rank(A : B) te bepal<strong>en</strong>. Zijn bi e<strong>en</strong> willekeurig elem<strong>en</strong>t van B. Aangezi<strong>en</strong> A gesorteerd<br />

is, kunn<strong>en</strong> we de rank van bi in A vind<strong>en</strong> door gebruik te mak<strong>en</strong> van de binaire zoekmethode.<br />

We vergelijk<strong>en</strong> bi met het middelste elem<strong>en</strong>t van A. Afhankelijk van de uitkomst van<br />

deze vergelijking kunn<strong>en</strong> we het zoek<strong>en</strong> beperk<strong>en</strong> tot de onderste of de bov<strong>en</strong>ste helft van A. Dit<br />

proces wordt herhaald totdat bi geïsoleerd is tuss<strong>en</strong> twee ope<strong>en</strong>volg<strong>en</strong>de elem<strong>en</strong>t<strong>en</strong> van A, m.a.w.<br />

a j(i) < bi < a j(i)+1, waarbij rank(bi : A) = j(i). Merk op dat we hier gebruik mak<strong>en</strong> van het feit<br />

dat de elem<strong>en</strong>t<strong>en</strong> van A <strong>en</strong> B allemaal verschill<strong>en</strong>d zijn.<br />

Dit algoritme bepaalt de rank van e<strong>en</strong> willekeurig elem<strong>en</strong>t van B in A in sequ<strong>en</strong>tiële tijd Θ(logn).<br />

Het is onmiddellijk duidelijk dat we deze methode in parallel kunn<strong>en</strong> uitvoer<strong>en</strong> voor alle elem<strong>en</strong>t<strong>en</strong><br />

van B. Dit levert e<strong>en</strong> parallel algoritme voor het bepal<strong>en</strong> van rank(B : A) met parallelle uitvoeringstijd<br />

Θ(logn). Dit impliceert e<strong>en</strong> parallel algoritme met uitvoeringstijd Θ(logn) voor het<br />

merg<strong>en</strong> van twee rij<strong>en</strong> van l<strong>en</strong>gte n. Het totaal aantal bewerking<strong>en</strong> gebruikt door dit algoritme is<br />

echter W(n) = Θ(nlogn), zodat het algoritme dus niet werk-optimaal is (aangezi<strong>en</strong> sequ<strong>en</strong>tiële<br />

algoritm<strong>en</strong> met lineaire uitvoeringstijd bestaan).<br />

4.3.3 Parallel algoritme voor merge via partitioner<strong>en</strong><br />

E<strong>en</strong> werk-optimaal parallel algoritme kan als volgt bekom<strong>en</strong> word<strong>en</strong>. Kies ongeveer n/log 2 n<br />

elem<strong>en</strong>t<strong>en</strong> elk uit A <strong>en</strong> B die A <strong>en</strong> B partitioner<strong>en</strong> in blokk<strong>en</strong> van ongeveer gelijke grootte. Pas<br />

de binaire zoekmethode toe om elk van de gekoz<strong>en</strong> elem<strong>en</strong>t<strong>en</strong> te rank<strong>en</strong> in de andere rij. Deze<br />

stap reduceert het probleem tot het merg<strong>en</strong> van e<strong>en</strong> aantal par<strong>en</strong> van deelrij<strong>en</strong>, die elk Θ(logn)<br />

elem<strong>en</strong>t<strong>en</strong> hebb<strong>en</strong>. Dan kunn<strong>en</strong> we e<strong>en</strong> optimaal sequ<strong>en</strong>tieel algoritme gebruik<strong>en</strong> om elk paar<br />

deelrij<strong>en</strong> te merg<strong>en</strong> tot e<strong>en</strong> gesorteerde deelrij, die deel uitmaakt van van de uiteindelijk gew<strong>en</strong>ste<br />

gesorteerde rij.<br />

Bij het uitwerk<strong>en</strong> van de details beperk<strong>en</strong> we ons voor de e<strong>en</strong>voud tot e<strong>en</strong> lichtjes ander algoritme.<br />

Algoritme 4.7 geeft de pseudocode voor het partitioneringsalgoritme, dat de belangrijkste<br />

compon<strong>en</strong>t van het gehele merge-algoritme zal uitmak<strong>en</strong>. In deze beschrijving veronderstell<strong>en</strong><br />

we niet dat de l<strong>en</strong>gte van de twee deelrij<strong>en</strong> noodzakelijk gelijk zal zijn.<br />

Volg<strong>en</strong>de stelling bewijst de correctheid <strong>en</strong> de complexiteit van dit algoritme.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


44 Hoofdstuk 4. Ontwerptechniek<strong>en</strong> voor parallelle algoritm<strong>en</strong><br />

Algoritme 4.7 Partitioneringsalgoritme<br />

Input: A = (a1,...,an) <strong>en</strong> B = (b1,...,bm) stijg<strong>en</strong>d, log 2 m <strong>en</strong> k = m/log 2 m geheel<br />

Output: k par<strong>en</strong> deelrij<strong>en</strong> (Ai,Bi), zodat |Bi| = log 2 m, <strong>en</strong> elk elem<strong>en</strong>t van Ai <strong>en</strong> Bi groter dan<br />

elk elem<strong>en</strong>t van Ai−1 <strong>en</strong> Bi−1, voor elke 1 ≤ i < k<br />

1: Stel j0 ← 0; jk ← n<br />

2: for i from 1 to k − 1 pardo<br />

3: Bepaal rank(bilog 2 m : A) via de binaire zoekmethode<br />

4: Stel ji ← rank(bilog 2 m : A)<br />

5: for i from 0 to k − 1 pardo<br />

6: Stel Bi ← (bilog 2 m+1,...,b (i+1)log 2 m)<br />

7: Stel Ai ← (a ji+1,...,aji+1 )<br />

Stelling 4.3.1. Zij C de gesorteerde rij bekom<strong>en</strong> door het merg<strong>en</strong> van de twee gesorteerde rij<strong>en</strong><br />

A <strong>en</strong> B, met l<strong>en</strong>gte resp. n <strong>en</strong> m. Algoritme 4.7 partitioneert A <strong>en</strong> B in par<strong>en</strong> deelrij<strong>en</strong> (Ai,Bi)<br />

zodanig dat |Bi| = Θ(log 2 m), ∑i |Ai| = n <strong>en</strong> C = (C0,C1,...), waarbij Ci de gesorteerde deelrij<br />

is die bekom<strong>en</strong> werd door Ai <strong>en</strong> Bi te merg<strong>en</strong>. Het algoritme heeft parallelle uitvoeringstijd<br />

T(n) = Θ(logn) <strong>en</strong> vereist W(n) = O(n+m) bewerking<strong>en</strong>.<br />

Bewijs: We bewijz<strong>en</strong> eerst dat elk elem<strong>en</strong>t in de deelrij<strong>en</strong> Ai <strong>en</strong> Bi groter is dan elk elem<strong>en</strong>t in<br />

Ai−1 <strong>en</strong> Bi−1, voor elke 1 ≤ i < k. De twee kleinste elem<strong>en</strong>t<strong>en</strong> van Ai <strong>en</strong> Bi zijn resp. a j(i)+1 <strong>en</strong><br />

bilog 2 m+1. De tweede grootste elem<strong>en</strong>t<strong>en</strong> van Ai−1 <strong>en</strong> Bi−1 zijn resp. a j(i) <strong>en</strong> bilog 2 m. Aangezi<strong>en</strong><br />

rank(bilog 2 m : A) = j(i), wet<strong>en</strong> we dat a j(i) < bilog 2 m < a j(i)+1. Hieruit volgt dat bilog 2 m+1 ><br />

bilog 2 m > a j(i) <strong>en</strong> ook dat a j(i) > bilog 2 m. M.a.w. elk van de elem<strong>en</strong>t<strong>en</strong> uit Ai <strong>en</strong> Bi is groter dan<br />

elk van de elem<strong>en</strong>t<strong>en</strong> uit Ai−1 <strong>en</strong> Bi−1. Hieruit volgt de correctheid van het algoritme.<br />

De complexiteitsanalyse gebeurt als volgt. Stap 1 neemt Θ(1) sequ<strong>en</strong>tiële tijd. De eerste parallelle<br />

for-lus vereist Θ(logn) parallelle tijd, aangezi<strong>en</strong> de binaire zoekmethode op alle gew<strong>en</strong>ste<br />

elem<strong>en</strong>t<strong>en</strong> in parallel uitgevoerd wordt. Het aantal bewerking<strong>en</strong> in deze lus is gegev<strong>en</strong><br />

door Θ(logn×(m/logm))=O(n+m), aangezi<strong>en</strong> (mlog 2 n/log 2 m) < (mlog 2 (n+m)/log 2 m) <<br />

n+m, voor m ≥ 4. De laatste parallelle for-lus vereist Θ(1) tijd <strong>en</strong> e<strong>en</strong> lineair aantal bewerking<strong>en</strong>.<br />

Het totale algoritme vereist dus T(n) = Θ(logn) parallelle uitvoeringstijd <strong>en</strong> W(n) = O(n+m)<br />

bewerking<strong>en</strong>.<br />

Wanneer we Algoritme 4.7 toepass<strong>en</strong> op het merge-probleem (waarbij we twee rij<strong>en</strong> van gelijke<br />

l<strong>en</strong>gte n hebb<strong>en</strong>), dan levert dat e<strong>en</strong> stel onafhankelijke merge-deelproblem<strong>en</strong>. Dit is de ess<strong>en</strong>tie<br />

van de partitioneringsstrategie.<br />

Nu w<strong>en</strong>s<strong>en</strong> we elk merge-deelprobleem op te loss<strong>en</strong> in Θ(logn) tijd, zodanig dat het totaal aantal<br />

gebruikte bewerking<strong>en</strong> proportioneel is met de grootte van de deelproblem<strong>en</strong>. Deze uitvoeringstijd<br />

kunn<strong>en</strong> we als volgt bekom<strong>en</strong>.<br />

Beschouw het merge-deelprobleem voor e<strong>en</strong> willekeurig paar (Ai,Bi). Merk op dat |Bi| = log 2 n<br />

voor alle i. Als |Ai| = O(logn), dan kunn<strong>en</strong> we (Ai,Bi) merg<strong>en</strong> in Θ(logn) sequ<strong>en</strong>tiële tijd door<br />

e<strong>en</strong> optimaal sequ<strong>en</strong>tieel algoritme te gebruik<strong>en</strong>. Anders gebruik<strong>en</strong> we Algoritme 4.7 om Ai te<br />

partitioner<strong>en</strong> in blokk<strong>en</strong> die elk O(logn) groot zijn (in dit geval speelt Ai de rol van B <strong>en</strong> Bi speelt<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


4.4. Accelerated cascading / Maximum bepal<strong>en</strong> 45<br />

de rol van A). Deze stap kost Θ(loglogn) tijd <strong>en</strong> O(|Ai|) bewerking<strong>en</strong>. We kunn<strong>en</strong> er dus voor<br />

zorg<strong>en</strong> dat elke deelrij l<strong>en</strong>gte Θ(logn) heeft, zonder de asymptotische complexiteit te verhog<strong>en</strong>.<br />

Dit leidt tot de volg<strong>en</strong>de stelling:<br />

Stelling 4.3.2. Zij A <strong>en</strong> B twee gesorteerde rij<strong>en</strong>, elk van l<strong>en</strong>gte n. Dan kunn<strong>en</strong> A <strong>en</strong> B via merge<br />

sam<strong>en</strong>gevoegd word<strong>en</strong> in T(n) = Θ(logn) tijd <strong>en</strong> W(n) = Θ(n) bewerking<strong>en</strong>.<br />

Merk op dat Algoritme 4.7 de binaire zoekmethode gebruikt om tegelijkertijd meerdere elem<strong>en</strong>t<strong>en</strong><br />

van B in A te rank<strong>en</strong>. M.a.w. de mogelijkheid van concurr<strong>en</strong>t read moet bestaan. Maar<br />

concurr<strong>en</strong>t write is voor dit algoritme niet nodig. Het algoritme werkt dus in het CREW PRAMmodel.<br />

4.4 Accelerated cascading / Maximum bepal<strong>en</strong><br />

4.4.1 Bepal<strong>en</strong> van het maximum<br />

Zoals reeds eerder gezi<strong>en</strong> bestaat er e<strong>en</strong> parallel algoritme voor het bepal<strong>en</strong> van het grootste<br />

elem<strong>en</strong>t uit e<strong>en</strong> rij X = (x1,...,xn), dat gebruik maakt van de techniek van gebalanceerde bom<strong>en</strong>.<br />

De parallelle uitvoeringstijd van dit algoritme is T(n)=Θ(logn) <strong>en</strong> het totale aantal bewerking<strong>en</strong><br />

is W(n) = Θ(n). Dit algoritme is werk-optimaal, want het optimale sequ<strong>en</strong>tiële algoritme voor<br />

dit probleem heeft lineaire uitvoeringstijd.<br />

Dit probleem is e<strong>en</strong> interessant voorbeeld van de strategie van accelerated cascading. Deze<br />

techniek bestaat uit het combiner<strong>en</strong> van e<strong>en</strong> traag maar optimaal algoritme met e<strong>en</strong> snel maar<br />

niet-optimaal algoritme, tot e<strong>en</strong> snel <strong>en</strong> optimaal algoritme.<br />

We bekijk<strong>en</strong> nu hoe we e<strong>en</strong> sneller parallel algoritme voor het bepal<strong>en</strong> van het maximum kunn<strong>en</strong><br />

bekom<strong>en</strong>. Daartoe gebruik<strong>en</strong> we, in plaats van e<strong>en</strong> gebalanceerde binaire boom (die logaritmische<br />

diepte heeft), e<strong>en</strong> boom van dubbel-logaritmische diepte. We construer<strong>en</strong> e<strong>en</strong> gebalanceerde<br />

boom met als blader<strong>en</strong> de waard<strong>en</strong> xi, zodanig dat het aantal kinder<strong>en</strong> van e<strong>en</strong> top gelijk<br />

is aan ⌈ √ nv⌉, waarbij nv het aantal blader<strong>en</strong> in e<strong>en</strong> deelboom met wortel v voorstelt. Elke interne<br />

top wordt gebruikt om het grootste elem<strong>en</strong>t van zijn deelboom bij te houd<strong>en</strong>. Voorwaard<strong>en</strong> op<br />

het aantal kinder<strong>en</strong> van e<strong>en</strong> top zull<strong>en</strong> er voor zorg<strong>en</strong> dat de boom dubbel-logaritmische diepte<br />

heeft. Het welslag<strong>en</strong> van deze strategie hangt af van het bestaan van e<strong>en</strong> parallel algoritme met<br />

constante uitvoeringstijd voor het uitvoer<strong>en</strong> van de bewerking voorgesteld door e<strong>en</strong> interne top,<br />

m.a.w. het bepal<strong>en</strong> van het grootste van e<strong>en</strong> willekeurig aantal elem<strong>en</strong>t<strong>en</strong>. We besprek<strong>en</strong> dus<br />

eerst het ontwerp<strong>en</strong> van dergelijk algoritme.<br />

4.4.2 Bepal<strong>en</strong> van het maximum in constante tijd<br />

Zij A e<strong>en</strong> rij van p elem<strong>en</strong>t<strong>en</strong>, waarvan we het grootste moet<strong>en</strong> bepal<strong>en</strong>. In Algoritme 4.8 gebeurt<br />

e<strong>en</strong> vergelijking tuss<strong>en</strong> elk paar elem<strong>en</strong>t<strong>en</strong> van A. Het grootste elem<strong>en</strong>t kan geïd<strong>en</strong>tificeerd<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


46 Hoofdstuk 4. Ontwerptechniek<strong>en</strong> voor parallelle algoritm<strong>en</strong><br />

Algoritme 4.8 Bepal<strong>en</strong> van het maximum in constante tijd<br />

Input: array A = (a1,...,ap) met p verschill<strong>en</strong>de getall<strong>en</strong><br />

Output: boolean array M = (m1,...,mp) met mi = true als <strong>en</strong> slechts als ai het maximum van A<br />

is<br />

1: for 1 ≤ i, j ≤ p pardo<br />

2: if ai ≥ a j th<strong>en</strong><br />

3: Stel bi, j ← true<br />

4: else<br />

5: Stel bi, j ← false<br />

6: for 1 ≤ i ≤ p pardo<br />

7: mi ← bi,1 ∧ bi,2 ∧...bi,p<br />

word<strong>en</strong> als het elem<strong>en</strong>t dat in al zijn vergelijking<strong>en</strong> de “winnaar” is. Daartoe houdt het algoritme<br />

e<strong>en</strong> tweedim<strong>en</strong>sionale boolean array B = (bi, j) bij, die het resultaat van elke vergelijking<br />

opslaat. Vervolg<strong>en</strong>s wordt e<strong>en</strong> array M opgebouwd. Wanneer het algoritme eindigt, heeft arrayelem<strong>en</strong>t<br />

mi de waarde true als <strong>en</strong> slechts als elem<strong>en</strong>t ai het grootste elem<strong>en</strong>t uit A is.<br />

Merk op dat dit algoritme concurr<strong>en</strong>t read nodig heeft. Bov<strong>en</strong>di<strong>en</strong> kan de tweede parallelle forlus<br />

uitgevoerd word<strong>en</strong> in constante tijd, als we concurr<strong>en</strong>t write toelat<strong>en</strong>. Dit algoritme werkt dus<br />

in het CRCW PRAM-model in Θ(1) tijd <strong>en</strong> gebruikt Θ(p 2 ) bewerking<strong>en</strong>. Dit levert de volg<strong>en</strong>de<br />

stelling.<br />

Stelling 4.4.1. Het grootste van p elem<strong>en</strong>t<strong>en</strong> kan op CRCW PRAM bepaald word<strong>en</strong> in Θ(1)<br />

parallelle tijd <strong>en</strong> Θ(p 2 ) bewerking<strong>en</strong>.<br />

4.4.3 Algoritme voor het maximum in dubbel-logaritmische tijd<br />

In e<strong>en</strong> gewortelde boom is het niveau van e<strong>en</strong> top v bepaald door het aantal bog<strong>en</strong> op het pad<br />

van de wortel naar v. De wortel heeft dus niveau 0. We definiër<strong>en</strong> nu de boom van dubbellogaritmische<br />

diepte met n blader<strong>en</strong>. Voor de e<strong>en</strong>voud veronderstell<strong>en</strong> we dat n = 22k voor zekere<br />

k geheel.<br />

De wortel van de boom heeft √ n = 22k−1 kinder<strong>en</strong>, elk van die kinder<strong>en</strong> heeft op zijn beurt 22k−2 kinder<strong>en</strong>, <strong>en</strong>z. Algeme<strong>en</strong>, e<strong>en</strong> top op niveau i heeft 22k−i−1 kinder<strong>en</strong>, voor 0 ≤ i ≤ k−1. T<strong>en</strong>slotte<br />

heeft elke top op niveau k nog 2 blader<strong>en</strong> als kinder<strong>en</strong>.<br />

Volg<strong>en</strong>de eig<strong>en</strong>schapp<strong>en</strong> zijn e<strong>en</strong>voudig (evt. met behulp van inductie) te bewijz<strong>en</strong>:<br />

(1) Het aantal topp<strong>en</strong> op niveau i is gegev<strong>en</strong> door n/2 2k−i<br />

(2) Het aantal topp<strong>en</strong> op niveau k is gegev<strong>en</strong> door n/2 = 22k−1. (3) De diepte van de boom is k+ 1 = log 2 log 2 n+1<br />

= 2 2k −2 k−i<br />

, voor 0 ≤ i < k.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


4.4. Accelerated cascading / Maximum bepal<strong>en</strong> 47<br />

Deze boom met dubbel-logaritmische diepte kan gebruikt word<strong>en</strong> voor het bepal<strong>en</strong> van het grootste<br />

van n elem<strong>en</strong>t<strong>en</strong>. Elke interne top houdt het grootste van de elem<strong>en</strong>t<strong>en</strong> in zijn deelboom bij.<br />

Het algoritme gaat niveau per niveau vooruit, van onder naar bov<strong>en</strong>, start<strong>en</strong>d met de blader<strong>en</strong>.<br />

Gebruik mak<strong>en</strong>d van Algoritme 4.8 kan het grootste in elke top bepaald word<strong>en</strong> in constante<br />

tijd. Hieruit volgt dat het algoritme het grootste van n elem<strong>en</strong>t berek<strong>en</strong>t in parallelle tijd<br />

T(n) = Θ(loglogn), hetge<strong>en</strong> expon<strong>en</strong>tieel sneller is dan het eerder gezi<strong>en</strong>e Θ(logn) algoritme.<br />

Vervolg<strong>en</strong>s prober<strong>en</strong> we het aantal bewerking<strong>en</strong> van dit algoritme in te schatt<strong>en</strong>. Het werk Wti (n)<br />

per top ti op niveau i wordt gegev<strong>en</strong> door<br />

Dit levert als totaal werk Wi(n) voor niveau i:<br />

Wti (n) = Θ((22k−i−1)<br />

2 ) = Θ(2 2k−i<br />

).<br />

Wi(n) = Θ(2 2k−i<br />

Het totale werk van het algoritme wordt bepaald door<br />

W(n) =<br />

k<br />

∑<br />

i=0<br />

M.a.w. het algoritme is niet werk-optimaal.<br />

× 2 2k −2 k−i<br />

) = Θ(2 2k<br />

) = Θ(n).<br />

Wi(n) = Θ(nloglogn).<br />

4.4.4 Het snelle algoritme optimaal mak<strong>en</strong><br />

We hebb<strong>en</strong> nu twee algoritm<strong>en</strong> voor het bepal<strong>en</strong> van het grootste van e<strong>en</strong> rij elem<strong>en</strong>t<strong>en</strong>. Het<br />

eerste, gebaseerd op e<strong>en</strong> binaire boom (met logaritmische diepte), is optimaal <strong>en</strong> vereist logaritmische<br />

tijd. Het tweede, gebaseerd op de boom met dubbel-logaritmische diepte, is niet optimaal,<br />

maar is “zeer snel” (dubbel-logaritmische tijd). In dergelijke gevall<strong>en</strong> kunn<strong>en</strong> we prober<strong>en</strong> de<br />

strategie van accelerated cascading te gebruik<strong>en</strong> om de twee algoritm<strong>en</strong> te combiner<strong>en</strong> tot e<strong>en</strong><br />

optimaal <strong>en</strong> zeer snel algoritme. In algem<strong>en</strong>e term<strong>en</strong> werkt de techniek als volgt:<br />

1. Voer het optimale algoritme uit, totdat de probleemgrootte gereduceerd is tot e<strong>en</strong> zekere<br />

drempelwaarde.<br />

2. Werk dan verder met het zeer snelle maar niet-optimale algoritme.<br />

We bekijk<strong>en</strong> nu hoe we deze strategie kunn<strong>en</strong> gebruik<strong>en</strong> bij het bepal<strong>en</strong> van het maximum van<br />

n elem<strong>en</strong>t<strong>en</strong>.<br />

In fase 1 voer<strong>en</strong> we het algoritme met de binaire boom uit, start<strong>en</strong>d vanaf de blader<strong>en</strong>, verderwerk<strong>en</strong>d<br />

voor ⌈log 2 log 2 log 2 n⌉ niveau’s. Aangezi<strong>en</strong> het aantal kandidat<strong>en</strong> in elk niveau gehalveerd<br />

wordt, wet<strong>en</strong> we dat het maximum zich bevindt tuss<strong>en</strong> de n ′ = O(n/loglogn) overblijv<strong>en</strong>de<br />

elem<strong>en</strong>t<strong>en</strong> op het einde van deze fase. Het totale aantal tot nu toe gebruikte bewerking<strong>en</strong> is<br />

W1(n) = O(n) <strong>en</strong> de corresponder<strong>en</strong>de tijd is T1(n) = O(logloglogn).<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


48 Hoofdstuk 4. Ontwerptechniek<strong>en</strong> voor parallelle algoritm<strong>en</strong><br />

In fase 2 gebruik<strong>en</strong> we de dubbel-logaritmische boom op de n ′ overblijv<strong>en</strong>de elem<strong>en</strong>t<strong>en</strong>. Deze<br />

fase vereist tijd T2(n) = Θ(loglogn ′ ) = Θ(loglogn) <strong>en</strong> werk W2(n) = Θ(n ′ loglogn ′ ) = O(n).<br />

Het totale algoritme is dus optimaal <strong>en</strong> vereist Θ(loglogn) parallelle tijd.<br />

Stelling 4.4.2. Het grootste van e<strong>en</strong> rij van n elem<strong>en</strong>t<strong>en</strong> kan optimaal bepaald word<strong>en</strong> in Θ(loglogn)<br />

tijd op e<strong>en</strong> CRCW PRAM.<br />

4.4.5 Opmerking: speciaal geval<br />

E<strong>en</strong> belangrijk speciaal geval van de techniek van accelerated cascading bestaat in het gebruik<br />

van e<strong>en</strong> optimaal sequ<strong>en</strong>tieel algoritme in fase 1. Ook bij het probleem van het bepal<strong>en</strong> van het<br />

maximum kan op die manier e<strong>en</strong> optimaal algoritme met uitvoeringstijd Θ(loglogn) bekom<strong>en</strong><br />

word<strong>en</strong>.<br />

Daartoe partitioner<strong>en</strong> we de input in n/log 2 log 2 n blokk<strong>en</strong> Bi, met elk ongeveer log 2 log 2 n elem<strong>en</strong>t<strong>en</strong>.<br />

Via het sequ<strong>en</strong>tiële algoritme bepal<strong>en</strong> we dan het maximum van elk blok; dit kan voor<br />

de verschill<strong>en</strong>de blokk<strong>en</strong> in parallel gebeur<strong>en</strong>. Vervolg<strong>en</strong>s werk<strong>en</strong> we verder via de boom van<br />

dubbel-logaritmische diepte om het maximum te bepal<strong>en</strong>.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


Hoofdstuk 5<br />

<strong>Parallelle</strong> sorteeralgoritm<strong>en</strong><br />

Sorter<strong>en</strong> is e<strong>en</strong> belangrijk probleem met vele toepassing<strong>en</strong>. Het ligt dan ook voor de hand om<br />

parallelle sorteeralgoritm<strong>en</strong> te ontwikkel<strong>en</strong>. In het sequ<strong>en</strong>tiële geval maakt m<strong>en</strong> doorgaans onderscheid<br />

tuss<strong>en</strong> twee klass<strong>en</strong> sorteeralgoritm<strong>en</strong>.<br />

Sorteeralgoritm<strong>en</strong> gebaseerd op vergelijking<strong>en</strong> sorter<strong>en</strong> door herhaaldelijk twee elem<strong>en</strong>t<strong>en</strong> te<br />

vergelijk<strong>en</strong> <strong>en</strong> ze te verwissel<strong>en</strong> indi<strong>en</strong> ze in de verkeerde volgorde staan. Voorbeeld<strong>en</strong> hiervan<br />

zijn bubblesort, mergesort <strong>en</strong> quicksort. Deze sorteeralgoritm<strong>en</strong> hebb<strong>en</strong> e<strong>en</strong> theoretische<br />

ondergr<strong>en</strong>s Ω(nlogn) voor de (sequ<strong>en</strong>tiële) complexiteit.<br />

Sorteeralgoritm<strong>en</strong> die niet gebaseerd zijn op vergelijking<strong>en</strong> gebruik<strong>en</strong> specifieke gek<strong>en</strong>de eig<strong>en</strong>schapp<strong>en</strong><br />

van de te sorter<strong>en</strong> gegev<strong>en</strong>s (zoals hun bitvoorstelling of hun verdeling). De theoretische<br />

ondergr<strong>en</strong>s voor de (sequ<strong>en</strong>tiële) complexiteit is hier Ω(n). Voorbeeld<strong>en</strong> zijn countingsort,<br />

bucketsort <strong>en</strong> radixsort.<br />

In dit hoofdstuk besprek<strong>en</strong> we parallelle variant<strong>en</strong> van <strong>en</strong>kele van deze klassieke sorteeralgoritm<strong>en</strong>.<br />

Daarnaast bestuder<strong>en</strong> we ook hoe specifieke circuits voor het sorter<strong>en</strong> van data, de zgn.<br />

sorteernetwerk<strong>en</strong>, kunn<strong>en</strong> geconstrueerd word<strong>en</strong>.<br />

49


50 Hoofdstuk 5. <strong>Parallelle</strong> sorteeralgoritm<strong>en</strong><br />

5.1 Sorteernetwerk<strong>en</strong><br />

x<br />

y<br />

min(x,y)<br />

max(x,y)<br />

Figuur 5.1: E<strong>en</strong> vergelijk<strong>en</strong>de poort<br />

5.1.1 Wat zijn sorteernetwerk<strong>en</strong>?<br />

Sorteernetwerk<strong>en</strong> zijn circuits die opgebouwd zijn uit één <strong>en</strong>kel type poort, nl. de vergelijk<strong>en</strong>de<br />

poort (of comparator gate). Deze poort krijgt als input twee getall<strong>en</strong> <strong>en</strong> ze geeft als output deze<br />

getall<strong>en</strong> in volgorde terug. We tek<strong>en</strong><strong>en</strong> e<strong>en</strong> comparator als e<strong>en</strong> boog tuss<strong>en</strong> de twee lijn<strong>en</strong> die<br />

word<strong>en</strong> vergelek<strong>en</strong> (zie Figuur 5.1).<br />

E<strong>en</strong> sorteernetwerk is e<strong>en</strong> circuit van vergelijk<strong>en</strong>de poort<strong>en</strong> dat zijn input in stijg<strong>en</strong>de volgorde<br />

teruggeeft. We tek<strong>en</strong><strong>en</strong> e<strong>en</strong> sorteernetwerk als e<strong>en</strong> verzameling lijn<strong>en</strong>, één voor elke input, met<br />

de vergelijk<strong>en</strong>de poort<strong>en</strong> toegevoegd tuss<strong>en</strong> de lijn<strong>en</strong>. Vooraleer e<strong>en</strong> poort kan reager<strong>en</strong>, moet ze<br />

wacht<strong>en</strong> tot al haar inputs beschikbaar zijn. Vergelijk<strong>en</strong>de poort<strong>en</strong> waarvan de lijn<strong>en</strong> niet overlapp<strong>en</strong>,<br />

kunn<strong>en</strong> in parallel werk<strong>en</strong>. Wanneer we e<strong>en</strong> sorteernetwerk visualiser<strong>en</strong>, dan groeper<strong>en</strong><br />

we de comparator<strong>en</strong> die in parallel kunn<strong>en</strong> werk<strong>en</strong>. Ze vorm<strong>en</strong> e<strong>en</strong> laag van het netwerk. Elke<br />

laag vereist één tijdse<strong>en</strong>heid om uitgevoerd te word<strong>en</strong>, aangezi<strong>en</strong> alle poort<strong>en</strong> van e<strong>en</strong> laag in<br />

parallel kunn<strong>en</strong> werk<strong>en</strong>. Het aantal poort<strong>en</strong> in de netwerk wordt de grootte van het netwerk<br />

g<strong>en</strong>oemd. De diepte van het netwerk is het aantal stapp<strong>en</strong> dat nodig is opdat elke poort zijn<br />

vergelijking uitgevoerd heeft.<br />

Voorbeeld 5.1.1. Beschouw het netwerk uit Figuur 5.2(a). Dit heeft 5 poort<strong>en</strong> <strong>en</strong> sorteert 4 getall<strong>en</strong><br />

in 3 stapp<strong>en</strong>. Het bestaat uit 3 lag<strong>en</strong>: de eerste <strong>en</strong> de tweede laag bestaan elk uit 2 vergelijk<strong>en</strong>de<br />

poort<strong>en</strong>, terwijl de derde laag uit 1 vergelijk<strong>en</strong>de poort bestaat. Dit sorteernetwerk<br />

heeft dus grootte 5 <strong>en</strong> diepte 3, hetge<strong>en</strong> betek<strong>en</strong>t dat de input na 3 stapp<strong>en</strong> gesorteerd is. In<br />

Figuur 5.2(b) wordt het sorter<strong>en</strong> van de getall<strong>en</strong> 17, 42, 23, 7 getoond.<br />

Hoe kunn<strong>en</strong> we nu het probleem van het sorter<strong>en</strong> van n getall<strong>en</strong> algeme<strong>en</strong> oploss<strong>en</strong>? We bekijk<strong>en</strong><br />

eerst e<strong>en</strong> e<strong>en</strong>voudiger probleem, nl. het bepal<strong>en</strong> van het grootste elem<strong>en</strong>t van de inputs.<br />

Daartoe vergelijk<strong>en</strong> we eerst de eerste twee inputs, daarna het grootste hiervan met de derde<br />

input, <strong>en</strong>zovoort, telk<strong>en</strong>s het vorige resultaat vergelijk<strong>en</strong>d met de volg<strong>en</strong>de input, totdat we de<br />

laatste lijn bereikt hebb<strong>en</strong>. Voor 8 elem<strong>en</strong>t<strong>en</strong> bekom<strong>en</strong> we het netwerk van grootte <strong>en</strong> diepte 7<br />

uit Figuur 5.3.<br />

De 7 comparator<strong>en</strong> op de diagonal<strong>en</strong> garander<strong>en</strong> dat het grootste inputelem<strong>en</strong>t zijn weg vindt<br />

naar de laatste lijn, waar het moet terechtkom<strong>en</strong>. Het idee achter het odd-ev<strong>en</strong>-transposition<br />

netwerk is om vele dergelijke diagonal<strong>en</strong> te gebruik<strong>en</strong>.<br />

Voorbeeld 5.1.2. Figuur 5.4 toont het odd-ev<strong>en</strong>-transposition netwerk voor n = 10. Dit netwerk<br />

heeft diepte 10 <strong>en</strong> grootte 45.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


5.1. Sorteernetwerk<strong>en</strong> 51<br />

(a) E<strong>en</strong> sorteernetwerk (b) Werking op de getall<strong>en</strong> 17, 42, 23, 7<br />

Figuur 5.2: E<strong>en</strong> sorteernetwerk <strong>en</strong> zijn werking<br />

Figuur 5.3: E<strong>en</strong> netwerk voor het bepal<strong>en</strong> van het grootste elem<strong>en</strong>t<br />

Figuur 5.4: Het odd-ev<strong>en</strong>-transposition netwerk voor n = 10 lijn<strong>en</strong>.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be<br />

17<br />

42<br />

23<br />

7<br />

17<br />

42<br />

7<br />

23<br />

23<br />

17<br />

7<br />

17<br />

23<br />

42


52 Hoofdstuk 5. <strong>Parallelle</strong> sorteeralgoritm<strong>en</strong><br />

E<strong>en</strong> odd-ev<strong>en</strong>-transposition netwerk op n lijn<strong>en</strong> is gebouwd uit twee soort<strong>en</strong> koppeling<strong>en</strong> van de<br />

lijn<strong>en</strong>. Wanneer we de lijn<strong>en</strong> nummer<strong>en</strong> van 1 tot n, dan word<strong>en</strong> in de eerste soort koppeling<br />

vergelijking<strong>en</strong> tuss<strong>en</strong> lijn<strong>en</strong> 1 <strong>en</strong> 2, 3 <strong>en</strong> 4, 5 <strong>en</strong> 6, <strong>en</strong>z. aangebracht. In de tweede soort koppeling<br />

word<strong>en</strong> vergelijking<strong>en</strong> tuss<strong>en</strong> lijn<strong>en</strong> 2 <strong>en</strong> 3, 4 <strong>en</strong> 5, <strong>en</strong>z. aangebracht. We alterner<strong>en</strong> deze<br />

koppeling<strong>en</strong> n − 2 keer, hetge<strong>en</strong> e<strong>en</strong> netwerk van diepte n oplevert.<br />

Stelling 5.1.3. Het odd-ev<strong>en</strong>-transposition netwerk sorteert n getall<strong>en</strong> in n stapp<strong>en</strong> met Θ(n 2 )<br />

poort<strong>en</strong>.<br />

(Bewijs als oef<strong>en</strong>ing)<br />

Het odd-ev<strong>en</strong>-transposition netwerk is sneller dan de beste sequ<strong>en</strong>tiële algoritm<strong>en</strong>, maar de versnelling<br />

met factor O(logn) is bekom<strong>en</strong> t<strong>en</strong> koste van Θ(n 2 ) poort<strong>en</strong>. De vraag is of we het<br />

netwerk kunn<strong>en</strong> verbeter<strong>en</strong>, zowel in diepte als in grootte. Dit blijkt e<strong>en</strong> moeilijk probleem te<br />

zijn.<br />

In het PRAM-model bestaat er e<strong>en</strong> gecompliceerde parallelle versie van het mergesort-algoritme<br />

dat sorteert in O(logn) parallelle tijd <strong>en</strong> O(nlogn) werk (e<strong>en</strong> algoritme dat we hier niet besprek<strong>en</strong>).<br />

Voor lange tijd bestond er e<strong>en</strong> conjectuur (o.a. door Knuth) dat deze gr<strong>en</strong>z<strong>en</strong> niet met<br />

e<strong>en</strong> sorteernetwerk kond<strong>en</strong> word<strong>en</strong> bereikt. In 1983 echter construeerd<strong>en</strong> Ajtai, Komlós <strong>en</strong> Szemerédi<br />

e<strong>en</strong> sorteernetwerk van diepte O(logn) <strong>en</strong> grootte O(nlogn). Hun constructie is echter<br />

zeer ingewikkeld <strong>en</strong> van weinig praktisch belang.<br />

Onze bedoeling in dit hoofdstuk is het besprek<strong>en</strong> van e<strong>en</strong> sorteernetwerk, geconstrueerd door<br />

Batcher, dat diepte O(log 2 n) <strong>en</strong> grootte O(nlog 2 n) heeft. Batcher gebruikte e<strong>en</strong> verdeel-<strong>en</strong>heers<br />

strategie voor het sorter<strong>en</strong>: e<strong>en</strong> inputrij wordt in twee helft<strong>en</strong> gesplitst, recursief gesorteerd,<br />

<strong>en</strong> dan word<strong>en</strong> de helft<strong>en</strong> sam<strong>en</strong>gevoegd (gemerged). De taak van het efficiënt merg<strong>en</strong> van twee<br />

gesorteerde rij<strong>en</strong> tot één gesorteerde rij blijkt moeilijker te zijn op sorteernetwerk<strong>en</strong> dan voor<br />

algem<strong>en</strong>e algoritm<strong>en</strong>. Om dit probleem op te loss<strong>en</strong>, bekijk<strong>en</strong> we eerst hoe e<strong>en</strong> sorteernetwerk<br />

voor speciale rij<strong>en</strong>, nl. de bitonische rij<strong>en</strong>, kan word<strong>en</strong> geconstrueerd. Daarna pass<strong>en</strong> we dit<br />

sorteernetwerk toe om twee gesorteerde rij<strong>en</strong> te merg<strong>en</strong> <strong>en</strong> vervolg<strong>en</strong>s gebruik<strong>en</strong> we dat netwerk<br />

om e<strong>en</strong> algeme<strong>en</strong> sorteernetwerk te construer<strong>en</strong>.<br />

5.1.2 Bitonisch sorter<strong>en</strong><br />

We b<strong>en</strong>ader<strong>en</strong> het sorteerprobleem door het eerst op te loss<strong>en</strong> voor e<strong>en</strong>voudige inputrij<strong>en</strong>. De<br />

meest e<strong>en</strong>voudige inputrij is e<strong>en</strong> rij die reeds in stijg<strong>en</strong>de volgorde gesorteerd is, want daar is er<br />

ge<strong>en</strong> werk te do<strong>en</strong>. In e<strong>en</strong> volg<strong>en</strong>de stap beschouw<strong>en</strong> we rij<strong>en</strong> die rotaties van gesorteerde rij<strong>en</strong><br />

zijn. We noem<strong>en</strong> e<strong>en</strong> dergelijke rij (a0,...,an−1) cyclisch stijg<strong>en</strong>d als er e<strong>en</strong> index i bestaat zodanig<br />

dat (ai,...,an−1,a0,...,ai−1) stijg<strong>en</strong>d is. Merk op dat dit voor i = 0 betek<strong>en</strong>t dat de rij zelf<br />

stijg<strong>en</strong>d is. Bijvoorbeeld, de rij<strong>en</strong> (92,78,92) <strong>en</strong> (12,23,31,4,7) zijn cyclisch stijg<strong>en</strong>d, terwijl<br />

de rij<strong>en</strong> (1,3,1,3) <strong>en</strong> (12,3,2) dit niet zijn. E<strong>en</strong> cyclisch stijg<strong>en</strong>de rij kan word<strong>en</strong> gevisualiseerd<br />

door zijn getall<strong>en</strong> op de omtrek van e<strong>en</strong> cirkel te schrijv<strong>en</strong> <strong>en</strong> het eerste elem<strong>en</strong>t in de rij door<br />

e<strong>en</strong> pijl te lat<strong>en</strong> aanwijz<strong>en</strong>.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


5.1. Sorteernetwerk<strong>en</strong> 53<br />

Figuur 5.5: Het netwerk D16.<br />

Voor de e<strong>en</strong>voud van de pres<strong>en</strong>tatie veronderstell<strong>en</strong> we voor de rest van deze paragraaf dat n e<strong>en</strong><br />

macht van 2 is.<br />

We bouw<strong>en</strong> e<strong>en</strong> netwerk Dn dat zijn input beschouwt als bestaande uit twee helft<strong>en</strong> <strong>en</strong> dat elke<br />

elem<strong>en</strong>t van de eerste helft vergelijkt met e<strong>en</strong> elem<strong>en</strong>t uit de tweede helft. Meer precies wordt<br />

elk elem<strong>en</strong>t ai vergelek<strong>en</strong> met a i+n/2, waarbij 0 ≤ i < n/2. Algeme<strong>en</strong> heeft Dn grootte n/2 <strong>en</strong><br />

diepte 1 (aangezi<strong>en</strong> alle vergelijk<strong>en</strong>de poort<strong>en</strong> in parallel kunn<strong>en</strong> werk<strong>en</strong>). Figuur 5.5 toont D16.<br />

Voorbeeld 5.1.4. Wanneer we D8 de inputrij (4,5,6,7,8,9,12,3) gev<strong>en</strong>, dan geeft het als output<br />

(4,5,6,3,8,9,12,7). Voor inputrij (5,6,7,8,9,12,3,4) geeft het (5,6,3,4,9,12,7,8). Voor<br />

(6,7,8,9,12,3,4,5) geeft het (6,3,4,5,12,7,8,9).<br />

Beschouw<strong>en</strong> we de twee helft<strong>en</strong> van de outputrij<strong>en</strong> in bov<strong>en</strong>staande voorbeeld<strong>en</strong>. Merk op dat<br />

D8 e<strong>en</strong> cyclisch stijg<strong>en</strong>de rij opsplitst in twee cyclisch stijg<strong>en</strong>de deelrij<strong>en</strong>, waarbij alle elem<strong>en</strong>t<strong>en</strong><br />

uit de eerste deelrij kleiner zijn dan de elem<strong>en</strong>t<strong>en</strong> in de tweede deelrij.<br />

Lemma 5.1.5. Wanneer de input voor Dn e<strong>en</strong> cyclisch stijg<strong>en</strong>de rij is, dan bestaat de output<br />

(b0,...,bn−1) uit twee cyclisch stijg<strong>en</strong>de rij<strong>en</strong> (b0,...,b n/2−1) <strong>en</strong> (b n/2,...,bn−1), zodanig dat<br />

bi ≤ b j voor 0 ≤ i < n/2 ≤ j < n, m.a.w. elk elem<strong>en</strong>t van (b0,...,b n/2−1) is kleiner dan (of gelijk<br />

aan) elk elem<strong>en</strong>t van (b n/2,...,bn−1).<br />

Bewijs. Aangezi<strong>en</strong> a cyclisch stijg<strong>en</strong>d is, wet<strong>en</strong> we dat er e<strong>en</strong> index m bestaat, zodanig dat<br />

am,...,an−1,a0,...,am−1 stijg<strong>en</strong>d is; mogelijks is m = 0. Beschouw de rij voorgesteld op e<strong>en</strong><br />

cirkel, met e<strong>en</strong> lijn door het c<strong>en</strong>trum die het grootste <strong>en</strong> het kleinste elem<strong>en</strong>t scheidt. Deze lijn<br />

splitst de cirkel in twee helft<strong>en</strong> <strong>en</strong> we merk<strong>en</strong> op dat elk elem<strong>en</strong>t in de helft die het kleinste<br />

elem<strong>en</strong>t bevat hoogst<strong>en</strong>s zo groot is als elk elem<strong>en</strong>t in de helft die het grootste elem<strong>en</strong>t bevat,<br />

aangezi<strong>en</strong> de elem<strong>en</strong>t<strong>en</strong> groter word<strong>en</strong> wanneer we in wijzerzin van het kleinste naar het grootste<br />

elem<strong>en</strong>t beweg<strong>en</strong>.<br />

Het netwerk Dn berek<strong>en</strong>t<br />

bi = min(ai,a i+n/2) <strong>en</strong> b i+n/2 = max(ai,a i+n/2).<br />

Gevisualiseerd op e<strong>en</strong> cirkel betek<strong>en</strong>t dit bijvoorbeeld dat b0 de kleinste <strong>en</strong> b n/2 de grootste is van<br />

de twee elem<strong>en</strong>t<strong>en</strong> aan beide uiteind<strong>en</strong> van de pijl. Hetzelfde geldt voor bi <strong>en</strong> b i+n/2, wanneer we<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


54 Hoofdstuk 5. <strong>Parallelle</strong> sorteeralgoritm<strong>en</strong><br />

Figuur 5.6: Het netwerk B16<br />

de pijl in wijzerzin roter<strong>en</strong> over i posities. We kunn<strong>en</strong> de berek<strong>en</strong>ing van de output dus bekijk<strong>en</strong><br />

als het roter<strong>en</strong> van de pijl, stap voor stap voor n/2 − 1 keer, vanaf zijn beginpositie.<br />

Merk op dat de uiteind<strong>en</strong> van de pijl steeds in teg<strong>en</strong>overgestelde helft<strong>en</strong> van de cirkel ligg<strong>en</strong>.<br />

Aangezi<strong>en</strong> alle elem<strong>en</strong>t<strong>en</strong> in de <strong>en</strong>e helft hoogst<strong>en</strong>s zo groot zijn als alle elem<strong>en</strong>t<strong>en</strong> in de andere<br />

helft, betek<strong>en</strong>t dit dat bi = min(ai,a i+n/2) steeds g<strong>en</strong>om<strong>en</strong> wordt uit de helft met het minimum,<br />

terwijl b i+n/2 = max(ai,a i+n/2) steeds g<strong>en</strong>om<strong>en</strong> wordt uit de helft met het maximum. Dit impliceert<br />

dat alle elem<strong>en</strong>t<strong>en</strong> van (b0,...,b n/2−1) kleiner (of gelijk) zijn dan alle elem<strong>en</strong>t<strong>en</strong> van<br />

(b n/2,...,bn−1). Bov<strong>en</strong>di<strong>en</strong> zijn beide deelrij<strong>en</strong> cyclisch stijg<strong>en</strong>d, omdat ze elk e<strong>en</strong> rotatie van<br />

e<strong>en</strong> deelrij van de oorspronkelijke rij zijn.<br />

Sam<strong>en</strong>vatt<strong>en</strong>d, het netwerk Dn verdeelt e<strong>en</strong> cyclisch stijg<strong>en</strong>de rij van l<strong>en</strong>gte n in twee cyclisch<br />

stijg<strong>en</strong>de deelrij<strong>en</strong> van l<strong>en</strong>gte n/2, zodanig dat elk elem<strong>en</strong>t in de eerste deelrij kleiner is dan<br />

elk elem<strong>en</strong>t in de tweede deelrij. We kunn<strong>en</strong> nu D n/2 op elke deelrij gebruik<strong>en</strong> om de deelrij<strong>en</strong><br />

verder te verwerk<strong>en</strong>. Wanneer we dit proces recursief verderzett<strong>en</strong>, bekom<strong>en</strong> we e<strong>en</strong> netwerk Bn<br />

dat cyclisch stijg<strong>en</strong>de rij<strong>en</strong> sorteert. Figuur 5.6 geeft B16.<br />

Lemma 5.1.6. Het netwerk Bn is e<strong>en</strong> sorteernetwerk voor cyclisch stijg<strong>en</strong>de rij<strong>en</strong>. Het heeft<br />

diepte log 2 n <strong>en</strong> grootte nlog 2 n.<br />

Bewijs. We bewijz<strong>en</strong> de correctheid door inductie op n. Het gestelde geldt voor n = 1, want B1<br />

is e<strong>en</strong> lijn zonder comparator<strong>en</strong>. Zij nu n e<strong>en</strong> eig<strong>en</strong>lijke macht van 2. Door de inductiehypothese<br />

kunn<strong>en</strong> we veronderstell<strong>en</strong> dat B n/2 cyclisch stijg<strong>en</strong>de rij<strong>en</strong> van l<strong>en</strong>gte n/2 correct sorteert. Beschouw<br />

e<strong>en</strong> cyclisch stijg<strong>en</strong>de rij als input voor Bn. Weg<strong>en</strong>s Lemma 5.1.5 verdeelt Dn deze rij in<br />

twee cyclisch stijg<strong>en</strong>de rij<strong>en</strong>, waarbij elk elem<strong>en</strong>t van de eerste deelrij kleiner is dan elk elem<strong>en</strong>t<br />

van de tweede rij. Dus, aangezi<strong>en</strong> beide deelrij<strong>en</strong> correct word<strong>en</strong> gesorteerd door B n/2, wordt de<br />

ganse rij correct gesorteerd.<br />

Merk op dat Bn meer doet dan <strong>en</strong>kel cyclisch stijg<strong>en</strong>de rij<strong>en</strong> sorter<strong>en</strong>; het sorteert ook zgn.<br />

bitonische rij<strong>en</strong> correct. E<strong>en</strong> bitonische rij is e<strong>en</strong> rij die e<strong>en</strong> rotatie is van e<strong>en</strong> rij die eerst<br />

stijg<strong>en</strong>d is <strong>en</strong> dan dal<strong>en</strong>d. Meer formeel: (a0,...,an−1) is bitonisch wanneer er e<strong>en</strong> m <strong>en</strong> e<strong>en</strong> c<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


5.1. Sorteernetwerk<strong>en</strong> 55<br />

bestaan zodanig dat<br />

am ≤ ... ≤ a (m+c)modn <strong>en</strong> a (m+c)modn ≥ a (m+c+1)mod n ≥ ... ≥ am−1.<br />

Voorbeeld 5.1.7. De rij (1,2,3,2,1) is bitonisch met m = 0 <strong>en</strong> c = 2; (5,12,34,56,49,8,6,3,4)<br />

is bitonisch met m = 7 <strong>en</strong> c = 5, want 3 ≤ 4 ≤ 5 ≤ 12 ≤ 34 ≤ 56 <strong>en</strong> 56 ≥ 49 ≥ 8 ≥ 6. Daar<strong>en</strong>teg<strong>en</strong><br />

is de rij (12,6,8,4) niet bitonisch.<br />

We kunn<strong>en</strong> Lemma 5.1.6 herformuler<strong>en</strong> voor bitonische rij<strong>en</strong>.<br />

Lemma 5.1.8. Wanneer de input voor Dn e<strong>en</strong> bitonische rij is, dan bestaat de output (b0,...,bn−1)<br />

uit twee bitonische rij<strong>en</strong> (b0,...,b n/2−1) <strong>en</strong> (b n/2,...,bn), zodanig dat bi ≤ b j voor 0 ≤ i < n/2 ≤<br />

j < n. M.a.w. alle elem<strong>en</strong>t<strong>en</strong> van (b0,...,b n/2−1) zijn kleiner dan of gelijk aan alle elem<strong>en</strong>t<strong>en</strong><br />

van (b n/2,...,bn).<br />

(Bewijs als oef<strong>en</strong>ing)<br />

Steun<strong>en</strong>d op dit lemma kunn<strong>en</strong> we nu aanton<strong>en</strong> dat Bn bitonische rij<strong>en</strong> correct sorteert. Het<br />

bewijs hiervan is analoog aan het bewijs van Lemma 5.1.6.<br />

Stelling 5.1.9. Bn is e<strong>en</strong> sorteernetwerk voor bitonische rij<strong>en</strong> met diepte log 2 n <strong>en</strong> grootte O(nlogn).<br />

5.1.3 Merg<strong>en</strong> <strong>en</strong> sorter<strong>en</strong><br />

Hoe kan het sorter<strong>en</strong> van bitonische rij<strong>en</strong> ons nu dichter br<strong>en</strong>g<strong>en</strong> bij het construer<strong>en</strong> van e<strong>en</strong><br />

algeme<strong>en</strong> sorteernetwerk? Het antwoord, op het eerste zicht verrass<strong>en</strong>d, is dat het ons helpt<br />

om twee gesorteerde rij<strong>en</strong> te merg<strong>en</strong>. We herinner<strong>en</strong> er aan dat mergesort werkt door de rij in<br />

twee helft<strong>en</strong> te splits<strong>en</strong>, vervolg<strong>en</strong>s elke deelrij recursief te sorter<strong>en</strong> <strong>en</strong> t<strong>en</strong>slotte de gesorteerde<br />

deelrij<strong>en</strong> te merg<strong>en</strong>.<br />

Het nut van het bitonische sorteernetwerk Bn wordt duidelijk wanneer we opmerk<strong>en</strong> dat twee gesorteerde<br />

rij<strong>en</strong> die ruggelings aan elkaar word<strong>en</strong> geschakeld, e<strong>en</strong> bitonische rij vorm<strong>en</strong>. M.a.w.<br />

zijn (a0,...,a n/2−1) <strong>en</strong> (b0,...,b n/2−1) twee stijg<strong>en</strong>de rij<strong>en</strong>, dan is (a0,...,a n/2−1,b n/2−1,...,b0)<br />

e<strong>en</strong> bitonische rij van l<strong>en</strong>gte n. Dus wanneer Bn deze rij als input krijgt, dan is het resultaat e<strong>en</strong><br />

gesorteerde rij.<br />

Op deze manier kunn<strong>en</strong> we Bn gebruik<strong>en</strong> om e<strong>en</strong> merging netwerk Mn te bouw<strong>en</strong> dat e<strong>en</strong> merge<br />

van twee stijg<strong>en</strong>de rij<strong>en</strong> uitvoert. Het <strong>en</strong>ige wat we moet<strong>en</strong> do<strong>en</strong>, is de volgorde in de tweede<br />

deelrij omker<strong>en</strong>. Figuur 5.7 toont de structuur van M8 <strong>en</strong> Figuur 5.8 toont nog meer expliciet hoe<br />

M4 eruitziet.<br />

Voorbeeld 5.1.10. We beschouw<strong>en</strong> het merg<strong>en</strong> door M8 van de rij<strong>en</strong> (12,18,23,34) <strong>en</strong> (7,14,29,81).<br />

Door het omker<strong>en</strong> van de tweede rij wordt de bitonische rij (12,18,23,34,81,29,14,7) bekom<strong>en</strong>.<br />

Deze rij wordt als input aan B8 gegev<strong>en</strong>. Deze voert D8 uit, hetge<strong>en</strong> de rij (12,18,14,7,81,29,23,34)<br />

oplevert. Vervolg<strong>en</strong>s word<strong>en</strong> twee D4 uitgevoerd, om (12,7,14,18) <strong>en</strong> (23,29,81,34) te bekom<strong>en</strong>.<br />

T<strong>en</strong>slotte word<strong>en</strong> vier D2 uitgevoerd, hetge<strong>en</strong> uiteindelijk de rij (7,12,14,18,23,29,34,81)<br />

oplevert.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


56 Hoofdstuk 5. <strong>Parallelle</strong> sorteeralgoritm<strong>en</strong><br />

Figuur 5.7: De structuur van het merging netwerk M8<br />

Figuur 5.8: Het netwerk M4, links met <strong>en</strong> rechts zonder snijd<strong>en</strong>de lijn<strong>en</strong><br />

Stelling 5.1.11. We kunn<strong>en</strong> e<strong>en</strong> netwerk van diepte log 2 n <strong>en</strong> grootte nlog 2 n/2 construer<strong>en</strong> voor<br />

het merg<strong>en</strong> van twee gesorteerde rij<strong>en</strong>.<br />

Gebruik mak<strong>en</strong>de van de merging netwerk<strong>en</strong> kunn<strong>en</strong> we nu e<strong>en</strong> sorteernetwerk Sn bouw<strong>en</strong> dat<br />

voor algem<strong>en</strong>e rij<strong>en</strong> werkt. Hiertoe gebruik<strong>en</strong> we het idee van mergesort. Zij S1 e<strong>en</strong> <strong>en</strong>kele lijn.<br />

Uit S1 bouw<strong>en</strong> we S2 door M2 op de twee lijn<strong>en</strong> toe te pass<strong>en</strong>. Aangezi<strong>en</strong> e<strong>en</strong> <strong>en</strong>kele input e<strong>en</strong><br />

gesorteerde rij is, sorteert S2 rij<strong>en</strong> van l<strong>en</strong>gte 2 correct. Analoog bouw<strong>en</strong> we S4 door twee kopies<br />

van S2 te nem<strong>en</strong> om de twee helft<strong>en</strong> van de input te sorter<strong>en</strong>, <strong>en</strong> vervolg<strong>en</strong>s de gesorteerde helft<strong>en</strong><br />

te merg<strong>en</strong> met M4 (zie Figuur 5.9). Figuur 5.10 illustreert de werking van S4 op de voorbeeldrij<br />

(4,1,3,2).<br />

Algeme<strong>en</strong> bouw<strong>en</strong> we op dezelfde manier uit twee S n/2 <strong>en</strong> één Mn e<strong>en</strong> sorteernetwerk Sn. Figuur<br />

5.11 toont het sorteernetwerk S8.<br />

Stelling 5.1.12. Het netwerk Sn is e<strong>en</strong> sorteernetwerk van diepte Θ(log 2 n) <strong>en</strong> grootte Θ(nlog 2 n)<br />

dat e<strong>en</strong> gegev<strong>en</strong> rij van l<strong>en</strong>gte n correct sorteert.<br />

Bewijs. We bewijz<strong>en</strong> de stelling door inductie op n. S1 is correct, aangezi<strong>en</strong> het maar 1 input<br />

heeft. Zij n e<strong>en</strong> eig<strong>en</strong>lijke macht van 2. Als inductiehypothese veronderstell<strong>en</strong> we dat S n/2 e<strong>en</strong><br />

inputrij van l<strong>en</strong>gte n/2 correct sorteert. Dan sorteert Sn eerst elke helft van zijn inputrij met<br />

behulp van S n/2, hetge<strong>en</strong> weg<strong>en</strong>s de inductiehypothese correct gebeurt. Vervolg<strong>en</strong>s voegt Sn de<br />

twee gesorteerde deelrij<strong>en</strong> sam<strong>en</strong> tot e<strong>en</strong> gesorteerde rij met behulp van e<strong>en</strong> (correct werk<strong>en</strong>d)<br />

merging netwerk Mn. Dit levert e<strong>en</strong> gesorteerde rij van l<strong>en</strong>gte n.<br />

De diepte van Sn is de som van de dieptes van Mn,M n/2,M n/4,...,M1, d.i. log 2 n+log 2 (n/2)+<br />

log 2 (n/4)+··· = Θ(log 2 n). Zij sn de grootte van Sn, dan is sn gegev<strong>en</strong> door de grootte van Mn<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be<br />

B8


5.1. Sorteernetwerk<strong>en</strong> 57<br />

S2<br />

S2<br />

Figuur 5.9: De structuur van het sorteernetwerk S4<br />

M4<br />

4 1 1<br />

1<br />

3<br />

2<br />

4<br />

2<br />

3<br />

Figuur 5.10: Werking van S4 bij het sorter<strong>en</strong> van (4,1,3,2)<br />

plus 2s n/2. Aangezi<strong>en</strong> Mn grootte nlog 2 n/2 heeft, krijg<strong>en</strong> we de volg<strong>en</strong>de recurr<strong>en</strong>te betrekking<br />

voor sn:<br />

sn = nlog 2 n/2+2s n/2.<br />

Daaruit kunn<strong>en</strong> we gemakkelijk afleid<strong>en</strong> dat sn = Θ(nlog 2 n).<br />

5.1.4 Het nul-e<strong>en</strong>-principe voor sorteernetwerk<strong>en</strong><br />

Om het achterligg<strong>en</strong>de idee achter de constructie van sorteernetwerk<strong>en</strong> te b<strong>en</strong>adrukk<strong>en</strong>, hebb<strong>en</strong><br />

we de correctheid van de gezi<strong>en</strong>e sorteernetwerk<strong>en</strong> tot nu toe rechtstreeks bewez<strong>en</strong>. In deze paragraaf<br />

besprek<strong>en</strong> we e<strong>en</strong> e<strong>en</strong> tool die dergelijke bewijz<strong>en</strong> dikwijls vere<strong>en</strong>voudigt, het zog<strong>en</strong>aamde<br />

nul-e<strong>en</strong>-principe.<br />

Stelling 5.1.13. Als e<strong>en</strong> sorteernetwerk correct werkt op alle mogelijke inputs bestaande uit<br />

<strong>en</strong>kel null<strong>en</strong> <strong>en</strong> <strong>en</strong><strong>en</strong>, dan werkt het ook correct voor willekeurige inputs.<br />

Deze stelling laat ons toe om sorteernetwerk<strong>en</strong> te verifiër<strong>en</strong> door ze <strong>en</strong>kel op rij<strong>en</strong> van null<strong>en</strong> <strong>en</strong><br />

<strong>en</strong><strong>en</strong> te test<strong>en</strong>. Voor e<strong>en</strong> netwerk met n inputs, betek<strong>en</strong>t dit dat we hoogst<strong>en</strong>s 2 n inputs moet<strong>en</strong><br />

test<strong>en</strong>, in teg<strong>en</strong>stelling tot oneindig veel.<br />

Bewijs. Veronderstel dat er e<strong>en</strong> sorteernetwerk is dat alle rij<strong>en</strong> van null<strong>en</strong> <strong>en</strong> <strong>en</strong><strong>en</strong> correct sorteert,<br />

maar dat e<strong>en</strong> zekere rij van getall<strong>en</strong> (a0,...,an−1) niet correct sorteert.<br />

Zij (b0,...,bn−1) de output die het sorteernetwerk geeft wanneer het de rij (a0,...,an−1) als<br />

input krijgt. Aangezi<strong>en</strong> de output niet correct gesorteerd is, moet er e<strong>en</strong> s < t bestaan waarvoor<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be<br />

2<br />

4<br />

3<br />

1<br />

2<br />

3<br />

4


58 Hoofdstuk 5. <strong>Parallelle</strong> sorteeralgoritm<strong>en</strong><br />

Figuur 5.11: Het sorteernetwerk S8<br />

bs > bt. We associër<strong>en</strong> e<strong>en</strong> rij van null<strong>en</strong> <strong>en</strong> <strong>en</strong><strong>en</strong> met (a0,...,an−1), als volgt. Label elke ai die<br />

kleiner is dan bs met e<strong>en</strong> nul, <strong>en</strong> alle andere ai met e<strong>en</strong> één.<br />

We bewijz<strong>en</strong> zo mete<strong>en</strong> dat, wanneer we de rij (a0,...,an−1) <strong>en</strong> de rij van zijn labels gelijktijdig<br />

door het sorteernetwerk lat<strong>en</strong> verwerk<strong>en</strong>, elke ai zijn label behoudt. Dit impliceert dat bs met<br />

e<strong>en</strong> 1 gelabeld is, <strong>en</strong> bt met e<strong>en</strong> 0. Aangezi<strong>en</strong> s < t, sorteert het netwerk dus de rij van labels niet<br />

correct, hetge<strong>en</strong> e<strong>en</strong> strijdigheid oplevert, aangezi<strong>en</strong> de labels null<strong>en</strong> <strong>en</strong> <strong>en</strong><strong>en</strong> zijn.<br />

Blijft nog te bewijz<strong>en</strong> dat de labels van de inputelem<strong>en</strong>t<strong>en</strong> dezelfde blijv<strong>en</strong>. Beschouw e<strong>en</strong><br />

vergelijk<strong>en</strong>de poort. Als zijn inputs allebei nul of allebei één zijn, dan geldt dit ook voor de<br />

output. In het geval waarbij de inputs a < a ′ hebb<strong>en</strong>, <strong>en</strong> a met 0 <strong>en</strong> a ′ met 1 gelabeld zijn,<br />

verandert de vergelijk<strong>en</strong>de poort niets aan a <strong>en</strong> a ′ , noch aan de labels. De andere mogelijkheid<br />

is dat we inputs a > a ′ hebb<strong>en</strong>, <strong>en</strong> dat a met e<strong>en</strong> 1 <strong>en</strong> a ′ met e<strong>en</strong> 1 gelabeld is – in dit geval<br />

verwisselt de vergelijk<strong>en</strong>de poort zowel de inputs a <strong>en</strong> a ′ als de labels, <strong>en</strong> ook hier blijv<strong>en</strong> de<br />

labels bij de oorspronkelijke elem<strong>en</strong>t<strong>en</strong>.<br />

We kunn<strong>en</strong> nu het nul-e<strong>en</strong>-principe gebruik<strong>en</strong> om aan te ton<strong>en</strong> dat het odd-ev<strong>en</strong>-transposition<br />

netwerk dat we eerder introduceerd<strong>en</strong>, correct werkt.<br />

Stelling 5.1.14. Het odd-ev<strong>en</strong>-transposition netwerk sorteert rij<strong>en</strong> van l<strong>en</strong>gte n in diepte n <strong>en</strong><br />

grootte Θ(n 2 ).<br />

Bewijs. Neem n vast <strong>en</strong> beschouw het odd-ev<strong>en</strong>-transposition netwerk voor rij<strong>en</strong> van l<strong>en</strong>gte n.<br />

Weg<strong>en</strong>s stelling 5.1.13 moet<strong>en</strong> we <strong>en</strong>kel aanton<strong>en</strong> dat het netwerk alle binaire inputrij<strong>en</strong> correct<br />

sorteert.<br />

We beschouw<strong>en</strong> e<strong>en</strong> zekere willekeurige inputrij (a0,...,an−1) van l<strong>en</strong>gte n. Zij ai de eerste nul<br />

in deze rij, m.a.w. ai = 0 <strong>en</strong> ak = 1 voor alle k < i.<br />

Als i ev<strong>en</strong> is, dan wordt ai vergelek<strong>en</strong> met ai+1 in de eerste laag van het netwerk, <strong>en</strong> er gebeurt<br />

niets. Echter, in de tweede laag wordt ai vergelek<strong>en</strong> met ai−1 = 1, <strong>en</strong> de twee elem<strong>en</strong>t<strong>en</strong> word<strong>en</strong><br />

verwisseld. Aangezi<strong>en</strong> alle elem<strong>en</strong>t<strong>en</strong> voor ai één zijn, zal ai vanaf dat punt naar vor<strong>en</strong> beweg<strong>en</strong><br />

tot het de eerste lijn bereikt heeft. Als i onev<strong>en</strong> is, zal ai onmiddellijk beginn<strong>en</strong> aan zijn beweging<br />

naar de eerste lijn, tot het die bereikt. Beide situaties word<strong>en</strong> geïllustreerd in Figuur 5.12.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


5.1. Sorteernetwerk<strong>en</strong> 59<br />

1 1<br />

1<br />

1<br />

0<br />

1<br />

0<br />

1<br />

0<br />

1<br />

0 0<br />

1<br />

1 1<br />

(a) Eerste 0 beweegt naar lijn 1 (b) Vertraging van 1 stap<br />

Figuur 5.12: Het nul-e<strong>en</strong>-principe voor het odd-ev<strong>en</strong>-transposition netwerk<br />

1 1<br />

1<br />

0<br />

1<br />

0<br />

0<br />

1<br />

0<br />

1<br />

0<br />

0<br />

1<br />

0<br />

1<br />

0<br />

1<br />

0<br />

1<br />

0<br />

1<br />

1<br />

1<br />

0<br />

0 1 1 1<br />

Figuur 5.13: Sorter<strong>en</strong> van (1,1,0,1,0,0) met het odd-ev<strong>en</strong>-tranposition netwerk<br />

Algeme<strong>en</strong> kunn<strong>en</strong> we drie toestand<strong>en</strong> voor elke 0 in de rij onderscheid<strong>en</strong>: “geblokkeerd”, “in<br />

beweging” <strong>en</strong> “aangekom<strong>en</strong>”. Er zijn twee gevall<strong>en</strong> van blokkering<strong>en</strong> die e<strong>en</strong> 0 belett<strong>en</strong> om naar<br />

zijn plaats te beweg<strong>en</strong>: ofwel in verkeerde fase zitt<strong>en</strong> (zoals de eerste nul op e<strong>en</strong> ev<strong>en</strong> lijn in<br />

Figuur 5.12), ofwel word<strong>en</strong> opgehoud<strong>en</strong> door e<strong>en</strong> voorafgaande 0 die nog niet beweegt.<br />

Door inductie kunn<strong>en</strong> we aanton<strong>en</strong> dat de k-de nul in de rij t<strong>en</strong> laatste in de (k+1)-de laag begint<br />

te beweg<strong>en</strong>, totdat ze haar positie bereikt heeft. Immers, zoals reeds eerder uitgelegd, begint de<br />

eerste 0 te beweg<strong>en</strong> in de eerste of tweede laag, <strong>en</strong> dan beweegt ze onmiddellijk verder naar haar<br />

uiteindelijke positie (aangezi<strong>en</strong> er ge<strong>en</strong> blokker<strong>en</strong>de null<strong>en</strong> vooraf kunn<strong>en</strong> gaan). De tweede<br />

nul kan <strong>en</strong>kel door de eerste nul word<strong>en</strong> geblokkeerd, wanneer de eerste nul nog niet aan het<br />

beweg<strong>en</strong> is. Dus begint de tweede nul ofwel in de tweede ofwel in de derde laag te beweg<strong>en</strong>,<br />

m.a.w. t<strong>en</strong> laatste in de derde laag. Algeme<strong>en</strong> kan de k-de nul <strong>en</strong>kel word<strong>en</strong> geblokkeerd door<br />

de voorafgaande null<strong>en</strong>, die allemaal t<strong>en</strong> laatste in de k-de laag beginn<strong>en</strong> te beweg<strong>en</strong>. Dus,<br />

afhankelijk van de fase, zal de k-de nul beginn<strong>en</strong> beweg<strong>en</strong> in de k-de of in de (k+ 1)-de laag.<br />

De k-de nul kan hoogst<strong>en</strong>s n − k posities van zijn uiteindelijk positie verwijderd zijn. Aangezi<strong>en</strong><br />

ze t<strong>en</strong> laatste in de (k+ 1)-de laag begint te beweg<strong>en</strong>, zijn er dan nog n − k lag<strong>en</strong> over waarin ze<br />

naar haar uiteindelijke positie kan beweg<strong>en</strong>.<br />

Voorbeeld 5.1.15. We bekijk<strong>en</strong> het sorter<strong>en</strong> van de rij (1,1,0,1,0,0) op het odd-ev<strong>en</strong>-transposition<br />

netwerk. Figuur 5.13 toont de werking van het netwerk.<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be<br />

0<br />

1<br />

0<br />

1<br />

0<br />

0<br />

0<br />

1<br />

1<br />

0<br />

0<br />

0<br />

1<br />

1<br />

1<br />

1<br />

1<br />

1<br />

1<br />

0<br />

1<br />

1<br />

1<br />

0<br />

1<br />

0<br />

0<br />

1


60 Hoofdstuk 5. <strong>Parallelle</strong> sorteeralgoritm<strong>en</strong><br />

5.2 Sorter<strong>en</strong> op interconnecti<strong>en</strong>etwerk<strong>en</strong><br />

In deze paragraaf besprek<strong>en</strong> we mogelijke sorteeralgoritm<strong>en</strong> op netwerktopologieën, zoals de rij,<br />

het rooster <strong>en</strong> de hyperkubus.<br />

5.2.1 Odd-ev<strong>en</strong>-transpositionsorter<strong>en</strong> op e<strong>en</strong> rij van processor<strong>en</strong><br />

Op e<strong>en</strong> rij processor<strong>en</strong> kunn<strong>en</strong> we het odd-ev<strong>en</strong>-transposition sorteeralgoritme dat we eerder<br />

zag<strong>en</strong>, implem<strong>en</strong>ter<strong>en</strong>. Elke processor houdt e<strong>en</strong> teller bij om te wet<strong>en</strong> of het system zich<br />

mom<strong>en</strong>teel in e<strong>en</strong> ev<strong>en</strong> of onev<strong>en</strong> fase bevindt. Om e<strong>en</strong> vergelijk<strong>en</strong>de poort te implem<strong>en</strong>ter<strong>en</strong><br />

moet<strong>en</strong> twee processor<strong>en</strong> sam<strong>en</strong>werk<strong>en</strong> <strong>en</strong> mogelijks hun elem<strong>en</strong>t<strong>en</strong> uitwissel<strong>en</strong>. In e<strong>en</strong> ev<strong>en</strong><br />

fase werk<strong>en</strong> de ev<strong>en</strong> processor<strong>en</strong> sam<strong>en</strong> met hun rechterbur<strong>en</strong>, m.a.w. de par<strong>en</strong> (0,1), (2,3), (4,5)<br />

<strong>en</strong>zovoort, <strong>en</strong> de ev<strong>en</strong> processor<strong>en</strong> ontvang<strong>en</strong> het kleinste elem<strong>en</strong>t. In e<strong>en</strong> onev<strong>en</strong> fase werk<strong>en</strong><br />

de ev<strong>en</strong> processor<strong>en</strong> sam<strong>en</strong> met hun linkerbur<strong>en</strong>, m.a.w. de par<strong>en</strong> (1,2), (3,4), (5,6), <strong>en</strong>zovoort.<br />

Na n stapp<strong>en</strong> stopp<strong>en</strong> alle processor<strong>en</strong>. Op dat mom<strong>en</strong>t hebb<strong>en</strong> ze de n fas<strong>en</strong> van het odd-ev<strong>en</strong>transposition<br />

netwerk gesimuleerd.<br />

De correctheid van dit algoritme volgt onmiddellijk uit de correctheid van het odd-ev<strong>en</strong>-transposition<br />

netwerk, bewez<strong>en</strong> in Stelling 5.1.3.<br />

Stelling 5.2.1. We kunn<strong>en</strong> n getall<strong>en</strong> op e<strong>en</strong> rij van n processor<strong>en</strong> sorter<strong>en</strong> in lineaire tijd m.b.v.<br />

het odd-ev<strong>en</strong>-transposition sorteeralgoritme.<br />

5.2.2 Bitonisch sorter<strong>en</strong> op de hyperkubus<br />

Wanneer we de inputlijn<strong>en</strong> van e<strong>en</strong> bitonisch sorteernetwerk met n = 2 d inputlijn<strong>en</strong> label<strong>en</strong> met<br />

de d-bitstrings 0...0 t.e.m. 1...1, dan bekom<strong>en</strong> we e<strong>en</strong> rechtstreekse mapping tuss<strong>en</strong> de inputlijn<strong>en</strong><br />

van het sorteernetwerk <strong>en</strong> de processor<strong>en</strong> in e<strong>en</strong> hyperkubus van dim<strong>en</strong>sie d. Merk op dat<br />

de vergelijking<strong>en</strong> tuss<strong>en</strong> elem<strong>en</strong>t<strong>en</strong> die het bitonisch sorteernetwerk uitvoert, telk<strong>en</strong>s gebeur<strong>en</strong><br />

tuss<strong>en</strong> inputlijn<strong>en</strong> waarvan het label in slechts één bitpositie verschilt. M.a.w. deze vergelijking<strong>en</strong><br />

gebeur<strong>en</strong> tuss<strong>en</strong> processor<strong>en</strong> die in de hyperkubus rechtstreeks verbond<strong>en</strong> zijn, <strong>en</strong> er is ge<strong>en</strong><br />

extra communicatie-overhead voor routing nodig.<br />

5.2.3 Shearsort op e<strong>en</strong> rooster van processor<strong>en</strong><br />

Vervolg<strong>en</strong>s bekijk<strong>en</strong> we e<strong>en</strong> sorteeralgoritme op het rooster. Het algoritme wordt shearsort g<strong>en</strong>oemd<br />

<strong>en</strong> het sorteert in twee fas<strong>en</strong> die ⌈log 2 n⌉+1 keer herhaald word<strong>en</strong>. In de rijsorteerfase<br />

word<strong>en</strong> alle rij<strong>en</strong> van het rooster gesorteerd met behulp van het odd-ev<strong>en</strong>-transposition sorteeralgoritme<br />

voor rij<strong>en</strong> van processor<strong>en</strong>. De rij<strong>en</strong> word<strong>en</strong> afwissel<strong>en</strong>d in stijg<strong>en</strong>de <strong>en</strong> dal<strong>en</strong>de volgorde<br />

gesorteerd. In de kolomsorteerfase sorter<strong>en</strong> we alle kolomm<strong>en</strong> in stijg<strong>en</strong>de volgorde. Na<br />

hoogst<strong>en</strong>s ⌈log 2 n⌉+1 herhaling<strong>en</strong> van deze fas<strong>en</strong> zijn de elem<strong>en</strong>t<strong>en</strong> in het rooster gesorteerd,<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


5.2. Sorter<strong>en</strong> op interconnecti<strong>en</strong>etwerk<strong>en</strong> 61<br />

stap 1<br />

stap 2<br />

stap 3<br />

rij<strong>en</strong> sorter<strong>en</strong> (fase 1) kolomm<strong>en</strong> sorter<strong>en</strong> (fase 2)<br />

15 4 10 6 →<br />

1 5 7 11 ←<br />

12 14 13 8 →<br />

9 16 2 3 ←<br />

4 6 3 1 →<br />

8 7 5 2 ←<br />

11 9 10 14 →<br />

16 12 13 15 ←<br />

1 3 4 2 →<br />

8 7 5 6 ←<br />

9 10 11 12 →<br />

16 15 13 14 ←<br />

4 6 10 15<br />

11 7 5 1<br />

8 12 13 14<br />

16 9 3 2<br />

1 3 4 6<br />

8 7 5 2<br />

9 10 11 14<br />

16 15 13 12<br />

1 2 3 4<br />

8 7 6 5<br />

9 10 11 12<br />

16 15 14 13<br />

Figuur 5.14: De rij (15,4,10,6,1,5,7,11,12,14,13,8,9,16,2,3) sorter<strong>en</strong> op<br />

e<strong>en</strong> rooster van processor<strong>en</strong> met het shearsort algoritme<br />

in e<strong>en</strong> soort ‘ploegvor<strong>en</strong>’-volgorde (m.a.w. afwissel<strong>en</strong>d in stijg<strong>en</strong>de <strong>en</strong> dal<strong>en</strong>de volgorde in de<br />

rij<strong>en</strong>).<br />

Voorbeeld 5.2.2. We gebruik<strong>en</strong> shearsort om de rij (15,4,10,6,1,5,7,11,12,14,13,8,9,16,2,3) te<br />

sorter<strong>en</strong>. We k<strong>en</strong>n<strong>en</strong> de getall<strong>en</strong> rij per rij aan de processor<strong>en</strong> van het rooster toe. Figuur 5.14<br />

illustreert de verschill<strong>en</strong>de stapp<strong>en</strong> in het algoritme.<br />

Om de correctheid van het shearsort algoritme te bewijz<strong>en</strong>, will<strong>en</strong> we het nul-e<strong>en</strong>-principe gebruik<strong>en</strong>,<br />

dat we in Paragraaf 5.1.4 invoerd<strong>en</strong>. Het nul-e<strong>en</strong>-principe werd weliswaar geformuleerd<br />

voor sorteernetwerk<strong>en</strong>, <strong>en</strong> niet voor algem<strong>en</strong>e algoritm<strong>en</strong> (het is ook zo dat het niet werkt voor<br />

algem<strong>en</strong>e algoritm<strong>en</strong>). Maar shearsort is e<strong>en</strong> zeer beperkt soort algoritme. T<strong>en</strong> eerste is het e<strong>en</strong><br />

vergelijk-<strong>en</strong>-verwissel algoritme, dat kan geïmplem<strong>en</strong>teerd word<strong>en</strong> door <strong>en</strong>kel gebruik te mak<strong>en</strong><br />

van vergelijk<strong>en</strong>de poort<strong>en</strong>. T<strong>en</strong> tweede is het ‘vergeetachtig’, in die zin dat het resultaat van<br />

e<strong>en</strong> vergelijking ge<strong>en</strong> invloed heeft op de vergelijking<strong>en</strong> die later gemaakt word<strong>en</strong>. E<strong>en</strong> dergelijk<br />

algoritme kan als e<strong>en</strong> sorteernetwerk geïmplem<strong>en</strong>teerd word<strong>en</strong>, waardoor het nul-e<strong>en</strong>-principe<br />

ervoor geldt.<br />

Stelling 5.2.3. Shearsort sorteert n 2 elem<strong>en</strong>t<strong>en</strong> in 2n(⌈log 2 n⌉+1) stapp<strong>en</strong> op e<strong>en</strong> n × n rooster.<br />

Bewijs. We pass<strong>en</strong> het nul-e<strong>en</strong>-principe toe <strong>en</strong> controler<strong>en</strong> dat het algoritme werkt voor binaire<br />

inputrij<strong>en</strong>.<br />

Beschouw<strong>en</strong> we twee rij<strong>en</strong> 2i <strong>en</strong> 2i+1 na de rijsorteerfase. Aangezi<strong>en</strong> rij 2i in stijg<strong>en</strong>de volgorde<br />

gesorteerd werd, start ze met e<strong>en</strong> blok null<strong>en</strong> <strong>en</strong> eindigt ze met e<strong>en</strong> blok <strong>en</strong><strong>en</strong>. Analoog<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


62 Hoofdstuk 5. <strong>Parallelle</strong> sorteeralgoritm<strong>en</strong><br />

begint rij 2i + 1 met e<strong>en</strong> blok <strong>en</strong><strong>en</strong> <strong>en</strong> eindigt met e<strong>en</strong> blok null<strong>en</strong>. Als het aantal <strong>en</strong><strong>en</strong> in de<br />

twee rij<strong>en</strong> minst<strong>en</strong>s n is, dan zull<strong>en</strong> de twee rij<strong>en</strong> resulter<strong>en</strong> in t<strong>en</strong>minste één rij vol <strong>en</strong><strong>en</strong> na de<br />

kolomsorteerfase. Analoog, als het aantal null<strong>en</strong> in de twee rij<strong>en</strong> t<strong>en</strong>minste n is, dan krijg<strong>en</strong> we<br />

e<strong>en</strong> rij vol null<strong>en</strong> na de kolomsorteerfase.<br />

Aangezi<strong>en</strong> e<strong>en</strong> paar rij<strong>en</strong> ofwel minst<strong>en</strong>s n null<strong>en</strong> ofwel minst<strong>en</strong>s n <strong>en</strong><strong>en</strong> moet bevatt<strong>en</strong>, wet<strong>en</strong><br />

we dat elk paar rij<strong>en</strong> bij de kom<strong>en</strong>de kolomsorteerfase zal aanleiding gev<strong>en</strong> tot t<strong>en</strong> minste één<br />

rij met <strong>en</strong>kel null<strong>en</strong> of <strong>en</strong>kel <strong>en</strong><strong>en</strong>. Deze rij<strong>en</strong> word<strong>en</strong> niet meer beïnvloed door verdere rij- of<br />

kolomsorteerfas<strong>en</strong>; we kunn<strong>en</strong> ze dus verder neger<strong>en</strong>.<br />

Dit betek<strong>en</strong>t dat het uitvoer<strong>en</strong> van e<strong>en</strong> rij- <strong>en</strong> kolomsorteerfase zorgt voor het halver<strong>en</strong> van het<br />

aantal rij<strong>en</strong> met elem<strong>en</strong>t<strong>en</strong> die hun uiteindelijke positie nog niet bereikt hebb<strong>en</strong>. Na ⌈log 2 n⌉+<br />

1 stapp<strong>en</strong> hebb<strong>en</strong> dus alle elem<strong>en</strong>t<strong>en</strong> hun uiteindelijke positie bereikt. Aangezi<strong>en</strong> de rij- <strong>en</strong><br />

kolomsorteerfase elk n stapp<strong>en</strong> nem<strong>en</strong>, is de totale uitvoeringstijd 2n(⌈log 2 n⌉+1).<br />

Voorbeeld 5.2.4. We bekijk<strong>en</strong> wat er gebeurt voor de volg<strong>en</strong>de input:<br />

0 1 0 0 1 0 0 1 →<br />

0 1 1 1 0 1 1 1 ←<br />

0 0 1 0 1 0 0 1 →<br />

1 0 0 1 0 0 1 0 ←<br />

1 1 1 0 1 0 1 0 →<br />

0 0 0 0 1 1 0 1 ←<br />

0 0 1 1 1 1 0 1 →<br />

1 1 0 0 1 1 1 1 ←<br />

Na de rijsorteerfase zi<strong>en</strong> de eerste twee rij<strong>en</strong> er als volgt uit:<br />

0 0 0 0 0 1 1 1 →<br />

1 1 1 1 1 1 0 0 ←<br />

De blokk<strong>en</strong> met <strong>en</strong><strong>en</strong> overlapp<strong>en</strong>, dus na de kom<strong>en</strong>de kolomsorteerfase zull<strong>en</strong> deze twee rij<strong>en</strong><br />

zorg<strong>en</strong> voor e<strong>en</strong> volledige rij <strong>en</strong><strong>en</strong>.<br />

In rij 3 <strong>en</strong> 4 zijn er meer null<strong>en</strong> dan <strong>en</strong><strong>en</strong>, zodat deze zull<strong>en</strong> zorg<strong>en</strong> voor e<strong>en</strong> volledige rij null<strong>en</strong><br />

na de kolomsorteerfase:<br />

0 0 0 0 0 1 1 1 →<br />

1 1 1 0 0 0 0 0 ←<br />

Rij 5 <strong>en</strong> 6 hebb<strong>en</strong> sam<strong>en</strong> precies 8 null<strong>en</strong> <strong>en</strong> 8 <strong>en</strong><strong>en</strong>, zodat ze zull<strong>en</strong> zorg<strong>en</strong> voor e<strong>en</strong> rij met<br />

null<strong>en</strong> <strong>en</strong> e<strong>en</strong> rij met <strong>en</strong><strong>en</strong>, na de kolomsorteerfase:<br />

0 0 0 1 1 1 1 1 →<br />

1 1 1 0 0 0 0 0 ←<br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be


5.3. PRAM-variant<strong>en</strong> van klassieke sorteeralgoritm<strong>en</strong> 63<br />

De laatste twee rij<strong>en</strong> hebb<strong>en</strong> e<strong>en</strong> meerderheid aan <strong>en</strong><strong>en</strong> <strong>en</strong> zull<strong>en</strong> dus resulter<strong>en</strong> in e<strong>en</strong> rij <strong>en</strong><strong>en</strong>.<br />

Sam<strong>en</strong>g<strong>en</strong>om<strong>en</strong> hebb<strong>en</strong> we minst<strong>en</strong>s 4 rij<strong>en</strong> met ofwel alles null<strong>en</strong> ofwel alles <strong>en</strong><strong>en</strong> (in feite<br />

hebb<strong>en</strong> we er hier zelfs 5, door rij 5 <strong>en</strong> 6). Het resultaat van de kolomsorteerfase is:<br />

0 0 0 0 0 0 0 0 →<br />

0 0 0 0 0 0 0 0 ←<br />

0 0 0 0 0 1 0 0 →<br />

0 0 0 0 0 1 0 0 ←<br />

1 1 1 1 1 1 1 1 →<br />

1 1 1 1 1 1 1 1 ←<br />

1 1 1 1 1 1 1 1 →<br />

1 1 1 1 1 1 1 1 ←<br />

Na nog e<strong>en</strong> rij- <strong>en</strong> kolomsorteerfase bekom<strong>en</strong> we:<br />

0 0 0 0 0 0 0 0 →<br />

0 0 0 0 0 0 0 0 ←<br />

0 0 0 0 0 0 0 0 →<br />

1 0 0 0 0 0 0 1 ←<br />

1 1 1 1 1 1 1 1 →<br />

1 1 1 1 1 1 1 1 ←<br />

1 1 1 1 1 1 1 1 →<br />

1 1 1 1 1 1 1 1 ←<br />

Nog e<strong>en</strong> rijsorteerfase levert e<strong>en</strong> gesorteerde rij.<br />

5.3 PRAM-variant<strong>en</strong> van klassieke sorteeralgoritm<strong>en</strong><br />

<strong>Algoritm<strong>en</strong></strong> <strong>en</strong> Datastructur<strong>en</strong> <strong>III</strong> Veerle.Fack@UG<strong>en</strong>t.be

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!