181
KONPUTAGAILU PARALELOAK Abiadura Handiko Konputazioa A. Arruabarrena — J. Muguerza Konputagailuen Arkitektura eta Teknologia saila Informatika Fakultatea — Euskal Herriko Unibertsitatea

KONPUTAGAILU PARALELOAK - sc.ehu.es · Hari independenteak sortzea (switching)..... 308. 8.4.6. Sinkronizazioko eragiketa kopurua txikiagotzea ..... 309. 8.4

  • Upload
    lenhan

  • View
    221

  • Download
    0

Embed Size (px)

Citation preview

KONPUTAGAILU PARALELOAK

Abiadura Handiko Konputazioa

A. Arruabarrena — J. Muguerza

Konputagailuen Arkitektura eta Teknologia saila Informatika Fakultatea — Euskal Herriko Unibertsitatea

KONPUTAGAILU PARALELOAK

Abiadura Handiko Konputazioa

A. Arruabarrena — J. Muguerza

Konputagailuen Arkitektura eta Teknologia saila Informatika Fakultatea — Euskal Herriko Unibertsitatea

2012ko iraila

AURKIBIDEA

Sarrera ................................................................................. 1

1. kapitulua. Bektore Konputagailuak ................................................. 7

1.1. Zer dira bektore-konputagailuak? .................................................................... 7 1.1.1. Zenbait arazo ...................................................................................................... 10

1.1.1.1. Bektore-konputagailu baten memoria ............................................... 10 1.1.1.2. Unitate funtzionalak ............................................................................. 11 1.1.1.3. Bektore-erregistroak .............................................................................. 11 1.1.1.4. Programak ............................................................................................... 12

1.1.2. Arkitektura eta makina-lengoaia ...................................................................... 13

1.2. Datu-dependentziak ......................................................................................... 15 1.2.1. Kateaketa (chaining) ...................................................................................................... 16

1.2.1.1. Kateaketa bi agindurekin ..................................................................... 17

1.2.2. Aginduen exekuzioko taulak ............................................................................ 18

1.3. Egiturazko dependentziak ............................................................................... 19 1.3.1. Memoriako busak (LV/SV unitate funtzionalak) ........................................... 20 1.3.2. Gatazkak memoria-moduluetan ...................................................................... 22

1.3.2.1. Memoria-eragiketa bakarra ................................................................. 22 1.3.2.2. Memoria-eragiketa bat baino gehiago .............................................. 25

1.3.3. Bektore-erregistroen luzera (strip mining) ...................................................... 29

1.4. Bektore-konputagailuen kalkulu-abiadura .................................................... 30 1.4.1. Kalkulu-abiadura bektoreen luzeraren arabera ............................................. 30

1.4.1.1. R∞ eta N1/2 .............................................................................................. 30

1.4.1.2. Azelerazio-faktorea (speed-up) ........................................................... 33 1.4.1.3. Nb ............................................................................................................. 34

1.4.2. Kalkulu eskalarraren eragina: Amdahl-en legea ............................................ 34

1.5. Bektore-kodea sortzeko teknika nagusiak .................................................... 37 1.5.1. Aginduen arteko datu-dependentziak ............................................................ 38 1.5.2. Bektorizazioa ....................................................................................................... 40

1.5.2.1. Dimentsio bakarreko bektoreak ......................................................... 40 1.5.2.2. Dimentsio anitzeko bektoreak ........................................................... 44 1.5.2.3. Begizta bat bektorizatu ahal izateko baldintza ............................... 46

1.5.2.4. Datu-dependentziak analizatzeko proba ......................................... 46

▪ vi ▪ AURKIBIDEA

1.5.3. Optimizazioak ..................................................................................................... 50 1.5.3.1. Aurreranzko ordezkapen globala (global forward substitution) ........... 50

1.5.3.2. Indukzio-aldagaiak ........................................................................................... 51 1.5.3.3. Antidependentziak (WAR) ........................................................................... 52 1.5.3.4. Irteera-dependentziak (WAW) .................................................................. 53

1.5.3.5. Begizta-trukea (loop-interchanging) ........................................................ 54 1.5.3.6. Hedapen eskalarra (scalar expansion) ................................................... 57 1.5.3.7. Begizten fusioa (loop fusion) ..................................................................... 57 1.5.3.8. Begizten kolapsoa (loop collapsing) ....................................................... 58 1.5.3.9. Beste zenbait optimizazio ............................................................................ 59

1.5.4. Maskara- eta Indize-bektoreak ................................................................................... 60 1.5.4.1. Maskaren erabilera .......................................................................................... 60 1.5.4.2. Indize-bektoreak ............................................................................................... 61

1.6. Laburpena ........................................................................................................... 64

2. kapitulua. Konputagailu Paraleloak (oinarrizko kontzeptuak) ....... 69

2.1. Sarrera ................................................................................................................. 69

2.2. DM-SIMD konputagailuak .............................................................................. 71 2.3. MIMD konputagailuak ..................................................................................... 73

2.3.1. Memoria partekatua (shared memory) ................................................................. 73 2.3.2. Memoria banatua edo pribatua (distributed memory) .................................. 74 2.3.3. Memoria logikoki partekatua baina fisikoki banatua

(distributed shared memory) ..................................................................................... 75 2.3.4. Clusters, constellations... eta abar ............................................................................ 76

2.4. Arazoak ............................................................................................................... 77

2.5. Sistema paraleloen eraginkortasuna. Amdahl-en eta Gustafson-en legeak ......................................................................................... 79

3. kapitulua. Datuen koherentzia SMP Konputagailuetan .......... 83

3.1. Problemaren nondik norakoa eta kontzeptuen berrikuspena ................. 83 3.1.1. Datuen koherentzia prozesadore bakarreko konputagailuetan .................. 84 3.1.2. Datuen koherentzia memoria partekatuko multiprozesadoreetan ............ 85 3.1.3. Partekatze faltsua ............................................................................................................ 87 3.1.4. Koherentziaren definizioa ........................................................................................... 87

3.2. Zelatatze motako koherentzia-protokoloak ................................................ 88 3.2.1. Bloke baten egoerak, eta kontrol-seinaleak ......................................................... 90 3.2.2. Baliogabetze-protokoloak ............................................................................................ 94

3.2.2.1. Hiru egoerako protokolo bat, MSI ........................................................... 94 3.2.2.2. Illinois protokoloa, MESI ............................................................................... 97 3.2.2.3. Berkeley protokoloa, MOSI ......................................................................... 99 3.2.2.4. Baliogabetze-protokoloen laburpena .................................................... 101

AURKIBIDEA ▪ vii ▪

3.2.3. Eguneratze-protokoloak ............................................................................................. 101 3.2.3.1. Firefly protokoloa, MSE(I) .......................................................................... 102 3.2.3.2. Dragon protokoloa, MOES(I) .................................................................. 104

3.2.4. Zelatatze-protokoloen laburpena ........................................................................... 105

3.3. Zelatatze-protokoloen gauzatzea ................................................................ 105 3.3.1. Arazoak ............................................................................................................................. 105

3.3.1.1. Cachearen direktorioa ................................................................................. 106 3.3.1.2. Idazketa-bufferrak .......................................................................................... 107 3.3.1.3. Bus-eskaerako protokoloa .......................................................................... 108 3.3.1.4. Atomikotasuna: koherentzia-kontrolagailuaren egoera ................. 109

3.3.2. Illinois koherentzia-protokoloa berriz ................................................................... 110 3.3.2.1. Lasterketak: egoera iragankorrak, kontrol-seinaleak ....................... 110 3.3.2.2. Deadlock, livelock eta starvation arazoak ........................................... 112

3.4. Zelatari hierarkikoa ......................................................................................... 113 3.4.1. Irakurketak ....................................................................................................................... 115 3.4.2. Idazketak .......................................................................................................................... 116

4. kapitulua. Prozesuen Sinkronizazioa SMP Konputa-gailuetan ......................................................................... 119

4.1. Sarrera ............................................................................................................... 119 4.2. Elkarrekiko esklusioa (mutual exclusion) .................................................... 123

4.2.1. Test&Set eta Swap aginduak .................................................................................... 125 4.2.1.1. Test&Set agindua ........................................................................................... 125 4.2.1.2. Swap agindua .................................................................................................. 125 4.2.1.3. Trafikoaren analisia ........................................................................................ 126 4.2.1.4. Test&Set with backoff prozedura ............................................................ 127 4.2.1.5. Test-and-Test&Set prozedura .................................................................... 128 4.2.1.6. Ezaugarrien laburpena ................................................................................. 130

4.2.2. Load Locked / Store Conditional eta Compare&Swap aginduak ............. 131 4.2.2.1. LL eta SC aginduak ........................................................................................ 132 4.2.2.2. Compare&Swap agindua ............................................................................ 134 4.2.2.3. Zenbait arazo LL eta SC aginduekin ...................................................... 135

4.2.3. Fetch&Op aginduak ..................................................................................................... 136 4.2.4. Trafikoa murrizteko hobekuntzak .......................................................................... 137

4.2.4.1. Txartelak............................................................................................................. 137 4.2.4.2. Sarraila-bektoreak .......................................................................................... 139

4.3. Puntutik punturako sinkronizazioa gertaeren bidez (events) ................. 141

4.4. Hesien bidezko sinkronizazioa (barriers) ................................................... 142 4.4.1. Hesi sinple batv142 4.4.2. Hesi berrerabilgarriak .................................................................................................. 143 4.4.3. Eraginkortasuna .............................................................................................................. 145

4.5. Laburpena ......................................................................................................... 146

▪ viii ▪ AURKIBIDEA

5. kapitulua. Memoriaren Kontsistentzia Konputagailu Paraleloetan ................................................................... 149

5.1. Sarrera ............................................................................................................... 149 5.1.1. Prozesadore bakarreko sistemak ............................................................................ 149 5.1.2. Multiprozesadoreak ..................................................................................................... 150 5.1.3. Programen semantika eta aginduen exekuzio-ordena .................................. 151 5.1.4. Aginduen atomikotasuna ........................................................................................... 153 5.1.5. Kontsistentzia-ereduak ................................................................................................ 154

5.2. Kontsistentzia sekuentziala (SC, sequential consistency)........................ 155 5.2.1. Memoria-eragiketen ordena eta atomikotasuna .............................................. 156 5.2.2. Eragina hardwarean eta konpiladorean ............................................................... 158

5.3. Eredu malguak (relaxed) ................................................................................ 159 5.3.1. Total Store Ordering (TSO) / Processor Consistency (PC) ........................ 160 5.3.2. Partial Store Ordering (PSO) ................................................................................... 162 5.3.3. Eredu malguenak ........................................................................................................... 162

5.3.3.1. Weak Ordering (WO) ................................................................................. 163 5.3.3.2. Release Consistency (RC) ......................................................................... 164

5.4. Laburpena eta perspektibak ......................................................................... 166

6. kapitulua. Konputagailu Paraleloen Komunikazio Sarea. Mezu Ematearen bidezko Komunikazioa. ............ 169

6.1. Sarrera ............................................................................................................... 169 6.2. Sarearen topologia .......................................................................................... 171

6.3. Kommutagailuen bidezko sareak ................................................................. 173 6.3.1. Kommutagailua (switch) ........................................................................................... 174 6.3.2. Crossbar sarea ................................................................................................................ 174 6.3.3. Urrats anitzeko sareak (multistage) ...................................................................... 175

6.3.3.1. Omega sarea ................................................................................................... 176 6.3.3.2. Bideratzea Omega sarean .......................................................................... 178 6.3.3.3. Irteera-gatazkak eta blokeoak ................................................................... 179 6.3.3.4. Beste komunikazio mota bat: broadcast-a. ........................................ 181 6.3.3.5. Beste zenbait sare .......................................................................................... 181 6.3.3.6. Laburpena ......................................................................................................... 183

6.4. Mezu-bideragailuen bidezko sareak ........................................................... 184 6.4.1. Mezu-bideragailuak ...................................................................................................... 184 6.4.2. Sare-topologia erabilienak ......................................................................................... 185

6.4.2.1. Dimentsio bakarreko sareak: katea eta eraztuna (chain, ring) .... 186 6.4.2.2. Mailak eta toruak (mesh, torus) .................... 186 6.4.2.3. Hiperkuboak (hypercube) ......................................................................... 188 6.4.2.4. Arbolak eta arbola sendoak (fat tree) ................................................... 189

AURKIBIDEA ▪ ix ▪

6.4.2.5. Topologien laburpena .................................................................................. 191 6.4.2.6. Lotura fisikoak ................................................................................................. 192

6.5. Komunikazioa sarean zehar .......................................................................... 193 6.5.1. Mezuak.............................................................................................................................. 193 6.5.2. Norekin eta noiz komunikatu behar da? Komunikazio-patroiak ............... 195 6.5.3. Bidea eraikitzea (switching strategy) ................................................................... 197

6.5.4. Mezuak bideratzea (routing) .................................................................................. 199

6.5.4.1. Bideratze-erregistroa ..................................................................................... 199 6.5.4.2. Bide-aukeratzea: estatikoa edo moldakorra ....................................... 203

6.5.5. Informazio-jarioaren kontrola (flow control) .................................................... 205 6.5.5.1. Mezuak aurrera joateko teknikak: Store-and-forward,

Wormhole eta Cut-through ....................................................................... 206 6.5.5.2. Baliabide-gatazkak: paketeetarako bufferrak ..................................... 209

6.5.6. Komunikazioaren eraginkortasuna: mezuen latentzia eta mezu-emaria .................................................................................................................... 213

6.5.6.1. Sareko komunikazio-denbora ................................................................... 214 6.5.6.2. Trafikoa kontuan hartuz .............................................................................. 216 6.5.6.3. Mezu-emari maximoa .................................................................................. 218 6.5.6.4. Analisi globala ................................................................................................. 220

6.5.7. Zenbait komunikazio-arazo ...................................................................................... 221 6.5.7.1. Pakete-blokeoak (deadlock). Kanal birtualak. Biratze

kontrolatuak (Turn model). Paketeen injekzioa kontrola-tzea. Bide seguruen erabilera ................................................................... 222

6.5.7.2. Livelock eta Starvation arazoak ............................................................... 228

6.5.8. Komunikazio-protokoloak ......................................................................................... 229

6.6. Konputagailu paraleloen eboluzioa ............................................................. 231

Eranskina. Batez besteko distantzien kalkulua hainbat topologiatarako ....... 235

7. kapitulua. Datuen Koherentzia DSM Konputagailuetan ....... 241

7.1. Sarrera ............................................................................................................... 241 7.2. Koherentzia-direktorioak ............................................................................... 243

7.2.1. Sarrera eta sailkapena ................................................................................................. 243 7.2.1.1. Arazoak .............................................................................................................. 245

7.2.2. Direktorioen egitura ..................................................................................................... 246 7.2.2.1. Memoria nagusiaren ondoko direktorioak ......................................... 246 7.2.2.2. Cache memorietan banatutako direktorioak ..................................... 251

7.2.3. Koherentzia-trafikoaren optimizazioa .................................................................. 254 7.2.4. Eragiketen atomikotasuna: lasterketak ................................................................. 257

7.3. Koherentzia-protokoloen gauzatzea: bi adibide ................................................. 259 7.3.1. SGI Origin multikonputagailuetako koherentzia-protokoloa ...................... 259

7.3.1.1. Irakurketak ........................................................................................................ 260 7.3.1.2. Idazketak ........................................................................................................... 263 7.3.1.3. Memoria nagusiaren eguneratzeak ........................................................ 268

▪ x ▪ AURKIBIDEA

7.3.2. SCI koherentzia-protokolo estandarra (Sequent NUMA-Q) ...................... 269 7.3.2.1. SCI: egoerak eta eragiketak ....................................................................... 270 7.3.2.2. Irakurketak ........................................................................................................ 272 7.3.2.3. Idazketak ........................................................................................................... 273 7.3.2.4. Memoria nagusiaren eguneratzeak ........................................................ 277 7.3.2.5. Atomikotasuna eta lasterketak ................................................................. 277

7.4. Laburpena ......................................................................................................... 279

8. kapitulua. Begizten Paralelizazioa eta Atazen Banaketa ...... 281

8.1. Sarrera ............................................................................................................... 281 8.1.1. Oinarrizko ideiak begizten paralelizazioari buruz .......................................... 287

8.2. Begizten paralelismo-maila adierazteko egitura nagusiak ....................... 290 8.2.1. Iterazioen arteko dependentziarik gabeko begiztak: doall begiztak ...... 290 8.2.2. Iterazioen arteko dependentziak dituzten begiztak ....................................... 291

8.2.2.1. Forall begiztak (sinkronizazio globala) ................................................ 292 8.2.2.2. Doacross begiztak ("puntutik punturako" sinkronizazioa) .......... 293

8.2.3. Antidependentzien eta irteera-dependentzien eragina................................. 298

8.2.4. Adi if aginduekin ............................................................................................................ 299

8.3. Sinkronizazioaren gauzatzea ........................................................................ 300 8.3.1. Sinkronizazioa kontagailuen bidez ........................................................................ 301

8.3.2. Kontagailu bakar bat prozesadore bakoitzeko ................................................. 303

8.4. Begiztak eraginkorki paralelizatzeko optimizazio nagusiak ................... 304 8.4.1. Dependentziak ezabatu edo minimizatu ............................................................ 304 8.4.2. Begizten fisioa ................................................................................................................ 305 8.4.3. Aginduen berrordenatzea ......................................................................................... 306 8.4.4. Dependentzien lerrokatzea (peeling) .................................................................. 307 8.4.5. Hari independenteak sortzea (switching) .......................................................... 308 8.4.6. Sinkronizazioko eragiketa kopurua txikiagotzea ............................................. 309 8.4.7. Begizten tratamendua (berrordenatzea...) ......................................................... 311

8.4.7.1. Begizta-trukea .................................................................................................. 311 8.4.7.2. Noranzko-aldaketa ........................................................................................ 313

8.4.7.3. Desplazamenduak (skew) ......................................................................... 314 8.4.7.4. Begizten kolapsoa eta koaleszentzia ..................................................... 315

8.5. Atazen banaketa (scheduling) ........................................................................ 316 8.5.1. Banatzen diren iterazioak: ondoz ondokoak edo tartekatuak ................... 316 8.5.2. Banaketa estatikoa edo dinamikoa ........................................................................ 318

8.5.2.1. Banaketa estatikoa ........................................................................................ 318 8.5.2.2. Banaketa dinamikoa: autobanaketa (self eta chunk

scheduling), autobanaketa gidatua (GSS) eta trapezoidala (trapezoid self-scheduling) ............................................... 319

8.6. Atal paraleloak: Fork / Join ............................................................................ 323 8.7. Eraginkortasunaren analisia ........................................................................... 324

AURKIBIDEA ▪ xi ▪

9. kapitulua. Abiadura Handiko Konputagailu Paraleloak. Programazio Paraleloa: OpenMP eta MPI. ........... 327

9.1. Abiadura handiko konputagailuak ............................................................... 328

9.2. Programazio Paraleloa: OpenMP eta MPI (sarrera)................................. 332 9.2.1. OpenMP ........................................................................................................................... 333

9.2.2. MPI ...................................................................................................................................... 337

Bibliografia ..................................................................... 341

Glosarioa ........................................................................ 345

Sarrera

Zein eguraldi izango dugu bihar bailara honetan? Nola eboluzionatzen

dira galaxiak? Nolakoa da atomoen elkarrekintza klorofila-molekula batean? Hegazkineko hegoen portaera egokia izango da turbulentzia baten barruan? Galdera horiei, eta beste askori, erantzun egokia emateko, zientzialariek eta ingeniariek konputagailuak erabiltzen dituzte, konputagailuak baitira, gaur egun, laborategiko tresna nagusiak. Zientzia eta teknika arloetan exekutatzen diren programetan egin behar den kalkulu kopurua itzela da, ia mugaezina, eta gainera ahalik eta denbora laburrenean egin behar da (ordu baten barruan eroriko den euri erauntsia bihar asmatzea ez da errenta!); zoritxarrez, nahiz eta prozesadoreak gero eta azkarragoak izan, erabiltzaileen beharrak

▪ 2 ▪ SARRERA

handiagoak dira beti. Behar horiei irtenbide bat emateko, hau da, prozesadoreen exekuzio-abiadura handitzeko, hiru arlo jorratu dira, nagusiki, konputagailuen historian zehar: teknologia elektronikoa, sistemaren egitura edo arkitektura, eta software-teknologia.

Teknologia elektronikoaren bidez lortu da transistore kopuru itzela txip bakar batean integratzea: dagoeneko 1.000 milioitik gora (eta gero eta gehiago). Aurrerapen hori dela eta, gero eta "gailu" gehiago integratzen dira prozesadorearekin batera txip bakar batean: unitate funtzional bereziak, erregistroak, cache memoria... baita hainbat prozesadore edo nukleo (core) ere. Era berean, erloju-maiztasunak gero eta handiagoak dira, 1-4 GHz-eko tartean dagoeneko ("lasterketa" hori dagoeneko gelditu bada ere). Beraz, oinarrizko zikloaren denbora oso txikia da (F = 1 GHz → T = 1 ns), eta, ondorioz, eragiketa gehiago egin daitezke segundo bakoitzeko.

Sistemaren arkitekturaren aldetik, dagoeneko "klasikoak" diren estrategiak erabiltzen dira: aginduen exekuzio segmentatua, supereskalarra edo VLIW motakoa (txip bakar batean integratzen diren nukleoak sinpleagoak ohi dira); memoriaren egitura hierarkikoa, cachea ere hainbat mailatan banatuta, memoria-atzipen azkarrena erdiesteko; erregistro-multzoaren erabilera egokia, datuak eskuratzeko behar den denbora minimizatzearren; eta abar.

Konpilazio-teknikak ere asko aurreratu dira. Aginduen arteko datu- eta kontrol-dependentzien eragina minimizatzea da helburu nagusia, unitate funtzionalen latentzia —eragiketak betetzeko behar den denbora— "ezkutatu" ahal izateko (denbora hori lan baliagarria egiteko aprobetxatuz).

Hala ere, prozesadoreak oso azkarrak izan arren —azkarrenek 10 Gflop/s-ko kalkulu-abiadura erraz gainditzen dute—, ez dira behar adinakoak hainbat aplikaziotarako, haien artean, adibidez, eguraldiaren iragarpena, prozesu fisikoen eta kimikoen simulazioak, aeronautikako diseinuak, prospekzio geologikoak, material berrien diseinua, ingeniaritzako garapenak, biologiako, genetikako eta farmaziako ikerkuntzak, irudien prozesamendua eta abar.

1986-2002 urteetan, prozesadoreen errendimenduaren hobekuntza-tasa urteko % 52 (!) izan zen, baina tasa hori asko jaitsi da, % 20ra, azken urteetan: prozesadore bakar batekin lor daitekeen kalkulu-abiadura bere muga fisikoetara (eta ekonomikoetara) heldu da. Beraz, aipatutako aplikazioetarako behar diren kalkulu-abiadura handiak lortzeko (Teraflop/s, Petaflop/s..., hau da, segundoko 1012, 1015... koma higikorreko eragiketa), arlo berriak jorratu behar dira.

SARRERA ▪ 3 ▪

Konputagailuen eboluzioan eman behar den hurrengo "jauzia" argi dago: aplikazioen exekuzioa prozesadore askoren artean banatzea; hau da, paralelismoa eta sistema paraleloak erabiltzea. Gainera, txipak fabrikatzeko teknologiak erraztu egiten du aukera hori: prozesadore (txip) bat eginda, aise egiten dira milaka, prezio onean gainera. Beraz, zergatik ez erabili 100, 1.000, 10.000... prozesadore problema bat ebazteko? Teorian, eta P prozesadore nola erabili jakingo bagenu, P aldiz azkarrago exekutatuko genituzke programak. Zoritxarrez, ez dugu hori lortuko, arazo berri asko agertuko baitira: nola banatu behar da lana prozesadoreen artean? sinkronizatu behar al dira prozesuak? nola gauzatuko da haien arteko komunikazioa?...

Aukera asko dago P prozesadore konputagailu bakar bat gisa egituratzeko. Ezaugarri batzuk komunak dituzte eta beste batzuk, aldiz, ez. Arkitektura edo egitura horiek sailkatzeko saio bat baino gehiago egin da. Ezagunena eta erabiliena, sinplea eta zaharra izanda ere (1966), Flynn-en sailkapena da. Bi parametro kontuan hartzen dira sailkapen horretan: agindu-jarioen kopurua —hots, programa-kontagailuen kopurua— eta datu-jarioen kopurua. Irudian, Flynn-en sailkapena ageri da.

datu-jarioak bakarra asko

agindu-jarioak

bakarra SISD SIMD

asko MIMD

▪ SISD (Single-Instruction-Single-Data) motako konputagailuak Programa bakar batek datu multzo bakar batekin lan egiten du; beraz,

prozesadore bakarreko ohiko sistemak dira hauek (konputagailu pertsonalak, lan-estazioak...). Zenbait kasutan, prozesadore bat baino gehiago dago horietako makina batean, baina, eskuarki, modu independentean egiten dute lan.

Aipatu dugunez, oraingo prozesadoreek "segmentatuak" dira. Aginduen exekuzioa hainbat fasetan banatzen da —bilaketa, deskodeketa, eragigaien irakurketa, memoria, unitate aritmetikoa, emaitzen idazketa...—, eta fase edo urrats bakoitzean agindu bat (edo batzuk, prozesadore supereskalarren kasuan) ari da prozesatzen; beraz,

▪ 4 ▪ SARRERA

une oro hainbat agindu ari dira exekutatzen batera, fase desberdinetan: agindu-mailako paralelismoa erabiltzen da (ILP, Instruction Level Parallelism). Gainera, hardwarearen zein konpiladorearen laguntzaz, prozesadorea gauza da aginduen jatorrizko exekuzio-ordena aldatzeko, exekuzio ahalik eta eraginkorrena (azkarrena) erdiesteko.

Irakurleak kontzeptu horiek guztiak badakizkiela kontsideratuko dugu.

▪ SIMD (Single-Instruction-Multiple-Data) motako konputagailuak Mota honetako konputagailuetan, agindu bera exekutatzen da batera

prozesadore guztietan, baina datu desberdinak prozesatzen dira. Sistema hauetan, beraz, datu-mailako paralelismoa (DLP, Data Level Parallelism) ustiatzen da. Bi arkitektura bereizi ohi dira: array processors izeneko makinak (distributed memory SIMD) eta bektore-konputagailuak (shared memory SIMD).

Lehenbiziko kasuan, prozesadore asko eta "oso sinpleak" (esaterako, bit bateko 16 k prozesadore) erabili ohi ditu konputagailuak, eta prozesadore guztiek programa bera exekutatzen dute, modu sinkronizatuan, baina datu desberdinak prozesatuz. Mota horretako makina asko egin ziren 80-95 urte bitartean, eta oso eraginkorrak dira zenbait aplikaziotan (irudiak eta seinaleak prozesatzeko, zenbakizko kalkulua egiteko...), baina agortu den eredua da eta ez dira jadanik fabrikatzen (antzeko ideiak eta egiturak hiru dimentsioko ingurune birtualak sortzeko erabiltzen ari badira ere). Bai, ordea, bektoreak prozesatzen espezializatutako bigarren motako makinak, bektore-konputagailuak, alegia.

▪ MIMD (Multiple-Instruction-Multiple-Data) motako konputagailuak Arkitektura paraleloen kasu orokorra da. Prozesu asko exekutatzen

dira konputagailuan, datu multzo desberdinen gainean. Adi: ez da soilik SISD motako makina multzoa, prozesadoreetan exekutatzen diren programak ez baitira independenteak.

Hori da eredua abiadura handiko konputazioa eskuratzeko: paralelismo masiboko konputagailuak, non P prozesadore (kopuru handia) elkarlanean aritzen diren problema bat ebazteko; hau da, hari-mailako paralelismoa ustiatzen da (TLP, Thread Level Parallelism). Oro har, hari-mailako paralelismoak datu-mailakoak baino aukera gehiago eskaintzen du exekuzio-abiadura handiagotzeko.

SARRERA ▪ 5 ▪

Hala ere, sistema eraginkorrak lortu ahal izateko, irtenbide egokia bilatu beharko zaie prozesadore bakarreko sistemetan ageri ez diren hainbat arazo berriri.

Hurrengo kapituluetan ikusiko dugunez, bi motako arkitekturak bereiz daitezke MIMD sistemetan:

• Memoria partekatuko sistemak: prozesadore guztiek memoria-espazio bera erabiltzen dute. Memoria zentralizatuta (SMP, symmetric multiprocessors) edo banatuta (DSM, distributed shared memory) egon daiteke. Hala, prozesuen arteko komunikazioa aldagai partekatuen bidez egiten da.

• Memoria pribatuko sistemak: prozesadore bakoitzak memoria-espazio pribatua erabiltzen du. Kasu honetan, prozesuen arteko komunikazioa mezu-ematearen bidez egiten da.

Hurrengo kapituluetan, MIMD motako konputagailu paraleloak aztertuko

ditugu. Lehenbizikoan, ordea, SIMD gisa sailka daitezkeen konputagailu berezi eta oso eraginkorrak analizatuko ditugu: bektore-konputagailuak. Horien arkitektura berezia da, eta leku garrantzitsua lortu dute konputazioaren historian. Bigarren kapituluan, sistema paraleloen aurkezpen xumea egingo dugu: eredu eta arkitektura nagusiak, arazo behinenak, Amdahl-en legea... Hirugarren kapituluan, SMP sistemen datuen koherentzia aztertuko dugu: zelatatze-protokoloak; laugarrenean, prozesuen arteko sinkronizaziorako agindu eta prozedura bereziak: T&S, LL, SC...; eta bosgarrenean, memoria-sistemaren kontsistentzia-ereduak: kontsistentzia sekuentziala eta eredu malguak. Seigarren kapituluan, prozesadoreen arteko komunikazioa ahalbidetzen duten sareen topologia, egitura eta erabilera aztertuko ditugu, bai eta prozesadoreen arteko komunikazioen eraginkortasuna ere. Zazpigarrenean, datuen koherentzia analizatuko dugu berriro, baina DSM sistemetan: koherentzia-direktorioak. Zortzigarrenean, begizten paralelizazioa eta iterazioen banaketa analizatuko ditugu. Azkenik, konputagailu paraleloen eboluzioa, merkatua, oraingo egoera eta etorkizuna ikusiko ditugu (top500 zerrenda), bai eta, gainetik bada ere, sistema paraleloak programatzeko oinarrizko tresnak ere: OpenMP (memoria partekatuko SMP sistemetarako) eta MPI (mezu-ematea, DSM zein MPP sistemetarako).

▪ 1 ▪

Bektore Konputagailuak

1.1. ZER DIRA BEKTORE KONPUTAGAILUAK?

Sarreran aipatu dugunez, MIMD motako makinak dira problema orokorrak paraleloan ebazteko arkitekturarik egokienak. Hala ere, problema garrantzitsu jakin batzuetarako, eraginkortasun handiko exekuzioak lor daitezke beste arkitektura mota bat erabiliz.

Kalkulu zientifikoko programen exekuzio-denbora gehiena begiztak exekutatzen xahutzen da. Esaterako:

do i = 0, N-1 C(i) = A(i) + B(i) enddo

N oso handia bada (N = 109 esaterako), benetan sinplea den begizta horren exekuzio-denbora oso luzea izango da. Prozesadore eskalar batean exekutatzen bada, hau bezalako kodea exekutatuko da (adibidez):

▪ 8 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

beg: FLD F1,A(R1) FLD F2,B(R1) FADD F3,F2,F1 FST C(R1),F3

ADDI R1,R1,#8 SUBI R2,R2,#1 BNZ R2,beg

Prozesadore eskalar batean, kasurik onenean, agindu bat zikloko exekutatuko da, hau da, gutxienez 7 ziklo beharko ditugu begizta-iterazio bat exekutatzeko; ondorioz, programaren exekuzio-denbora osoa TE = 7N ziklo izango da1.

Bi ezaugarri berezi ditu aurreko begiztak. Batetik, prozesatzen diren datu-egiturak oso erregularrak dira: A, B eta C bektoreak; eta, bestetik, begizta-iterazio guztiak edozein hurrenkeratan exekuta daitezke, ez baitago inongo datu-dependentziarik haien artean. Defini dezagun zer diren, testuinguru honetan, bektoreak. Hiru parametro hauen bidez definitzen den datu-egitura da bektorea:

• hasiera-helbidea: bektorearen aurreneko osagaiaren memoria-helbidea.

• luzera: bektorearen osagai kopurua. • pausoa (stride): ondoz ondoko bi osagairen arteko distantzia

memorian.

Adibidez, 1000, 1002, 1004, 1006, 1008, 1010, 1012 eta 1014 memoria-posizioetan metatzen den bektorea (osagai bat memoria-posizio bakoitzeko) honela definitzen da:

hasiera-helbidea = 1000 luzera = 8 pausoa = 2

Prozesadore eskalar batek, izenak dioen moduan, datu eskalarrekin (zenbaki soilekin) egiten du lan. Zientzia- eta ingeniaritza-alorretan, aldiz, bektoreak oso maiz erabiltzen dira, eta aurrekoa bezalako programak behin eta berriz exekutatu behar izaten dira, eta, ondorioz, denbora luzeak behar izaten dira. Zergatik ez erabili arkitektura eta makina-lengoaia bereziak, zuzenean bektoreak prozesatzeko? Esaterako, zergatik ez idatzi aurreko programa beste modu honetan? 1 Prozesadorea supereskalarra bada, agian zikloko agindu bat baino gehiago exekutatuko da; exekuzio-

denbora, beraz, txikiagoa izan daiteke.

1.1. ZER DIRA BEKTORE KONPUTAGAILUAK? ▪ 9 ▪

LV V1,A(R1) ; irakurri A bektorea LV V2,B(R1) ; irakurri B bektorea ADDV V3,V1,V2 ; batu bi bektoreak (emaitza, V3 erregistroan) SV C(R1),V3 ; idatzi emaitza C bektorean

Zer adierazi (exekutatu) nahi dugu LV V1,A(R1) aginduarekin? Bada, honako hau (segmentazio-eskema adibide bat baino ez da2):

LV V1,A(R1) BD Ir AM M M M Id

Ir AM M M M Id

Ir AM M M M Id

Ir ... ... ... ...

Ir AM M M M Id

Adierazpena sinplifikatzeko, honela ere adieraz daiteke bektore-agindu baten exekuzioa:

LV V1,A(R1) BD Ir AM M M M Id Id ... ... Id

Hau da, agindu bakar batekin bektore osoa (N osagai) irakurtzen da memoriatik, ez osagai bakar bat! Horretarako, memoriak tartekatua izan behar du; hala, beste arazorik izan ezean, osagai bat eskuratu ahal izango dugu memoriatik ziklo bakoitzean, eta bektore-erregistro batean idatzi.

Honela geratuko litzateke aurreko programaren exekuzioa (unitate funtzionalen latentziak adibide jakin bat baino ez dira):

LV V1,A(R1) BD Ir AM M M M Id ... (N ziklo) ...

LV V2,B(R1) BD Ir AM M M M Id ... (N ziklo) ...

ADDV V3,V1,V2 BD . . . . Ir A A Id ... (N ziklo) ...

SV C(R1),V3 BD Ir AM . . . . Ir M M M Id ... ... Id

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ... ... 14+N

th N

(oraingoz, demagun irakur daitezkeela ADDV eta SV aginduetako eragigaiak taulan markatu ditugun zikloetan, 8an eta 11n, alegia).

2 Ohiko exekuzio faseak: BD, agindua bilatzea eta deskodetzea; Ir, eragigaiak irakurtzea; AM,

memoriako helbideen kalkulua; A, eragiketa bat unitate funtzional batean; M, eragiketa bat memorian; Id, emaitzak erregistroetan idaztea. Behar dituen faseak baino ez ditu erabiltzen agindu bakoitzak.

▪ 10 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Exekuzio-eredua hori bada, analisi sinple bat egin daiteke programaren exekuzio-denbora kalkulatzeko (sinplifikazio asko ari gara egiten; geroxeago formalizatuko ditugu kalkuluak): azken aginduaren idazketa faseari ekin baino lehen, ziklo kopuru jakin bat behar da, hasiera-denbora, th; eta gero, exekuzioa bukatzeko, N ziklo behar dira, bektore-osagai bakoitzeko bat. Beraz:

TB = th + N Adierazpen hori prozesadore eskalar baterako lortu dugunarekin

konparatzen badugu, garbi ageri da abantaila. Esaterako, bektoreen osagai kopurua N = 128 bada eta th = 14 ziklo bada, honako exekuzio-denbora hauek izango ditugu:

TE = 7 N = 896 ziklo TB = th + N = 142 ziklo (aurrekoaren % 16)

Ez da hori abantaila bakarra. Batetik, begiztari dagozkion kontrol-dependentzia3 guztiak desagertu dira, definizioz begizta bera desagertu baita bektore-kode berrian. Bestetik, 4 agindu baino ez da exekutatu behar, eta ez 7N, begizta eskalarrekoak. Hori dela eta, agindu-cachea askoz gutxiago erabiliko da, eta, ondorioz, buseko trafikoa txikiagoa izango da.

Baina, jakina, hori guztia ez dator musu-truk. Egia esan, gauza asko aztertu eta analizatu behar ditugu xeheago aurreko exekuzio-eskeman, agindu berezi horiek exekutatzeko beharko diren baliabideak ezagutzeko.

1.1.1. Zenbait arazo

1.1.1.1. Bektore-konputagailu baten memoria

Bektore-prozesadore batek modu intentsiboan erabiltzen du memoria. Esaterako, aurreko adibidean, hiru aginduk erabiltzen dute batera memoria: bi LV eta SV bat; eta, gainera, agindu bakoitzak N "hitz" irakurri edo idatzi behar ditu memorian! Bi arazo konpondu behar dira:

1. Zenbat bus daude memoriarako? Memoria-sistema eta prozesadorea datu-bus baten bidez komunikatzen dira. Memoriako bektore-agindu

3 Jauzi-aginduen exekuzioari dagozkio kontrol-dependentziak. Eskuarki, i helbideko aginduaren

ondoren i+1 helbideko agindua exekutatzen da, jauzi-aginduen kasuan izan ezik. Jauzi bat exekutatu behar denean, ez dugu jakingo zein den hurrengo aginduaren helbidea jauziaren exekuzioa bukatu arte. Beraz, prozesadorea gelditu egin beharko da (hala ere, badago hainbat teknika ziklo horiek ez galtzeko, eta programaren exekuzioarekin jarraitu ahal izateko).

1.1. ZER DIRA BEKTORE KONPUTAGAILUAK? ▪ 11 ▪

bakar batek N hitzeko transferentzia eskatzen du, eta, beraz, N ziklotan zehar okupatuko du busa (demagun hitz bakar bat transferitzen dela ziklo bakoitzean). Ondorioz, komunikazio-bus bakarra balego, agindu bakar batek erabili ahal izango luke memoria, eta gainerakoek itxaron egin beharko lukete aurrekoak bukatu arte, busa erabili ahal izateko. Ondorioz, exekuzio-denbora ez litzateke N ordenakoa izango, baizik eta kN-koa (k = 2, 3..., memoria-aginduak).

2. Ez al da gatazkarik izango memoria-moduluen erabilera dela eta? Nahiz eta memoria-espazioa tartekatua izan (hainbat memoria-moduluren artean), litekeena da memoria-modulu berean izatea behar diren bektore-osagaiak. Beraz, atzipen bati ekiteko, itxaron egin beharko genuke aurreko atzipena bukatu arte. Hortaz, exekuzio-denbora handiagoa izango litzateke.

Izan ere, bektore-konputagailu baten memoria-sistema oso garrantzitsua da: memoriarako bide (bus) asko behar dira, eta memoriak tartekatuta egon behar du, modulu askotan, atzipen-gatazkak minimizatu ahal izateko.

1.1.1.2. Unitate funtzionalak

Aurreko exekuzio-eskema aztertu ondoren, argi eta garbi ageri da unitate funtzionalek segmentatuak izan behar dutela. Agindu bakar batekin (ADDV, esaterako) N eragiketa (batuketa) exekutatzen dira, zikloko bat. Batugailua segmentatuta ez balego, ez litzateke posible izango datu bat zikloko lortzea. Era berean, mota bakoitzeko unitate funtzional bat baino gehiago izatea egokia izango da, agindu batek N ziklotan zehar okupatuko baitu unitate funtzionala.

1.1.1.3. Bektore-erregistroak

Zer dira bektore-erregistroak? Zer tamainakoak dira? Nola irakurtzen eta idazten dira?

Bektore-erregistro batean, bektore baten osagaiak gordetzen dira. Osagai bakoitza, eskuarki, koma higikorreko eskalar bat da, 64 bitekoa esaterako. Beraz, bektore bat gordetzeko, 64×N bit behar ditugu. Erregistroen edukiera, jakina, ez da mugagabea. Kasurik arruntenetan, 64 edo 128 bektore-osagai gordetzeko gauza dira (Lmax); hots, bektore-erregistro batean 64 (edo 128) × 64 = 4 (edo 8) kilobit gordetzen dira.

Tamainari erreparatuz, aise ulertzen da erregistro-multzoan erregistro asko ez izatea. Eskuarki, 8-16 erregistro izango ditugu (16 × 8 = 128 kilobit).

▪ 12 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Zenbait konputagailutan, erregistroen tamaina moldakorra da; hau da, erregistro-multzoko "memoria-espazioa" luzera txikiko erregistro asko edo luzera handiko erregistro gutxi definitzeko erabil daiteke.

Zer egin prozesatu behar ditugun bektoreen tamaina Lmax maximo hori (64 edo 128) baino handiagoa bada? Bada, begizta bat osatu behar da, eta iterazio bakoitzean Lmax osagai prozesatu (strip mining). Berriro agertuko dira, beraz, kontrol-dependentziak, nahiz eta orain 64 (128) alditik behin izan.

Aurreneko bektore-konputagailuetan, bektore-erregistroak "bloke" bat gisa tratatzen ziren; hala, esaterako, bektore baten osagai guztiak idatzi arte ezin zen erregistroaren edukia irakurri. Oraingo bektore-konputagailuetan, aldiz, bektore-erregistro bat osatzen duten elementuak independenteki helbidera daitezke, eta, ondorioz, erregistro baten lehenengo osagaiak irakurri egin daitezke oraindik osagai guztiak idatzita ez badaude ere.

Bestalde, bektore bat idazteak hainbat ziklo behar dituenez, agindu bat baino gehiago izango dira idazten, aldi berean, erregistro-multzoan. Nahitaez, erregistroetarako idazketa-bus bat baino gehiago (asko) beharko ditugu (era berean, irakurketa-bus ugari ere beharko ditugu).

Bektore-konputagailuen erregistroak, beraz, gailu konplexuak dira.

1.1.1.4. Programak

Zer programa mota exekuta daiteke bektore-konputagailu batean? Bektore-konputagailuak optimizatuta daude bektoreak prozesatzeko. Baina, programa errealetan, bektoreak prozesatzeaz gain kode eskalarra ere prozesatu beharko da. Nola egiten da hori? Zer eragin dauka kalkulu-abiaduran? Gero ikusiko dugun moduan, kalkulu eskalarraren eragina oso handia izan daiteke sistema osoaren errendimenduan.

Bestalde, azter dezagun berriro zer egiten dugun bektoreak prozesatzen ditugunean. Kontuan hartu adibide hau:

do i = 0, N-1 A(i) = A(i) + 1 enddo

bektore-erregistroak U.F.

1.1. ZER DIRA BEKTORE KONPUTAGAILUAK? ▪ 13 ▪

Eskalarki exekutatzen bada, eta sinplifikatuz, honako hau izango litzateke aginduen hurrenkera (L = load; S = store; + = batuketa; i = bektorearen i osagaia):

L0 +0 S0 / L1 +1 S1 / L2 +2 S2 / L3 +3 S3 / ... / LN–1 +N–1 SN–1

Bektore gisa exekutatuz gero (LV - ADDV - SV), beste hurrenkera hau izango genuke:

L0 L1 L2 ... LN–1 / +0 +1 +2 ... +N–1 / S0 S1 S2 ... SN–1

Hau da, begizta bektorialki exekutatzen bada, ez da errespetatuko aginduen jatorrizko hurrenkera. Zoritxarrez, hainbat kasutan ezin da hurrenkera hori aldatu, errespetatu egin behar baitira aginduen arteko datu-dependentziak. Beraz, kasu horietan ezin izango dugu begizta bektorialki exekutatu. Programa bat bektore moduan exekuta daitekeen ala ez erabakitzeko, datu-dependentziak sakon analizatu behar dira; ikusiko dugun moduan, bektore-konpiladoreak asko lagunduko digu langintza horretan.

Aurreko guztia laburbilduz: balizko eraginkortasun handiko eredua definitu badugu ere, arazo asko gainditu beharko ditugu kalkulu-abiadura handiak lortzeko.

1.1.2. Arkitektura eta makina-lengoaia

Bektore-konputagailuen arkitekturak askotarikoak dira, fabrikatzaileen arabera. Hasierako bektore-konputagailuek ez zituzten erregistroak erabiltzen, eta eragiketa guztiak memoriarekin egiten ziren. Eredu horri "Memoria-Memoria" (M/M) deritzo. Baina laster bektore-erregistroak gehitu ziren, eta hala dira oraingo bektore-prozesadore guztiak: bektore-eragiketen eragigaiak erregistroetatik hartzen dira eta emaitzak erregistroetan uzten dira (R/R eredua).

Hurrengo irudian, bektore-konputagailu baten eskema logikoa ageri da. Bi atal bereiz daitezke: atal eskalarra eta atal bektoriala. Prozesadore eskalarra aginduak bilatzeaz eta deskodetzeaz arduratzen da. Agindua arrunta bada, eskalarra, berak exekutatuko du, behar diren erregistroak erabiliz; bektoriala bada, aldiz, bektore-prozesadoreari pasatuko dio kontrola, agindua exekuta dezan. Besterik adierazi ezean, kontrol-unitatea Tomasulo eredukoa (desordena / desordena) izango da.

▪ 14 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Aipatu dugunez, bektoreak prozesatuko baditugu ere, errealitatean kode eskalarraren eta bektorialaren nahastea izango dugu programa gehienetan. Beraz, agindu eskalarrak zein bektorialak erabili beharko ditugu. Agindu eskalarrak ez ditugu aipatuko, ohikoak baitira.

Bektore-agindu mota asko dago, formatu askotarikoak, konputagailuen arabera. Hona hemen adibide ohikoenak (geroxeago aztertuko ditugu beste batzuk):

OPV Vi,Vj,Vk Vi = Vj OP Vk (OP = ADD, SUB, MUL, DIV...) Bi bektoreren arteko eragiketa. Emaitza bektore

bat da.

OPVS Vi,Vj,Fk Vi = Vj OP Fk OPVI Vi,Vj,#b Vi = Vj OP #b (OP = ADD, SUB, MUL, DIV...) Bektore baten eta eskalar baten arteko eragiketa.

Emaitza bektore bat da.

LV Vi,A(Rj) Irakurri egiten da memorian (A+Rj) hasiera-helbideko bektorea, eta Vi erregistroan uzten da (helbideratze-modu gehiago egon daiteke).

SV A(Rj),Vi Antzekoa, baina bektore bat memorian idazteko.

Erregistroak

Unitate funtzionalak

Prozesadore eskalarra (osoa)

Bektore-prozesadorearen

kontrola

Helbideetako unitatea (datuak)

Mem

oria

(erag.)

1.2. DATU DEPENDENTZIAK ▪ 15 ▪

Hiru parametro eman behar dira bektore bat identifikatzeko: hasiera-helbidea, luzera eta pausoa. Hasiera-helbidea LV/SV aginduetan bertan adierazten da (helbideratze-moduen arabera). Bektorearen luzera eta pausoa, aldiz, lehenago adierazi behar dira. Bi erregistro berezi erabiliko ditugu horretarako: VL (vector length), luzera emateko (zenbat osagai), eta VS (vector stride), pausoa zehazteko. VL-ren edukia Lmax (erregistroen tamaina maximoa) baino handiagoa bada, Lmax osagai prozesatuko dira.

Adibidez, honako agindu hauek exekutatu behar ditugu bektore bat irakurtzeko:

MOVI VL,#64 ; bektorea 64 osagaikoa da MOVI VS,#8 ; pausoa 8 da

LV V1,A(R1)

Hala, bektore baten 64 osagai kargatuko dira V1 erregistroan, A+R1, A+R1+8, A+R1+16, A+R1+24... helbidekoak.

Zenbait konputagailutan, bektoreen pausoa esplizituki adierazi behar da aginduan bertan, eta horretarako erregistro-multzoko erregistro orokor bat erabiltzen da.

1.2. DATU DEPENDENTZIAK

Prozesadore (super)eskalarretan gertatzen den bezala, datu-dependentziek mugatu egiten dute bektore-prozesadoreen kalkulu-abiadura. Bi aginduren artean datu-dependentzia dagoela esaten dugu, baldin eta bigarrenak lehenengoak sortuko duen emaitza erabili behar badu; beraz, eragigaia eskuratzeko, bigarren agindua gelditu egin beharko da aurrekoaren exekuzioa bukatu arte. Datu-dependentzien eragina arintzeko, zirkuitulaburrak (unitate funtzionalen arteko konexio bereziak) erabiltzen dira prozesadore eskalarretan (forwarding). Bektore-prozesadoreetan ere antzeko ideia erabiltzen da.

Hurrengo adibideetarako, honako segmentazio-eskema hau erabiliko dugu (Tomasulo):

LV/SV → BD Ir AM M M M Id

ADDV → BD Ir A A Id

▪ 16 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

1.2.1. Kateaketa (chaining)

Bi agindu kateatu egiten direla esaten da, baldin eta lehenengoak sortzen dituen bektore-osagaiak bigarrenak erabiltzen baditu, sortu ahala, bektore-erregistroan gorde arte itxaron gabe. Ikus dezagun adibide sinple bat:

do i = 0, N-1 LV V1,A(R1) A(i) = A(i) + 1 → ADDVI V2,V1,#1 enddo SV A(R1),V2

Programa horrek datu-dependentzia garbiak ditu: LV → ADDVI (V1) eta ADDVI → SV (V2). Nola exekutatzen da, bada, programa hori? Bi aukera ditugu: aginduen arteko kateaketa egin gabe, edo aginduen arteko kateaketa eginez.

a. Kateaketa egiten ez bada, bigarren aginduak itxaron egin behar du lehenengoa bukatu arte, dagokion bektore-erregistroa (V1) irakurri ahal izateko. Irudian, exekuzioaren eskema bat ageri da (aztertu noiz exekutatzen diren Ir faseak).

LV V1,A(R1) BD Ir AM M M M Id ... Id

ADDVI V2,V1,#1 BD . . . . . ... . Ir A A Id ... Id

SV A(R1),V2 BD Ir AM . . ... . . . . . ... . Ir M M M Id ...

zikloak ← 6 → ← N → ← 3 → ← N → ← 4 → ← N

Beraz, honako exekuzio-denbora hau lortzen da: TB = 13 + 3N ziklo.

b. Aldiz, kateaketa egiten bada, sortu ahala erabiltzen dira bektore-

osagaiak hurrengo unitate funtzionalean; hots, prozesadore eskalarretan ohikoa den Id → Ir zirkuitulaburra egiten da.

LV V1,A(R1) BD Ir AM M M M Id Id ... (N ziklo) ...

ADDVI V2,V1,#1 BD . . . . Ir A A Id Id ... (N ziklo) ...

SV A(R1),V2 BD Ir AM . . . . Ir M M M Id ... ... Id

zikloak ← 6 → ← 3 → ← 4 → ← N →

Orain, beste hau izango dugu exekuzio-denbora: TB = 13 + N ziklo.

1.2. DATU DEPENDENTZIAK ▪ 17 ▪

Portaera hori kualitatiboki ere azter daiteke. Esaterako, honela exekutatuko da aurreko programa (LV / ADDV / SV), denboran zehar, kateaketaren arabera:

kateaketa erabili gabe: T ~ 3N kateaketa erabiliz: T ~ N

Desberdintasuna ageri-agerian dago. Lehenbiziko kasuan, exekuzio-denbora 3N ordenakoa da; bigarrenean, aldiz, N ordenakoa baino ez. Esaterako, N = 64 bada, exekuzio-denbora 13 + 3×64 = 205 ziklotik 13 + 64 = 77 ziklora jaisten da (% 38). Beraz, eraginkortasuna lortzeko bektore-konputagailuetan, aginduak kateatzeko aukera izatea ia ezinbestekoa da.

1.2.1.1. Kateaketa bi agindurekin

Aurreko adibidean, agindu bakar batekin egin da eragigaien kateaketa: ADDVI agindua LV aginduarekin, edo SV agindua ADDVI aginduarekin. Kasurik konplexuenean, ordea, bi datu-jario erabili beharko genituzke kateaketarako. Ikus adibide hau (C = A + B):

LV V1,A(R1) BD Ir AM M M M Id Id ... (N ziklo) ...

LV V2,B(R1) BD Ir AM M M M Id Id ... (N ziklo) ...

ADDV V3,V1,V2 BD . . . . Ir A A Id Id ... (N ziklo) ...

SV C(R1),V3 BD Ir AM . . . Ir M M M Id ... ... Id

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 14+N

Hirugarren aginduak (ADDV) lehenengoak eta bigarrenak sortzen dituzten

V1 eta V2 bektoreak erabili behar ditu. Baina bi bektore horiek ez datoz "sinkronizatuta", lehenengoa 7. zikloan eta bigarrena 8. zikloan sortzen baitira (eta hortik aurrera gainerako osagaiak). Beraz, 7. zikloan ez dago prest bigarren eragigaiaren lehenengo osagaia, eta 8.ean "galdu" egin da lehenengoarena (ez da galdu, noski, bektore-erregistroan gordetzen ari baita).

LV

ADDVI

SV

ADDVI

SV

LV

▪ 18 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Kateaketa egiteko, honako hau egin beharko da: eragigai bat unitate funtzionaletik hartu, eta bestea idazten ari den erregistrotik (V1). Hori egin ahal izateko, erregistro-multzoak onartu egin behar du erregistro bat irakurtzea idazten ari den aldi berean (ohikoa da oraingo bektore-konputagailuetan: flexible chaining edo kateaketa malgua); hori egiterik ez badago, kateaketarako aukera galdu egingo da (beste soluziorik erabiltzen ez bada, behintzat) eta itxaron egin beharko da eragigaien idazketa bukatu arte.

1.2.2. Aginduen exekuzioko taulak

Bektore-programen exekuzioa urratsez urrats analizatzea astuna da. Hori dela eta, exekuzio-eskema horiek egin beharrean, taula batean bilduko ditugu aginduen exekuzioan zehar gertatzen diren ekintza edo datu nagusiak:

• Exekuzioaren hasiera: zenbat ziklo igaro diren, hasieratik, unitate funtzionala erabili baino lehen. Exekuzioaren hasiera arrunta izan daiteke (eragigaiak erregistroetatik irakurri ondoren), edo kateaketaren bidezkoa. Azken kasu horretan, [ ] artean jarriko dugu.

(aginduen exekuzioa segmentatua da, eta aginduak banan-banan exekutatzen dira; prozesadorea ez da supereskalarra)

• Unitate funtzionalaren latentzia. • Lehenbiziko osagaia sortzen den zikloa. • Azken (N) osagaia sortzen den zikloa.

Esaterako, LV agindurako, honako hau izango genuke:

BD Ir AM M M M Id ... ... Id

exekuzioaren hasiera (3) memoriaren latentzia (3) 1. datua (6+1) N. datua (6+N)

Honela laburtu daitezke aurreko bi adibideen exekuzioak:

kateaketa ez kateaketa bai

A = A + 1 Ex. has. UF lat. 1. dat. N. dat. Ex. has. UF lat. 1. dat. N. dat.

LV V1,A(R1) 3 3 6+1 6+N 3 3 6+1 6+N

ADDVI V2,V1,#1 6+N+1 2 9+N+1 9+2N [7] 2 9+1 9+N

SV A(R1),V2 9+2N+1 3 13+2N+1 13+3N [10] 3 13+1 13+N

1.3. EGITURAZKO DEPENDENTZIAK ▪ 19 ▪

Kateaketa erabiltzen ez bada, ADDVI aginduak itxaron egin behar du V1 idatzi arte (6+N zikloa), eta, gero, erregistroa irakurri beharko du (+1). Gauza bera gertatzen zaio SV aginduari: itxaron egin behar du ADDVI bukatu arte (9+2N zikloa); gero, V2 irakurriko du; eta, azkenik, memorian idatziko du.

Aginduen exekuzioa kateatzen bada, ordea, batuketa 7 zikloan has daiteke (ziklo horretan heltzen da memoriatik bektorearen lehenbiziko osagaia), eta memoria-idazketa 10 zikloan, batuketaren lehen emaitzako zikloan, hain zuzen ere.

Portaera bera islatzen da bigarren adibidean. Kateaketarik ez badago, ADDV aginduak itxaron egin behar du eragigai guztiak prest izan arte (7+N zikloa), eta gero biak irakurri. Kateaketa egiten denean, ordea, eragigai bat (V2) memoriatik hartuko da, eta bestea (V1) erregistrotik (hor idatzi da lehen osagaia aurreko zikloan); kateaketa-zikloa, beraz, 8a da.

kateaketa ez kateaketa bai

C = A + B Ex. has. UF lat. 1. dat. N. dat. Ex. has. UF lat. 1. dat. N. dat.

LV V1,A(R1) 3 3 6+1 6+N 3 3 6+1 6+N

LV V2,B(R1) 4 3 7+1 7+N 4 3 7+1 7+N

ADDV V3,V1,V2 7+N+1 2 10+N+1 10+2N [8] 2 10+1 10+N

SV C(R1),V3 10+2N+1 3 14+2N+1 14+3N [11] 3 14+1 14+N

Oharra: bektore-exekuzioko eredu didaktiko bat ari gara erabiltzen, eta helburua ez da xehetasunak azaltzea, portaera orokorra azaltzea baizik. Bektore-konputagailu errealetan antzeko estrategiak erabiltzen dira, estrategia horien gauzatzeak askotarikoak izan badaitezke ere.

1.3. EGITURAZKO DEPENDENTZIAK

Datu-dependentziak analizatu ondoren, azter ditzagun orain egiturazko dependentziak. Gogoratu: egiturazko dependentzia bat sortzen da erabili behar den baliabidea okupaturik dagoenean. Segur aski, memoria da gailurik garrantzitsuena bektore-konputagailuetan. Memoria erabiltzen denean, alde batetik, komunikazio-bideak edo busak erabiltzen dira. Baina, zenbat bus daude memoriarekin lan egin ahal izateko? Bestetik, memoria-moduluak

▪ 20 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

berak daude. Okupaturik daude? Une horretan erabili ezin bada, zenbat denbora itxaron beharko da memoria-modulu jakin bat erabili ahal izateko?

1.3.1. Memoriako busak (LV/SV unitate funtzionalak)

LV eta SV aginduek memoriarekiko datu-transferentzia bat egiten dute eta, horretarako, busak erabiltzen dituzte. LV edo SV agindu bat exekutatzen denean, busa N ziklotan mantentzen da okupaturik; agindu batek busa erabiltzen duen bitartean, besteek ezingo dute bus hori erabili, eta itxaron egin beharko dute, bidea libre izan arte. Ondorioz, bus kopurua "nahikoa" ez bada, aginduen exekuzio-abiadura ez da oso handia izango.

Bus kopuruaren eragina aztertzeko, har dezagun berriro aurreko adibidea (A = A + 1; LV / ADDVI / SV). Demagun kateaketa posible dela, baina bus bakarra dagoela memoriarekin lan egiteko (LV edo SV)4. Hala bada, hirugarren aginduak (SV) memorian idazten hasi behar duenean, kateaketa-zikloan, busa okupaturik dago, LV agindua erabiltzen ari baita oraindik (ziklo askotarako, gainera). Beraz, itxaron egin beharko du lehenengoa bukatu arte (busa libre izan arte), eta orduan irakurriko du idazten ari den bektore-erregistroa (V2)5.

Hau litzateke exekuzio-eskema:

LV V1,A(R1) BD Ir AM M M M Id Id ... (N ziklo) ... Id

ADDVI V2,V1,#1 BD . . . . Ir A A Id Id ... (N ziklo) ... Id

SV A(R1),V2 BD Ir AM . . . . ? . ... ... Ir M M M Id ... (N ziklo)

busa okupatuta... libre

edo, eskematikoki:

Honela adieraziko dugu exekuzio hori taula batean: 4 Oharra: memoriako busak LV zein SV aginduetarako erabil daitezke; zenbait makinatan, ordea, bus

"banatuak" erabiltzen dira, batzuk irakurtzeko eta beste batzuk idazteko. 5 Erregistroak idazten ari diren bitartean irakurri ezin badira, itxaron egin beharko da idazketa erabat

bukatu arte.

ADDVI

SV

LV

T ~ 2N

1.3. EGITURAZKO DEPENDENTZIAK ▪ 21 ▪

bus bakar bat / kateaketa A = A + 1 Ex. has. UF lat. 1. dat. N. dat.

LV V1,A(R1) 3 3 6+1 6+N

ADDVI V2,V1,#1 [7] 2 9+1 9+N

SV A(R1),V2 [6+N] 3 9+N+1 9+2N

Errepika dezagun analisia, baina lehen erabili dugun bigarren

adibidearekin. Lehenengo kasuan bus bakarra dago, eta bigarrenean bi; aginduen exekuzioa kateatu egin daiteke.

bus bat / kateaketa bi bus / kateaketa

C = A + B Ex. has. UF lat. 1. dat. N. dat. Ex. has. UF lat. 1. dat. N. dat.

LV V1,A(R1) 3 3 6+1 6+N 3 3 6+1 6+N

LV V2,B(R1) 6+N 3 9+N+1 9+2N 4 3 7+1 7+N

ADDV V3,V1,V2 [10+N] 2 12+N+1 12+2N [8] 2 10+1 10+N

SV C(R1),V3 [9+2N] 3 12+2N+1 12+3N [6+N] 3 9+N+1 9+2N

Bus bakar bat dagoenean, bigarren LV aginduak ezin du memoria erabili

aurrekoak busa askatzen duen arte, eta gauza bera gertatzen zaio SV aginduari (izan ere, busa askatzen denerako, V3 erregistroaren idazketa bukatzen ari da!). Ondorioz, exekuzio-denbora 3N ordenakoa da. Bi bus badaude, LV aginduak aldi berean exekutatuko dira, baina SV aginduak itxaron egin beharko du.

bus bat / kateaketa: 3N bi bus / kateaketa: 2N

Begien bistan dago ondorioa: memoria-aginduak exekutatzeko nahikoa baliabiderik ez badago, aginduak kateatzeko aukera izanda ere, exekuzio-denbora luzea izango da.

Bil ditzagun aurreko bi adibideen exekuzio-denborak, kateaketa eta bus kopurua kontuan hartuta:

LV LV

SV ADDV

LV

LV

SV ADDV

▪ 22 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

1. A = A + 1 (N = 64) kateaketa ez 13 + 3N = 205 ziklo → 3,20 ziklo/datu kateaketa / 1 bus 9 + 2N = 137 ziklo → 2,14 z/d kateaketa / 2+ bus 13 + N = 77 ziklo → 1,20 z/d

2. C = A + B (N = 64) kateaketa ez / 1 bus 16 + 4N = 272 ziklo → 4,25 z/d kateaketa ez / 3 bus 14 + 3N = 206 ziklo → 3,22 z/d kateaketa / 1 bus 12 + 3N = 204 ziklo → 3,19 z/d kateaketa / 2 bus 9 + 2N = 137 ziklo → 2,14 z/d kateaketa / 3 bus 14 + N = 78 ziklo → 1,22 z/d

Datuek argi eta garbi adierazten dutenez, memoriako bus asko izatea eta aginduak kateatu ahal izatea oinarrizkoa da exekuzio eraginkorrak lortzeko.

1.3.2. Gatazkak memoria-moduluetan

1.3.2.1. Memoria-eragiketa bakarra

Busen arazoa aztertu ondoren, analiza dezagun orain memoria nola erabiltzen den. Edozein konputagailuren memoria-sistema hainbat modulutan tartekatzen da; horrela, i eta i+1 helbideak ez dagozkio modulu berari, ondoz ondoko moduluei baizik. Badakigu zein den arrazoia: i helbideko hitza irakurri ondoren, i+1 helbidekoa irakurtzen da kasu gehienetan; bi hitz horiek memoria-modulu desberdinetan baldin badaude batera irakur daitezke, denbora aurrezteko (oro har, mk hitz irakur daitezke batera, mk modulu kopurua izanik). Gogoratu: eskuarki, modulu berean ezingo diogu eragiketa bati ekin aurrekoa bukatu arte. LV edo SV agindu bat exekutatzen denean, N irakurketa edo idazketa

egiten dira memorian, zikloko bat. Hori egin ahal izateko, libre dauden memoria-moduluetan gertatu behar dute atzipen horiek; bestela, baliabide-gatazkak izango ditugu, eta ez dugu lortuko eragiketa bat zikloko exekutatzea.

Arazoa non dagoen ikusteko, azter dezagun adibide bat. A(A0:A15) bektorea irakurri behar da; memoria 4 modulutan tartekatuta dago, eta bektorea ondoz ondoko posizioetan (s = 1) gorde da, m0 modulutik aurrera. Memoriaren latentzia 3 ziklo da. Bektorea irakurtzen ari denean, honako egoera hau izango dugu memoria-moduluetan:

1.3. EGITURAZKO DEPENDENTZIAK ▪ 23 ▪

m0 m1 m2 m3 A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 ...

→ denbora (zikloak)

m0 M M M M M M ... m1 M M M M M M ... m2 M M M M M M

m3 M M M M M M

m0 moduluan hasten da irakurketa; m1, m2, m3 moduluetan jarraitzen da

hurrengo zikloetan, eta berriro m0 modulura itzultzen da, hurrengo osagaiak irakurtzeko (ikus goiko irudia). Modulu hori libre dago une horretan, aurreko atzipena dagoeneko bukatu delako; beraz, ez dugu arazorik izango.

Baina, esaterako, memoriaren latentzia 8 ziklo bada, m0ra itzultzean okupatuta aurkituko dugu modulua, aurreko eragiketa oraindik bukatu gabe egongo baita! Beraz, itxaron egin beharko dugu modulu hori erabili ahal izateko, eta, ondorioz, exekuzio-denbora handiagoa izango da.

Arazoa larriagoa izan daiteke bektorearen definizioaren arabera; esaterako, A bektorearen pausoa s = 4 izango balitz, osagai guztiak modulu berean egongo lirateke, m0n, hain zuzen ere: atzipen guztietan arazoak izango genituzke, atzipen bakoitzak 3 ziklo dirau eta.

Memoria-gatazkak sortuko direnetz aztertzeko, beraz, hiru parametro kontuan hartu behar dira: memoriaren atzipen-denbora edo latentzia —tm—, modulu kopurua —mk—, eta bektoreen pausoa —s—. Hiru parametroetatik bi, latentzia eta modulu kopurua, diseinu-parametroak dira, hots, makina diseinatzen denean erabakitzen dira, eta erabiltzaileek ezin dituzte aldatu. Hirugarrena, bektoreen pausoa, aldiz, programei dagokie, eta, beraz, alda daiteke gatazkak saihestearren.

Pausoa s = 1 bada, memoria-modulu guztiak erabiltzen dira bektore bat irakurtzen edo idazten denean (m0–m1–m2–...); beraz, gatazkarik ez izateko, honako hau bete behar da:

mtmk ≥

Memoria-modulu bat berriz erabili behar denerako mk ziklo igaro direnez, libre izango da beti.

▪ 24 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Kasu orokorrerako, pausoa s > 1, memoria-eragiketa batek zenbat memoria-modulu erabiliko dituen kalkulatu behar da. Esaterako, aurreko A bektoreko adibidean, s = 4 denean, memoria-modulu bakar bat erabiltzen da, beti bera (m0). Erraz frogatu daiteke hau dela memoria-eragiketa batean erabiltzen den memoria-moduluen kopurua:

),( smkZKHmk

(ZKH = zatitzaile komunetan handiena)

Beraz, eta aurrekoa orokortuz, memoria-agindu batek ez du memoria-moduluekin arazorik izango, baldin eta erabiliko duen modulu kopurua atzipen-denbora (ziklotan) baino handiagoa edo berdina bada:

mtsmkZKHmk

≥),(

Memoria-modulu guztiak erabiltzea da egokiena gatazkak minimizatzeko, eta horretarako ZKH(mk, s) = 1 izan behar du, hots, mk eta s parametroek zenbaki lehenak izan behar dute elkarrekiko. Eskuarki, mk 2ren berretura da, hau da, 2i (8, 16, 32, 64...). Kasu horietarako, eta s = 1 denean gatazkarik ez badago, ez da arazorik sortuko s zenbaki bakoitia denean (1, 3, 5...). Hala ere, arazoak izan daitezke s bikoitia denean.

Badago kasu hobezin bat. Memoriako modulu kopurua, mk, zenbaki lehena bada, edozein s lehena izango da berarekiko (haren multiploak izan ezik). Esaterako, mk = 5 bada, ez da arazorik izango s = 1, 2, 3, 4, 6, 7, 8... denean. Hala ere, memoriako modulu kopurua zenbaki lehena bada, 17 esaterako, hitz (helbide) bati dagokion modulua eta modulu horren barneko helbidea kalkulatzea (memoriako kontrolagailuak egin behar ditu kalkulu horiek, atzipen bati ekiteko) asko zailtzen dira, zatiketa bat egin behar delako zatidura eta hondarra lortzeko (mk = 2i bada, pisu txikieneko i bitek modulua adierazten dute, eta gainerakoek modulu barneko helbidea). Zatiketa horrek behar duen denbora dela eta, irtenbide hori ez da erabiltzen.

Oro har, oso balio desberdinak izan ditzake s-k bektoreak prozesatzen direnean. Esaterako, matrizeak prozesatzen direnean, hainbat bektore defini daitezke: errenkadak, zutabeak, diagonal nagusia, diagonal txikia... Bi matrize biderkatzeko, adibidez, errenkadak eta zutabeak erabili behar dira. Zenbait kasutan, eta bektore horien pausoak egokienak izan daitezen, matrizeak ez dira memorian modu trinkoan gordetzen (hitz guztiak bata

1.3. EGITURAZKO DEPENDENTZIAK ▪ 25 ▪

bestearen atzetik), eta hainbat posizio hutsik uzten dira osagaien artean (padding).

Teknika hori zertan datzan ikusteko, analiza dezagun adibide soil bat: 4 modulutan tartekatutako memoria-sistema bat, eta 4×4-ko matrize bat. Matrize horren errenkadak zein zutabeak erabili behar ditugu (ikus beheko taulak). Ageri denez, errenkadek (s = 1) ez dute arazorik sortzen, osagaiak memoria-modulu desberdinetan baitaude, baina arazoak ditugu edozein zutabe (s = 4) eskuratzeko. Errenkadak zein zutabeak arazorik gabe atzitu ahal izateko, memoria-posizio batzuk hutsik utzi behar dira matrizearen osagaien artean (irudian aukera bat ageri da). Orain, s = 5 behar da zutabeak eskuratzeko, eta horrela ez dago arazorik, zutabeen osagaiak modulu desberdinetan geratu baitira. Hala ere, lehen ez zegoen arazorik, esaterako, diagonal nagusia zein txikia irakurtzeko, eta orain bai6.

m0 m1 m2 m3 m0 m1 m2 m3 A00 A01 A02 A03 A00 A01 A02 A03 A10 A11 A12 A13 → - A10 A11 A12 A20 A21 A22 A23 A13 - A20 A21 A30 A31 A32 A33 A22 A23 - A30 A31 A32 A33 -

se = 1 gatazkarik ez se = 1 gatazkarik ez sz = 4 gatazkak (denak m0n) sz = 5 gatazkarik ez sD = 5 gatazkarik ez sD = 6 gatazkak sd = 3 gatazkarik ez sd = 4 gatazkak

1.3.2.2. Memoria-eragiketa bat baino gehiago

Ikusi dugunez, LV edo SV agindu bat exekutatzen denean, arazoak izan daitezke memoria-moduluak atzitzean. Gauza bera gertatzen da memoriako agindu bat baino gehiago batera exekutatzen ari direnean. Nahiz eta agindu bakoitzak bere buruarekin arazorik izan ez (esaterako, memoriako modulu kopurua behar adinakoa delako), litekeena da aginduen arteko kolisioak izatea: agindu bat erabiltzen ari den memoria-modulu bera erabili behar du beste batek, une berean.

Azter dezagun arazoa adibide baten bidez. Demagun memoria 8 modulutan tartekatuta dagoela eta memoriaren latentzia 3 ziklo dela (aurreko 6 Lehen aipatu dugun moduan, onena mk zenbaki lehena izatea da. Esaterako, mk = 5 bada, matrizeko

errenkadak, zutabeak eta bi diagonalak gatazkarik gabe atzi daitezke, tartean hutsuneak utzita (ariketa gisa uzten dugu hori frogatzea).

▪ 26 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

adibideetako segmentazio-eskema bera). Ez dago arazorik memoriako busekin, eta aginduak kateatu egin daitezke. A bektorearen lehen osagaia memoriako m0 moduluan dago eta bektorearen pausoa s = 1 da.

bi bus / kateaketa A = A + 1 Ex. has. UF lat. 1. dat. N. dat.

LV V1,A(R1) 3 3 6+1 6+N

ADDVI V2,V1,#1 [7] 2 9+1 9+N

SV A(R1),V2 [10]

Lehen ikusi dugunez, SV agindua 10 zikloan kateatu daiteke; hau da, prest dago memorian idazteko. Baina, nola dago memoria une horretan: libre, okupaturik? Irudiko exekuzio-eskeman ageri da memoria-moduluak nola ari diren erabiltzen. LV aginduak 4. zikloan hasi du irakurketa, m0 moduluan. A bektorearen pausoa s = 1 denez, m0 moduluaren ondoren, m1, m2, ..., m7 moduluak erabiliko dira, eta berriro m0, m1, m2... Latentzia 3 ziklo izanik, aginduak ez dauka arazorik bere buruarekin (mk ≥ tm).

t (zikloak) mem. 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

m0 M M M - M M M m m m

m1 M M M - - M M M m m m

m2 M M M M M M

m3 M M M M M M

m4 M M M M M M

m5 M M M M M M

m6 M M M M M

m7 M M M M

SV agindua 10 zikloan kateatu daiteke, 11 zikloan memorian hasteko, m0 moduluan (bektore bera, A, gorde behar da). Nola dago une horretan memoria-modulu hori, libre ala okupatuta? LV agindua exekuzioan dago, eta okupatuta mantenduko du hainbat modulu. Modulu horiek zein diren jakiteko, kalkulatu egin behar dugu zein modulutan hasi behar duen atzipena LV aginduak ziklo horretan. Horretarako, nahikoa da zenbat ziklo daraman lanean eta nondik abiatu den jakitea. Adibide honetan, denbora hori 10 – 3 = 7 ziklo da, eta m0 modulutik abiatu denez gero (eta s = 1 denez), m7 moduluan hastear egongo da 11 zikloan (ikus aurreko taula). Beraz, modulu hori ez da libre egongo.

1.3. EGITURAZKO DEPENDENTZIAK ▪ 27 ▪

Baina hori ez da ziklo horretan erabil ez daitekeen modulu bakarra. Izan ere, aurreko zikloetan hasitako atzipen batzuk oraindik bukatu gabe daude. Memoriaren latentzia tm izanik, atzetik tm–1 modulu mantentzen dira oraindik okupatuta. Adibidean tm = 3 denez, bi modulu mantentzen dira okupatuta atzetik, m6a eta m5a, hain zuzen ere.

Argudio bera erabiliz, aurretik beste tm–1 modulu "erreserbatu" behar dira okupatu gabe, LV aginduaren irakurketak arazorik gabe jarraitu ahal izateko; adibidean, m0 eta m1 moduluak (bestela, LV aginduak topo egingo luke SV aginduarekin hurrengo zikloan!).

Hau da, adibide honetan, 11 zikloan, <m5 – m6 – m7 – m0 – m1> moduluak "okupatuta edo erreserbatuta" daude. Une horretan horietako modulu bat beste agindu batek erabili behar badu, itxaron egin beharko du modulua askatu arte. Zoritxarrez, SV aginduak m0 modulua erabili nahi du, eta itxaron egin beharko du. Zenbat ziklo? Erabili behar den moduluak modulu okupatuen zerrendan duen posizio adina ziklo. Adibidean, 4 ziklo itxaron behar da; izan ere, 11 zikloan, m5–...–m1 moduluak daude okupatuta; hurrengo zikloan, m6–...–m2; hurrengoan, m7–...–m3, eta hurrengoan, m0–...–m4. Azkenik, 15 zikloan, m0 modulua libre geratuko da, eta SV aginduak hasi ahal izango du A bektorea idazten.

Oro har, j eta k memoria-aginduen arteko gatazkak analizatzeko, hau egin behar da:

a. Kalkulatu j aginduak zein modulutan hasi behar duen atzipena, k aginduak memoria lehen aldiz erabili nahi duenean (nahikoa da aurreko aginduak zenbat ziklo daraman memorian eta zein modulutik abiatu zen jakitea):

(hzk – hzj) + hasiera-moduluaj (hz = memoria-eragiketako hasiera-zikloa)

b. Gehitu atzean eta aurrean tm–1 modulu gehiago, tm memoriaren latentzia izanik, une horretan ezin erabil daitezkeen memoria-moduluen zerrenda osatzeko.

< tm–1 modulu | (hzk – hzj) + hasiera-moduluaj | tm–1 modulu >

Eragiketa guztiak modulu mk egin behar dira, non mk memoriako modulu kopurua baita.

c. k aginduak erabili behar duen lehenengo memoria-modulua okupatuta badago, kalkulatu itxarote-denbora, modulu horrek aurreko zerrendan duen posizioa hain zuzen ere, eta gehitu denbora hori hasiera-denborari.

▪ 28 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Prozedura hori aise orokortu daiteke s pausoko atzipenetarako, baldin eta analizatzen ari diren memoria-aginduen pausoak berdinak badira. Hain zuzen, ziklo bakoitzean s modulu aurreratzen denez, batetik, (hk – hj) × s + has-modj kalkulatu behar da, eta, ondoren, gainerako tm–1 moduluak s-ka gehitu behar dira. Bestalde, pauso desberdineko bi memoria-eragiketen arteko gatazken analisia konplexuagoa da eta, eskuarki, lehenengoa bukatu arte itxaron egin beharko da bigarrenari ekin baino lehen.

Berregin dezagun aurreko adibidea irizpide horiek kontuan hartuz. Taulan ageri denez, SV aginduak 10 zikloan egin nahi du kateaketa. LV agindua dela eta, ezin izango ditu memoria-modulu hauek erabili: (10 – 3) + 0 = 7 modulua, aurreko biak, 6 eta 5, eta hurrengo biak, 0 eta 1. m0 modulua erabili behar duenez, 4 ziklo itxaron beharko da. Une horretan, 14 zikloan, kateaketa ezin da dagoneko egin zuzenean batugailutik, eta, aukeran, erregistrotik egingo da (hori posible ez balitz, itxaron egin beharko genuke batuketa bukatu arte).

bi bus / kateaketa

A = A + 1 Ex. has. Mod. okup. Itxar. UF lat. 1. dat. N. dat.

LV V1,A(R1) 3 - - 3 6+1 6+N

ADDVI V2,V1,#1 [7] - - 2 9+1 9+N

SV A(R1),V2 [10] ?? 5 / 6 –7– 0 / 1 +4 3 17+1 17+N

Memoria erabili ahal izateko itxaron behar den ziklo kopurua

kalkulatzeko, exekutatzen ari diren memoria-agindu guztiekin egin behar da analisia, bakoitzak tm modulu okupatuko baitu, une oro, memorian.

Bidenabar, eta aurrekoaren ondorio gisa, ezin dira onartu (mk div tm) memoria-eragiketa baino gehiago aldi berean, horiekin memoria-modulu guztiak okupatzen direlako. Esaterako, aurreko kasuan (mk = 8 eta tm = 3) ezin dira prozesatu batera 8 div 3 = 2 memoria-agindu baino gehiago; sobera legoke, beraz, balizko hirugarren memoria-busa.

Bi ondorio atera daitezke aurreko paragrafoetatik. Batetik, bektore-konputagailu baten memoria-sistemaren tartekatze-maila, modulu kopurua, handia izango da datu-jarioari eutsi ahal izateko; eta, bestetik, garrantzitsua da bektoreak memorian egoki kokatzea, atzipen-gatazkak ekiditeko, eta, horretarako, funtsezkoa izango da konpiladorearen laguntza. Gatazkak gainditzea lortu ezean, ezin izango dugu datu bat zikloko eskuratu eta, beraz, ezingo da modelatu exekuzio-denbora orain arte egin dugun moduan: esaterako, 1. datua, 5+1 zikloan; N. datua, 5+N zikloan.

1.3. EGITURAZKO DEPENDENTZIAK ▪ 29 ▪

1.3.3. Bektore-erregistroen luzera (strip mining)

Baliabide-gatazkekin jarraituz, analiza dezagun orain bektore-erregistroen erabilera. Erregistro eskalarrekin egiten den modu berean, bektore-erregistroak erabiltzen dira bektoreak prozesadorean bertan mantentzeko eta haiekin eragiketak egiteko. Erregistro horiek erabiltzean, hainbat muga izango dugu. Batetik, kopurua, ez baitugu bektore-erregistro asko izango (ez, behintzat, erregistro eskalar adina). Bestetik, erregistroak irakurtzeko eta idazteko busak. Esaterako, ADDV V3,V2,V1 aginduarekin N ziklo mantenduko dira okupatuta bi irakurketa-bus eta idazketa-bus bat. Beraz, bus gehiago ez badago, ezin izango dugu antzeko beste agindu bat exekutatu aurrekoa bukatu arte.

Hirugarren muga tamainari dagokio. Bektoreak edozein tamainatakoa izan badaitezke ere, erregistroak tamaina mugatukoak izango dira; ohikoak dira, esaterako, 64 edo 128 hitzekoak. Beraz, bektore-agindu bakar batekin ezin dira prozesatu bektore-erregistroak baino luzeagoak diren bektoreak. Ez dago beste biderik: bektore luzeak prozesatzeko, begizta bat antolatu beharko dugu, bektore hori Lmax tamainako hainbat zatitan prozesatzeko. Prozesu horri strip mining deritzo.

Memoriatik irakurri edo memorian idatzi behar diren bektoreen luzera erregistro berezi batean adierazi behar da, VL (vector length) erregistroan. VL ≤ Lmax bada, erregistro horretan adierazitako osagai kopurua prozesatuko da; baina VL > Lmax bada, Lmax osagai bakarrik prozesatuko dira. Esate baterako:

do i = 0, N-1 A(i) = A(i) + 1 → enddo

MOVI VS,#1 MOVI R1,#N segi: MOV VL,R1

LV V1,A(R2) ADDVI V2,V1,#1 SV A(R2),V2

ADDI R2,R2,#Lmax (bider hitz-tam.) SUBI R1,R1,#Lmax BGTZ R1,segi

Bektoreen luzeraren arabera, begiztaren azken iterazioa osagai kopuru txikiagorekin egingo da. Adibidez, Lmax = 128 eta N = 1.000 badira, azken iterazioan 104 osagai baino ez dira prozesatuko (7 × 128 + 104 = 1.000).

Jakina, exekuzio-denboran (kalkulu-abiaduran, beraz) nabarituko dugu begizta horren eragina. Demagun bektore-eragiketa batek behar duen

▪ 30 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

denbora TB = th + tb N ziklo gisa adieraz daitekeela, lehen ikusi dugun moduan. Erregistroen tamaina kontuan hartuta, begiztaren exekuzio-denbora honelaxe adierazi beharko da:

NtttL

NT bbeghmax

B ++

= )(

N/Lmax-ek begizta eskalarreko iterazio kopurua adierazten du, eta tbeg iterazio horien kontrolerako behar den denbora da (adi! hasierako batugaia ere N-ren araberakoa da orain).

Strip mining prozesua ia ezinbestekoa da bektoreak prozesatu behar direnean; izan ere, kasu gehienetan ez dugu jakingo prozesatu behar diren bektoreen luzera, parametro hori programa exekutatzean erabakiko baita. Beraz, kasurik sinpleenean ere, hau da, bektoreen luzera erregistroen tamaina baino txikiagoa denean, behin "ordaindu" beharko dugu begiztaren kontrolari dagokion denbora, tbeg.

Ikus dezagun adibide bat: N = 500 TB = 30 + 3N → TB = 30 + 1.500 = 1.530 ziklo (ideala) 3,06 ziklo/osagai

baina Lmax = 64 tbeg = 10 ziklo → TB = 8 × (30+10) + 1.500 = 1.820 ziklo 3,64 ziklo/osagai (+ % 19)

1.4. BEKTORE KONPUTAGAILUEN KALKULU

ABIADURA

Kalkulu-abiadura handiko exekuzio-eredu berria definitu dugu (arkitektura eta makina-lengoaia), bektoreak (begiztak) modu eraginkorrean prozesatzeko. Azter ditzagun, bada, bektore-konputagailuen exekuzio-abiadura definitzen duten parametro nagusiak.

1.4.1. Kalkulu-abiadura bektoreen luzeraren arabera

1.4.1.1. R∞ eta N1/2

Lehenik eta behin, gogora dezagun berriro nola adieraz daitekeen begizten exekuzio-denbora prozesadore eskalarretan eta bektore-prozesadoreetan:

1.4. BEKTORE KONPUTAGAILUEN KALKULU ABIADURA ▪ 31 ▪

▪ eskalar moduan TE = te N te = iterazio bat exekutatzeko denbora ▪ bektore gisa7

TB = th + tb N th = hasiera-denbora tb = osagai bat prozesatzeko denbora

Exekuzio-denborak ziklotan edo (nano)segundotan (erloju-periodoaz biderkatuta) adieraz daitezke. Irudian, bektore-eragiketa baten exekuzio-denbora ageri da bektoreen luzeraren arabera, lerro zuzen bat, alegia.

Hortik abiatuta, honela definitzen da bektore-programa baten kalkulu-

abiadura edo errendimendua (performance), alegia, zikloko (edo segundoko) prozesatu den osagai kopurua:

NttN

TNR

bhBB +

==

Kalkulu-abiadura Mflop/s-tan eman ohi da (Mega FLoat OPeration / s), hau da, segundo batean exekutatu den koma higikorreko eragiketa kopurua. Horretarako, bektoreekin egindako eragiketa kopurua (ErKop) kontuan hartu behar dugu8, koma higikorreko N × ErKop eragiketa egin baitira guztira.

Bestalde, segundotan eman behar da TB, exekuzio-denbora; ziklotan badago (hala dago, esaterako, egin ditugun aurreko adibide guztietan), erloju-periodoaz biderkatu behar da segundotara pasatzeko; denbora zatitzailean dagoenez gero, gauza bera da maiztasunaz biderkatzea (F = 1/T). Beraz, honela lortuko dugu kalkulu-abiadura: 7 Bektore-erregistroen tamaina kontuan hartu gabe. 8 Kalkulu-abiadura dela eta, ez da gauza bera batuketa bakar bat egitea denbora jakin batean, edo bi

batuketa eta biderketa bat.

0 5

100 150 200 250 300

0 25 50 75 100 125 150 N (bektoreen luzera)

th

malda = tb

TB = 30 + 2N N1/2

2th

TB

▪ 32 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

FErKopNtt

NRbh

B ××+

= Mflop/s (th, tb ziklotan, F MHz-etan)

Analiza dezagun grafikoki aurreko adierazpena.

Irudian ageri denez, R funtzioak asintota bat du N ∞-rantz doanean. Hau da, bektoreak oso handiak izanda ere, lor daitekeen kalkulu-abiadura mugatua da. Balio maximo horri R∞ deritzo.

FErKopt

RRb

BN ××== ∞→∞1lim

Hainbat kasutan, exekuzioaren eraginkortasuna ere adierazi ohi da, hau

da, abiadura maximoaren frakzioa:

eraginkortasuna = R / R∞ [0 – 1] tartean

Kalkulu-abiadura maximoa ezin da, definizioz, lortu. Hori dela eta, egokia da, R∞-rekin batera, beste parametro bat erabiltzea: N1/2, bektoreen luzera minimoa kalkulu-abiadura maximoaren erdia lortu ahal izateko. Definizio horren arabera, R(N1/2) = R∞/2; beraz,

N1/2 / (th + tb × N1/2) = 1/tb × 1/2 → N1/2 = th / tb (goiko zenbaki osoa)

N1/2 oso handia bada, seguru asko errendimendu maximotik nahiko urrun ibiliko gara programa errealetan; txikia bada, aldiz, ez da beharrezkoa izango oso bektore luzeak prozesatzea kalkulu-abiadura handia erdiesteko9.

N1/2 definitu den bezala, beste edozein balio ere defini daiteke: N3/4, N1/4... bektoreen tamaina minimoa abiadura maximoaren frakzio jakin bat lortzeko. 9 Nahi izanez gero, exekuzio-denbora eta kalkulu-abiadura N1/2 eta R∞ parametroen funtzio gisa eman

daitezke, honela: TB = (N + N1/2) / R∞ RB = R∞ × (1 / (1 + N1/2/N))

N (osagai kopurua)

R∞

R (

kalk

ulu-

abia

dura

)

R∞/2

N1/2

1.4. BEKTORE KONPUTAGAILUEN KALKULU ABIADURA ▪ 33 ▪

Kalkulu-abiadurako bi parametro nagusiak esperimentu sinple baten bidez lor daitezke: exekutatu programa bektoreen hainbat luzeratarako (N), neurtu exekuzio-denborak, eta marraztu TB(N) funtzioa. Zuzen bat izango da, exekuzio-denbora linealki hazten baita N-rekin. Zuzen horren jatorriko ordenatuak th adierazten du, eta malda tb da. Beraz, R∞, kalkulu-abiadura maximoa, zuzen horren maldaren alderantzizkoa izango da. Era berean, N1/2 kalkulatzeko, TB = 2 th exekuzio-denbora behar duen bektore-luzera lortu behar da (N = N1/2 = th / tb denean, TB = th + (th / tb) × tb = 2 th da).

Exekutatzen den programaren araberakoa da R∞ parametroa. Hala ere, erraz kalkula daiteke bektore-konputagailu baten balizko abiadura gorena (peak performance) edozein programatarako. Jakina, balio gorena tb = 1 denean eta unitate funtzional guztiak batera erabiltzen direnean (ErKop = unitate funtzionalen kopurua) lortuko dugu. Esaterako, 6 unitate funtzional eta F = 500 MHz dituen bektore-konputagailu batek lor dezakeen kalkulu-abiadura maximoa 6 × 500 = 3.000 Mflop/s = 3 Gflop/s da. Baina, ez nahastu gero! Balio hori guztiz teorikoa da, eta oso kasu berezietan baino ez da lortuko, oro har tb > 1 izango delako eta unitate funtzional guztiak batera erabiliko ez ditugulako.

1.4.1.2. Azelerazio-faktorea (speed-up)

Bektore-konputagailu baten kalkulu-abiadura adierazteko beste bide bat, konparazio bat erabiltzea da: zenbat bider azkarragoa da programaren exekuzioa modu bektorialean modu eskalarrean baino? Balio horri azelerazio-faktorea (speed-up) deritzo, eta honela kalkulatzen da:

NttNt

TTK

bh

e

B

EB +

==

KB funtzioaren portaera R funtzioarena bezalakoa da, eta balio maximoa lortzen du N infiniturantz doanean:

b

eBN t

tKK == ∞→∞ lim

K∞ parametroak honako hau adierazten du: zenbat aldiz gehiago kostatzen den bektore-osagai bat eskalarki prozesatzea bektorialki prozesatzea baino, bektoreak oso luzeak direnean. Lehenik eta behin, K∞ handia izatea interesatzen zaigu, horrek esan nahi baitu bektore-prozesadorea oso azkarra dela (eskalarrarekin alderatuta). Hala ere, laster ikusiko dugunez, parametro gehiago kontuan hartu behar ditugu, kode bektorialarekin batera kode eskalarra ere exekutatu behar baita.

▪ 34 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

1.4.1.3. Nb

R∞ eta N1/2 dira bektore-konputagailuetan gehien erabiltzen diren "kalitate-parametroak", nahiz eta, zenbait kasutan, beste parametro batzuk ere aipatzen diren. Esaterako, exekuzio-denbora txikiagoak lortzen al dira beti bektore-prozesadorean prozesadore eskalarrean baino? Kalkula dezagun Nb parametroa, TE = TB egiten duen bektoreen luzera:

12/1

−=

−=→+=

∞KN

tttNNttNt

be

hbbbhbe

Beraz, prozesatu behar diren bektoreek Nb osagai baino gutxiago badituzte (hau da, oso txikiak badira, N1/2 eta K∞-ren arabera) ez du merezi bektore-prozesadorea erabiltzea, azkarrago exekutatuko baita prozesadore eskalarrean.

1.4.2. Kalkulu eskalarraren eragina: Amdahl-en legea

Bektoreak prozesatzen dituzten programak dira egokienak bektore-prozesadoreetan exekutatzeko. Baina, zoritxarrez, bektoreez gain, kode eskalarra ere exekutatu behar da programa guztietan; izan ere, kalkulu intentsiboko programa "interesgarri" gutxi idatz daiteke bakarrik bektore-kodea erabiliz. Beraz, programa jakin baten kalkulu-abiadura ondo neurtzeko, kode eskalarrak behar duen denbora ere kontuan hartu behar da.

Izan bedi f bektorialki exekuta daitekeen programaren frakzioa, eta 1 – f eskalarki exekutatu behar dena. Programaren zati bat bektorialki exekutatuko da, eta haren exekuzio-denbora azaldu berri dugun ereduaren arabera izango da, baina beste zatiaren exekuzio-denbora eredu eskalarraren araberakoa izango da; beraz, honela adierazi behar da programa osoaren exekuzio-denbora:

TBE = f TB + (1 – f) TE

Beraz, prozesadore eskalarrarekin alderatuta, hau izango da benetan lortuko den azelerazio-faktorea:

Aurreko adierazpidea Amdahl-en legea da. f = 0 denean —kode guztia eskalarra, beraz—, azelerazio-faktorea 1 da, noski. Eta f = 1 denean —kode guztia bektore-kodea—, azelerazio-faktorea KB da, lehen definitu dugunez.

)1(/)1(/

)1( −−=

−+=

−+==

BB

B

BE

BE

EB

E

BE

EBE KfK

KTTff

TTTffT

TTTK

1.4. BEKTORE KONPUTAGAILUEN KALKULU ABIADURA ▪ 35 ▪

Ikus dezagun grafikoki azelerazio-faktorearen portaera f-ren arabera.

Grafikoan ageri denez, azelerazio-faktore esanguratsua erdiesteko, bektorizazio-faktoreak handia behar du izan. Esaterako, KB = 16 kasurako, exekuzioa 8 aldiz azkartzeko, f > 0,93 izan behar dugu! Edo f = 0,65 bada, esaterako, azelerazio-faktorea ez da inoiz 3 baino handiagoa izango, nahiz eta KB infinitua izan. Izan ere, limitean, KB handia denean, azelerazio-faktorea 1 / (1–f) da.

Programak bektorizatzea konpiladorearen ardura da (programatzailearen laguntzarekin). Grafikoko X ardatzean, konpiladoreek lortu ohi dituzten bektorizazio-faktoreak (batez beste) ageri dira. Eskuarki, [0,55 - 0,75] tartean kokatzen da f. Eta garbi azaltzen denez, ehuneko horiekin azelerazio-faktorea oso mugatua izango da, KB handia izan arren. Beraz, konpilazio-prozesuaren eraginkortasuna oso garrantzitsua da kalkulu-abiadura handiak lortuko badira.

N1/2 parametroa kalkulatu dugun bezala, hemen ere antzeko parametro bat kalkula daiteke: f1/2, behar den bektorizazio-faktorea gutxienez abiadura maximoaren erdia lortzeko (KB/2).

111

)1(2 2/12/1 −

−=→−−

=BBB

BBK

fKfK

KK

Oro har, beraz, programa jakin batekin benetan lortuko den kalkulu-abiadura adierazteko, kode eskalarra zein bektoriala kontuan hartu behar dira:

NtKfNttfN

NtfNttfN

TffTN

TNR

bbhebhEBBEBE

∞−++=

−++=

−+==

)1()()1()()1(

KB = ∞ 16 8 4 2

▪ 36 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Lehen bezala, Mflop/s-tan jartzeko, koma higikorreko eragiketa kopuruaz biderkatu behar da, eta, denbora ziklotan badago, erloju-maiztasunaz.

Zenbait testutan, aurreko adierazpena beste modu honetan ematen da:

RN,f = R∞ × εN × εf non εN = 1 / [1 + N1/2/N] eta εf = 1 / [f + (1–f) K∞ × εN]

hau da, badago errendimendu maximo bat R∞,1 bektoreen luzera infinitua eta bektorizazio-faktorea 1 denean, eta gero bi muga, bata bektoreen luzera N delako, eta bestea bektorizazio-faktorea f delako. Jar dezagun adibide bat. Bektore-konputagailu batek honako parametro hauek ditu: R∞ = 800 Mflop/s, N1/2 = 60, K∞ = 10, f = 0,8 eta N = 128. Beraz, N infinitu eta f = 1 izango balira, 800 Mflop/s lortuko genituzke. N = 128 denez, lehenengo muga εN = 0,68 da. Bigarrena, f = 0,8 delako (eta N = 128), beste hau da: εf = 0,46. Ondorioz, hau izango da lortuko den kalkulu-abiadura: 800 × 0,68 × 0,46 = 252 Mflop/s.

Kode eskalarrak sistema osoaren errendimenduan duen eragina berriro

azpimarratzeko, azter dezagun adibide hau. Bektore-konputagailu jakin batean, bi hobekuntza egin dira. Lehenbizikoan, bektore-prozesadorearen abiadura bikoiztu egin da: tb erdira jaitsi da. Bigarrenean, berriz, prozesadore eskalarraren abiadura bikoiztu egin da: te erdira jaitsi da. Grafikoan, jatorrizko konputagailuarekin eta bi hobekuntzekin lortuko liratekeen azelerazio-faktoreak (normalizatuta) ageri dira bektorizazio-faktorearen arabera.

Bi muturretako portaera argia da. Programak erabat bektoriza

daitezkeenean (f = 1 denean), azelerazio-faktorea hobea da KB bikoiztuta duen konputagailuan (makina berria bi aldiz azkarragoa da). Aldiz, programa

0 2 4 6 8

10 12

14

16

0 0.2 0.4 0.6 0.8 1

Aze

lera

zio-

fakt

orea

(nor

mal

izat

ua)

f (bektorizazio-faktorea)

Amdahl-en legea

CRAY X-MP tb = 10 ns te = 66,6ns

tb = 5 ns te = 66,6 ns

tb = 10 ns te = 33,3 ns

1.5. BEKTORE KODEA SORTZEKO TEKNIKA NAGUSIAK ▪ 37 ▪

bektorizatu ezin bada (f = 0, dena kode eskalarra), emaitza hobeak lortzen dira prozesadore eskalarra hobetu den konputagailuan.

Eta kasu orokorrean? Erantzuna f-ren araberako da. Baina, kontuz! bektorizazio-faktorea [0,6 – 0,8] tartean geratzen bada, ez du merezi KB oso handia izatea, eta egokiagoa da prozesadore eskalarraren abiadura handitzea. Beraz, exekutatu behar diren programak ehuneko handietan bektorizatu ezin badira, ez zaigu gehiegi interesatzen KB handiko bektore-konputagailuak erabiltzea, ez baititugu haien abantailak aprobetxatuko.

1.5. BEKTORE KODEA SORTZEKO TEKNIKA

NAGUSIAK

Bektore-konputagailuek bektore-kodea exekutatzen dute; baina, oro har, programen zati bat bakarrik idatz daiteke bektore-kode gisa. Nori dagokio zati hori identifikatzea eta bektore-kode gisa idaztea, programatzaileari edo konpiladoreari? Beti bezala, egokiena hau da: programatzailearen lana makinaren ezaugarriekiko independentea izatea; hala, programatzaileak goi-mailako lengoaiaren bat erabiliko du programak sortzeko, eta, gero, konpiladore batek itzuliko ditu programa horiek makina-kodera, jakineko konputagailuaren ezaugarriak kontuan hartuz. Zorionez, badaude bektore-kodea automatikoki sortzen duten bektore-konpiladore eraginkorrak. Bektore-konpiladoreak analizatuko ditu begizten datu-dependentziak, hark erabakiko du bektore gisa exekuta daitezkeen eta nola egin daitekeen, eta dagokien kodea sortuko du. Dena dela, programatzailearen laguntza ezinbestekoa da maiz bektorizazio-faktore handiak eskuratzeko, zaila baita, hainbat kasutan, goi-mailako lengoaia batetik bektore-kodera automatikoki itzultzea. Hori dela eta, zenbait programazio-lengoaiak (Fortran-ek, esaterako) egitura bereziak dituzte bektore-eragiketak adierazteko eta konpiladoreari laguntzeko.

Egiaztatu dugunez, biziki garrantzitsua da programaren frakzio handi bat bektore-eragiketa gisa adieraztea. Hori egin ezean, lortuko dugun kalkulu-abiadura ez da oso handia izango. Hurrengo ataletan, bektore-konpiladoreek kodea bektorizatzeko erabiltzen dituzten estrategia nagusiak aztertuko ditugu. Analisi eta estrategia berak erabiliko ditugu, geroago, begiztak P prozesadoreren artean exekutatu ahal izateko.

▪ 38 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

1.5.1. Aginduen arteko datu-dependentziak

Dagoeneko aipatu dugunez, bektorizatzea, besteak beste, aginduen hurrenkeraren aldaketa berezi bat da. Baina aginduak ezin dira berrordenatu haien arteko dependentziak kontuan hartu gabe. Gogoratu: bi aginduk memoria-posizio bera erabiltzen badute eragigaiak irakurtzeko edo emaitzak uzteko, datu-dependentzia bat dago haien artean.

Bi dependentzia mota bereizi ohi dira: benetako dependentziak, eta izen-dependentziak; azken horiek ere, bi motakoak izan daitezke: antidependentziak eta irteera-dependentziak.

• Benetako dependentziak (RAW, read-after-write)

1: A = B + C 2: D = A

Dependentzia dago 1 eta 2 aginduen artean, bigarrenak erabiltzen duen eragigaia —A— lehenengoak sortuko duena baita. Grafo batean, dependentzia-grafoan, adierazi ohi dira datu-dependentziak; dependentzia mota hori aginduen arteko gezi baten bidez adierazten da. Geziak hurrenkera adierazten du (zer exekutatu behar den lehenago eta zer geroago). Adibide horretan, 2 aginduko irakurketa 1 aginduko idazketaren ondoren egin behar da.

RAW dependentziak ezin dira ekidin, programatu nahi den algoritmoari baitagozkio (aginduen arteko datu-jarioa zehazten dute). Zenbait kasutan, zirkuitulaburren bidez konponduko dira; bestela, itxaron egin beharko da aurreko eragiketa bukatu arte bigarrenari ekiteko.

• Antidependentziak (WAR, write-after-read)

1: A = B + C 2: B = D

Antidependentzia dago 1 eta 2 aginduen artean, lehenengoak erabili

behar duen eragigai bat —B— bigarrenak aldatuko duelako. Marra bat

1

2

A

1

2

B

1.5. BEKTORE KODEA SORTZEKO TEKNIKA NAGUSIAK ▪ 39 ▪

duen gezi batez adieraziko ditugu antidependentziak dependentzia-grafoan. Adibideko grafoan, geziak honako hau adierazten du: 2 aginduak itxaron egin behar du B aldagaia idazteko, 1 agindua aldagai hori irakurri arte.

Antidependentziak ez dira benetako dependentziak bezain "gogorrak" (ez dago datu-transferentziarik aginduen artean), eta bektore-kodean ordena-aldaketa txikiak eginez konpon daitezke.

• Irteera-dependentziak (WAW, write-after-write)

1: A = B + C 2: A = D

Irteera-dependentzia dago 1 eta 2 aginduen artean, biek aldagai bera —A— idatziko baitute. Grafoan, zirkulutxo bat duen gezi batez adieraziko dugu. Idazketen hurrenkera, noski, errespetatu egin behar da, grafoko geziak adierazten duen legez.

Irteera-dependentziak ere ez dira "gogorrak", eta, eskuarki, programaren idazkerari dagozkio; beraz, desagerraraz daitezke bektore-kodea egoki ordenatzen bada.

Ez ahaztu: dependentzia mota dena delarik ere, eragiketen hurrenkera jakin bat ezartzen du dependentziak; hots, zer egin behar den lehen eta zer gero.

Aurreko paragrafoetan, agindu soilen arteko dependentziak laburbildu ditugu. Baina, berez, begizta osoa ordezkatzen da bektore-kodearekin; hots, aginduen arteko dependentziak analizatzean, begiztaren edozein iteraziotan ager daitezkeela kontuan hartu behar dugu (bektoreen edozein osagaitan). Hori dela eta, lagungarria da dependentzia-grafoan dependentziaren "distantzia" ere adieraztea. Begizta baten aginduen arteko dependentziaren distantziak dependentzia hori zenbat iterazio geroago gertatuko den adierazten du.

Esaterako, dependentzia iterazio berean bada, distantzia 0 da; hurrengo iterazioan bada, distantzia 1 da, eta abar. Dimentsio bat baino gehiagoko bektoreetarako, distantzia-bektore bat erabiltzen da, osagai bat begiztaren dimentsio bakoitzeko. Adibidez:

1

2

A

▪ 40 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

do i = 2, N-2 1: A(i) = B(i) + 2 2: C(i) = A(i-2) + A(i+1) enddo

do i = 2, N-1 do j = 1, N-2 1: A(i,j) = A(i,j-1) * 2 2: C(i,j) = A(i-2,j+1) + 1 enddo enddo

dependentzia-grafoa iterazio-espazioa

Iterazioen artean gertatzen bada, hau da, dependentziaren distantzia d > 0

bada, loop carried deritzo dependentziari. Programa jakin bat bektorizatu ahal izateko, aginduen arteko

dependentzien analisia egin behar da (ez ahaztu: behe-mailako aginduak desordenatu egin behar dira). Horretarako, aipatu dugun dependentzia-grafoa sortu behar da. Dependentzia-grafoan, begiztaren edozein iteraziotako aginduen arteko dependentziak adierazten dira. Dimentsio bat baino gehiagoko begizten kasuetan, lagungarria da beste grafo mota bat ere erabiltzea, iterazio-espazioa izeneko grafoa (ikus aurreko irudiak): dependentziak ez dira markatzen aginduen artean, iterazioen artean baizik. Hurrengo adibideetan, bi grafoak erabiliko ditugu.

1.5.2. Bektorizazioa

1.5.2.1. Dimentsio bakarreko bektoreak

Bektore-kodea sortzek teknika nagusiak azaldu baino lehen, azter ditzagun adibide batzuk10.

10 Bektore guztiak N (edo N×N) tamainakoak dira. A helbideak lehenengo osagaia, A0, erakusten du,

A+1-ek bigarrena, eta abar (makinaren helbideratze-unitatea eta aldagaien tamaina kontuan hartu gabe). Izen desberdineko bektoreek memoria-posizio desberdinak erabiltzen dituzte, hau da, ez dira teilakatzen (ez dago aliasing-ik). Era berean, helbideak adierazteko erabiltzen den erregistroaren hasierako edukia 0 da (adibideetan, R1).

A, 2

A, 1

i

i=0 i=1 i=2 …

1

2

A, 2 A, 1

1

2

A, (2, –1)

A, (0, 1) j

i A, (2, –1)

A, (0, 1)

1.5. BEKTORE KODEA SORTZEKO TEKNIKA NAGUSIAK ▪ 41 ▪

1.5.2.1.1. Lehen adibidea

do i = 0, N-1 A(i) = B(i) + C(i) enddo

Agindu/iterazioen artean batere dependentziarik ez dagoenez, ez daukagu inolako arazorik kodea bektorizatzeko eta honela idazteko:

MOVI VL,#N ; bektoreen luzera MOVI VS,#1 ; bektoreen pausoa (stride)

LV V1,B(R1) LV V2,C(R1) ADDV V3,V1,V2 SV A(R1),V3

Zenbait lengoaiatan, honela adierazten da eragiketa hori: A(0:N:1) = B(0:N:1) + C(0:N:1), non A(x:y:z)-k adierazten baitu: x, hasiera; y, osagai kopurua; eta z, pausoa.

Adi. Jatorrizko begizta eskalarra eta idatzi dugun bektore-kodea ez dira guztiz baliokideak. Izan ere, i aldagaia erabiltzen da begizta eskalarrean, begizta kontrolatzeko zein bektore-osagaiak adierazteko; beraz, begizta bukatzen denean, i aldagaian azken iterazioko balioa geratuko da. Ohikoa ez bada ere, litekeena da programa berean, gerorago, i aldagaiaren balio hori erabili behar izatea. Bektore-konpiladoreak sortu behar duen kodeak jatorrizko kodearekin bat etorri behar du, salbuespenik gabe. Beraz, nahiz eta bektore-kodean erabili behar ez den, azken iterazioko balioa utzi beharko da i aldagaian, N–1 kasu honetan. Gauza bera egin beharko da antzeko aldagai guztiekin. Sinplifikatzeko asmoz, adibideetan ez dugu eragiketa horiei dagokien kodea idatziko.

1.5.2.1.2. Bigarren adibidea

do i = 0, N-1 1: A(i) = B(i) + C(i) 2: D(i) = A(i) enddo

dependentzia-grafoa iterazio-espazioa

Bi grafoak egin ditugu: dependentzia-grafoa eta iterazio-espazioa. Datu-dependentzia bat dago begiztan, lehenengo agindutik bigarren agindura;

1

2

A, 0 A, 0

i

▪ 42 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

dependentzia iterazio berean gertatzen da, iterazio-espazioan ageri den bezala.

Zenbait testutan, honela adierazten da dependentzia hori: 1 δ= 2; = ikurrak dependentzia iterazio berean gertatzen dela adierazten du (bestela, < ikurra erabiltzen da).

Dependentzia horrek ez du arazorik sortzen, eta programa honela bektoriza daiteke (eskematikoki):

MOVI VL,#N MOVI VS,#1

(1) LV V1,B(R1) LV V2,C(R1) ADDV V3,V1,V2 SV A(R1),V3 ; A = B + C

(2) SV D(R1),V3 ; ez da A irakurri behar, V3n baitago

1.5.2.1.3. Hirugarren adibidea

do i = 1, N-1 1: A(i) = B(i) + C(i) 2: D(i) = A(i-1) enddo

1 δ< 2

Begizta horren dependentzia-grafoa aurrekoaren antzekoa da, baina orain iterazio-espazioan zehar banatzen dira dependentziak; izan ere, bigarren aginduan erabili behar dugu, i iterazioan, lehenengo aginduak i–1 iterazioan sortu duen osagaia: 1i → 2i+1.

Berriro ere, ez dago arazorik kodea bektorizatzeko, honela adibidez:

MOVI VL,#N-1 MOVI VS,#1

(1) LV V1,B+1(R1) LV V2,C+1(R1) ADDV V3,V1,V2 SV A+1(R1),V3 ; idatzi A1–AN-1 bektorea

(2) LV V4,A(R1) ; A0–AN-2 bektorea memoriatik irakurri SV D+1(R1),V4

Garbi dago: orain ezin da 1 aginduak sortutako bektorea 2 aginduan aprobetxatu, ez baitugu zehatz-mehatz bektore bera erabili behar, A0-AN-2

1

2

A, 1 A, 1

i

1.5. BEKTORE KODEA SORTZEKO TEKNIKA NAGUSIAK ▪ 43 ▪

bektorea baizik; beraz, lehenik idatzi egin behar da memorian A1-AN-1 bektorea, eta gero irakurri A0-AN-2 bektorea.

1.5.2.1.4. Laugarren adibidea

do i = 0, N-2 1: A(i) = B(i) + C(i) 2: D(i) = A(i+1) enddo Antidependentzia bat dago begizta horretan, bigarren agindutik

lehenengora: A bektorearen balio zaharrak irakurri behar dira 2 aginduan, ez 1 aginduak sortzen dituenak. Dagoen ordenan, begizta ezin da bektorizatu, ezin baita A(i) bektorea (osagai guztiak) idatzi lehenengo aginduan bigarren aginduan behar den A(i+1) bektorea irakurri baino lehen.

Geroxeago formalizatuko dugu kasu hori; nahikoa da esatea orain arazoa ordena-aldaketa batekin konpontzen dela, hemen ikusten den moduan:

MOVI VL,#N-1 MOVI VS,#1

(2) LV V1,A+1(R1) ; aurreratu 2 aginduaren irakurketa SV D(R1),V1

(1) LV V2,B(R1) LV V3,C(R1) ADDV V4,V2,V3 SV A(R1),V4 ; idatzi 1 aginduaren emaitza

Ikus daitekeenez, programako antidependentzia (eragiketen hurrenkera

jakin bat) errespetatu egin da bektore-kodean.

1.5.2.1.5. Bosgarren adibidea

do i = 1, N-1 1: A(i) = B(i-1) + 1 2: B(i) = A(i) enddo

Bektore-kodea sortzeko arazorik larriena ageri da begizta horretan:

aginduen arteko dependentziek ziklo bat osatzen dute dependentzia-grafoan.

1

2

A, 1

A, 1

i

1

2

A, 0 B, 1

A, 0

i

B, 1

▪ 44 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Lehenbiziko aginduak bigarrenak sortutako B bektorea (ia osagai guztiak) behar du, eta, beraz, ezin du eragigaia irakurri bigarren agindua bukatu arte; baina, era berean, bigarren aginduak ezin du irakurri A bektorea, lehenengo aginduak sortutako emaitzak behar dituelako. Ez dago arazoa konpontzeko modurik, eta begizta eskalarki exekutatu beharko da.

Dependentzia-zikloen adibide sinpleenak errekurrentziak ditugu, non dependentzia-zikloa agindu batek bere buruarekin osatzen duen:

do i = 3, N-1 1: A(i) = A(i-3) * 3 enddo

Iterazio bakoitzean, duela hiru iterazioko emaitza erabili behar da eragigai gisa. Argi eta garbi, eragiketa hori ezin da bektorizatu: nola irakurri agindu batekin bektore osoa —LV V1,A(R1)—, behar ditugun osagaiak oraindik sortzeke badaude?

1.5.2.2. Dimentsio anitzeko bektoreak

Aztertu ditugun aurreko adibide guztietan, dimentsio bakarreko bektoreak erabili ditugu. Baina nola bektorizatzen da, esaterako, matrize-eragiketa bat?

do i = 0, N-1 (bektore guztiak [N, M] tamainakoak) do j = 0, M-1 A(i,j) = B(i,j) + C(i,j) enddo enddo

Matrizeekin lan egiten denean, eskuarki bi bektore mota definitzen dira: errenkadak eta zutabeak. Begiztak berak zehazten du nola prozesatu nahi den matrizea, errenkadaka edo zutabeka, nahiz eta, hainbat kasutan, bi aukerak zilegi izan (esaterako, aurreko adibidean gauza bera da do i / do j exekutatzea edo, alderantziz, do j / do i).

Dependentzia-grafoa sortzeko, barneko indizearen araberako bektoreak analizatuko ditu konpiladoreak, eta horien arabera erabakiko du zer egin. Nolanahi ere, bi dimentsioko bektoreak prozesatzeko, begizta bat antolatu behar da, dela errenkadak dela zutabeak banan-banan prozesatzeko.

Esaterako, aurreko adibidean ez dago datu-dependentziarik; beraz, bi aukera ditugu: j begizta bektorizatzea (errenkadak), edo i begizta bektorizatzea (zutabeka).

1 A, 3

1.5. BEKTORE KODEA SORTZEKO TEKNIKA NAGUSIAK ▪ 45 ▪

Errenkadak bektore gisa prozesatzeko, honako hau egin behar da:

MOVI R2,#N ; errenkada kopurua MOVI VL,#M ; errenkaden luzera MOVI VS,#1 ; pausoa beg: LV V1,B(R1) LV V2,C(R1) ADDV V3,V1,V2 SV A(R1),V3 ADDI R1,R1,#M ; hurrengo errenkada SUBI R2,R2,#1 ; errenkada bat gutxiago BNZ R2,beg

Errenkada (bektore) bat prozesatu ondoren, R1 erregistroa eguneratu

behar da (+M), hurrengo errenkada erakusteko. R2 erregistroa kontagailu bat baino ez da, errenkada guztiak prozesatu ahal izateko.

Era berean, honela idatzi behar da kodea matrizeen zutabeak bektorizatzeko:

MOVI R2,#M ; zutabe kopurua MOVI VL,#N ; zutabeen luzeraa MOVI VS,#M ; pausoa beg: LV V1,B(R1) LV V2,C(R1) ADDV V3,V1,V2 SV A(R1),V3 ADDI R1,R1,#1 ; hurrengo zutabea SUBI R2,R2,#1 ; zutabe bat gutxiago BNZ R2,beg

Orain, bektore (zutabe) baten pausoa M da, eta hurrengo zutabearen

hasiera-helbidea erakusteko, +1 baino ez da egin behar11. Bigarren aukera hori erabiltzen denean, "begizta-trukea" egiten dela esaten da.

Oro har, beraz, P dimentsioko begiztak bektorizatzeko, P aukera desberdin analizatu behar dira (bat dimentsioko), eta egokiena aukeratu, beti ere aginduen arteko datu-dependentziak kontuan hartuz.

11 Oharra: aurreko adibideetan, matrizeak errenkadaka daude gordeta memorian, C-k egiten duen

bezala. Fortran-ek, aldiz, zutabeka gordetzen ditu matrizeak.

j

A

s = 1

i

0,0 0,1 … 0,M-1

1,0 1,1 … 1,M-1

… … … …

N-1,0 N-1,1 … N-1,M-1

j A

s = M

i

0,0 0,1 … 0,M-1

1,0 1,1 … 1,M-1

… … … …

N-1,0 N-1,1 … N-1,M-1

▪ 46 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

1.5.2.3. Begizta bat bektorizatu ahal izateko baldintza

Laburbil dezagun aurreko adibideetan ikusitakoa. Begiztaren aginduen arteko dependentziak analizatu behar ditu konpiladoreak, eta dependentzia-grafoa sortu. Grafo horretan oinarriturik erabaki behar du nola idatzi bektore-kodea begizta horretarako. Maiz, bektore-kodea sortzeko, berrordenatu egin beharko du jatorrizko kodea. Hori egitean, noski, konpiladoreak errespetatu egin behar du dependentziek ezartzen duten aginduen (eragiketen) arteko ordena: x → y dependentziak adierazten du x aginduaren eragiketa jakin bat y aginduaren eragiketa jakin bat baino lehen egin behar dela.

Zoritxarrez, ezin da edozein begizta bektorizatu. Nola jakin noiz bai eta noiz ez? Oro har, begizta bektoriza daiteke aginduen arteko datu-dependentziek ziklorik osatzen ez badute dependentzia-grafoan.

Begizta bektoriza daitekeenean, konpiladoreak bektore-kodea sortuko du, aginduen jatorrizko ordenari eutsiz edo, datu-dependentziak errespetatzeko, aginduak berrordenatuz (ikus geroxeago). Adi: aurreko adierazpenak ez du esaten zikloak daudenean bektorizazioa ezinezkoa dela. Geroxeago analizatuko ditugu ziklo horiek desegiteko erabil daitezkeen teknika batzuk.

Nahiz eta dependentzia-grafoan dependentzia-zikloak egon, eskuarki agindu batzuek parte hartuko dute ziklo horietan, eta besteek ez. Beraz, osoa bektorizatu ezin bada ere, konpiladorea saiatuko da, ahal duen neurrian, begizta partzialki bektorizatzen: arazoak sortzen dituen zatia eskalarki exekutatuko da; gainerakoa, bektorialki (loop fission). Adibidez:

do i = 1, N-1 1: A(i) = B(i) 2: B(i) = B(i-1) enddo

(lehenbiziko agindua bektoriza daiteke, baina bigarrena ez, bere buruarekiko dependentzia dela eta)

MOVI VL,#N-1 MOVI VS,#1

(1) LV V1,B+1(R1) SV A+1(R1),V1

(2) MOVI R3,#N-1

beg: FLD F1,B(R2) FST B+1(R2),F1 ADDI R2,R2,#1 SUBI R3,R3,#1 BNZ R3,beg

1.5.2.4. Datu-dependentziak analizatzeko proba

Esan dugunez, begizta bat bektorizatu ahal izateko, dependentzien analisia egin behar da lehenik. Baina, erraza al da bi aginduren artean datu-

1

2

B, 1

B, 0

1.5. BEKTORE KODEA SORTZEKO TEKNIKA NAGUSIAK ▪ 47 ▪

dependentziaren bat dagoen ala ez jakitea? Aurreko adibideetan ez da zaila izan, bektore-osagaiak atzitzeko indizeak (helbideak) funtzio sinpleak zirelako (i, i+1...). Analizatu, ordea, adibide hau:

do i = L1, L2 X(f(i)) = ... ... = X(g(i)) + 1 enddo

Badago dependentziaren bat X bektorean? Jakina, erantzuna f eta g funtzioen araberakoa da. f eta g funtzioen emaitzak, ordea, ezin dira aurreikusi, eta, beraz, konpiladoreak ez du nahikoa informaziorik erabaki bat hartzeko. Ondorioz, dependentzia badagoela erabaki beharko du.

Kasu berezi batzuetan bakarrik erabaki dezake konpiladoreak dependentzia dagoenetz: f eta g funtzioak do begiztako indizearen funtzio linealak direnean. Esaterako:

do i = L1, L2 X(a*i+b) = ... ... = X(c*i+d) enddo

Izan ere, hori bera da hasieran eman dugun bektoreen definizioarekin bat datorren kasu bakarra: memoriako hainbat osagai distantzia (pauso edo stride) konstantera. Geroxeago ikusiko dugu nola prozesatu pauso konstantea ez duten bektoreak (adibidez, A(i2)→ A1, A 4, A 9, A16...). X bektorean dependentzia dagoen ala ez erabakitzeko, honako ekuazio hau

ebatzi behar da:

a i1 + b = c i2 + d L1 ≤ i1, i2 ∈ Z ≤ L2

hau da, ikusi egin behar da ea bi balio dauden, i1 eta i2, begiztaren iterazio-mugen barnean, zeinekin bektoreak atzitzeko helbideak berdinak diren.

a i + b c i + d

i1 i2 L1 L2

▪ 48 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Aurreko adierazpena ekuazio diofantiarra da, eta soluzio orokorra aurkitzea oso konplexua da. Hala ere, honako hau esan daiteke:

▪ Ez dago dependentziarik (ekuazioak ez du soluziorik), baldin eta (d – b) / ZKH(a, c) ∉ Z, hots, zenbaki osoa ez bada.

Analisi horri ZKH proba deritzo (zatitzaile komunetan handiena) eta, beste batzuk ere erabiltzen badira ere, erabilienetako bat da aginduen arteko dependentziak analizatzeko.

ZKH probak ez du esaten dependentziaren bat noiz dagoen, noiz ez dagoen baizik. Izan ere, emaitza zenbaki osoa bada, ekuazioak badu soluziorik, baina dependentzia dagoen ala ez jakiteko, soluzioak begiztaren mugen barruan dauden analizatu behar da. Horretarako, askotan nahikoa da atzitzen diren bektore-tarteak aztertzea: teilakatzen ez badira, ez dago dependentziarik; teilakatzen badira, litekeena da dependentzia bat izatea12. Hiru kasu bereiz daitezke:

(1) (2) (3)

Lehen kasuan ez dago dependentziarik: ekuazioaren balizko soluzioa begiztaren bi mugetatik kanpo izango da (begiztaren tartearen barruan, bi ekuazioek ez dute inoiz balio bera ematen). Bigarren kasuan, dependentzia egon daiteke, bi ekuazioen emaitzek tarte komun bat dutelako; (dependentzia mota eragiketen araberakoa izango da). Hirugarren kasua da konplexuena. Dependentzia egon daiteke bi aginduen artean; gainera, batean idazketa eta bestean irakurketa egiten bada, begiztaren tarte batean antidependentziak izango ditugu eta bestean dependentziak (antzeko arazoa bi eragiketak idazketak badira). Beraz, agindu horiek ezin dira bektorizatu, osagai batzuk idazketa egin baino lehen irakurri behar direlako eta beste batzuk idazketa egin eta gero (agian begizta bi partetan banatu daiteke, gurutze-puntuaren arabera, eta teknika desberdinak erabili, batean zein bestean, kodea sortzeko). 12 Erabakia konplexua da, kontuan hartu behar baitira bektoreen pausoak (a eta c) eta teilakatzen den

tartearen luzera, gutxienez bektore-osagai batean bat egiten dutela ziurtatzeko.

i L1 L2 i L1 L2 i L1 L2

1.5. BEKTORE KODEA SORTZEKO TEKNIKA NAGUSIAK ▪ 49 ▪

Ikus ditzagun adibide batzuk:

(1) do i = 1, 100 A(2*i) = ... → (1 – 0) / ZKH(2, 2) = 1/2 ... = A(2*i+1) enddo

Beraz, ez dago dependentziarik bi aginduen artean; izan ere, agindu batek osagai bikoitiak idazten ditu, eta besteak osagai bakoitiak irakurtzen ditu.

(2) do i = 5, 100 A(i-5) = ... ... = A(2*i+90) → (90 – (–5)) / ZKH(2, 1) = 95 enddo

Beraz, dependentzia egon daiteke. Baina ez dago, atzipen-tarteak disjuntuak direlako: wr: A0 ... ... A95 rd: A100 ... ... A290

(3) do i = 1, 100 A(3*i+100) = ... → (100 – (–1)) / ZKH(3, 2) = 101 ... = A(2*i-1) enddo

Litekeena da dependentziaren bat egotea. Hauek dira atzipen-tarteak: wr: A103 ... ... A400 rd: A1 ... ... A199 Bi tarteek zati komun bat dute; beraz, bai, badago dependentzia: kasu honetan, esaterako, i = 1 iterazioko emaitza (A103) i = 52 iterazioan irakurtzen da.

(4) do i = 1, 100 A(6*i+3) = ... → (81 – 3) / ZKH(6, 3) = 26 ... = A(3*i+81) enddo

Beraz, egon daiteke dependentzia. Hauek dira atzipen-tarteak: wr: A9 ... ... A603 rd: A84 ... ... A381 Tarte bat bestearen barnean dago; beraz, dependentzia badago, segur aski bi motakoa. Adibidez, i = 2 iterazioan A87 osagaia irakurtzen da, geroago, i = 14 iterazioan idatziko dena (antidependentzia bat); baina gero, i = 28 iterazioan, A165 osagaia irakurtzen da, i = 27 iterazioko emaitza, hain zuzen ere (benetako dependentzia).

▪ 50 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Adi. Memoria-atzipenen pausoa bi tokitan adieraz daiteke: begizta-mugen definizioan edo aginduetan bertan. ZKH proba erabili baino lehen, ordea, begiztak normalizatu egin behar dira, begiztaren pausoak 1 izan dadin. Nahikoa da, horretarako, aldagai-aldaketa sinple bat egitea; esaterako:

do i = 1, 100, 2 do k = 1, 50, 1 A(i) = ... A(2*k-1) = ... B(2*i+5) = ... B(4*k+3) = ... enddo enddo

Laburbilduz: bektore-konpiladoreak analizatuko ditu begiztako aginduen arteko dependentziak, dependentzia-grafoa sortzeko. Grafo horretan dependentzia-ziklorik ez badago, begizta zuzenean bektorizagarria da, eta dagokion bektore-kodea sortuko du. Bestela, bektorizazioa ahalbidetzeko hainbat optimizazio-teknika erabiliko ditu, dependentzien eragina desagerrarazteko, eta, azkenik, osoa ezin bada, begizta partzialki bektorizatzen saiatuko da. Azter ditzagun, bada, optimizazio-teknika nagusiak.

1.5.3. Optimizazioak

Konpilazio-prozesua oso garrantzitsua da kalkulu-abiadura handia lortzeko. Ez ahaztu: bektorizazio-faktore handia lortu ezean, makinaren errendimendua ez da ona izango (Amdahl-en legea). Aipatu berri dugu zer baldintza bete behar den begizta bat bektorialki idatzi eta exekutatu ahal izateko: dependentzia-grafoan ziklorik ez izatea. Maiz, begiztak dituen dependentziak programaren idazkerari dagozkio, eta ez, ordea, exekutatu nahi den algoritmoari (esaterako, antidependentziak edo irteera-dependentziak direnean). Kasu horietan, zenbait eraldaketa edo optimizazio egin daitezke kodea bektorizatu ahal izateko. Bi motakoak dira analizatuko ditugun optimizazioak: dependentziak desagerrarazten laguntzen dutenak eta kalkulu-abiadura handiagoa lortzeko erabiltzen direnak.

1.5.3.1. Aurreranzko ordezkapen globala (global forward substitution)

Analizatu begizta hau:

NP1 = L + 1 NP2 = L + 2 ...

1.5. BEKTORE KODEA SORTZEKO TEKNIKA NAGUSIAK ▪ 51 ▪

do i = 1, L 1: B(i) = A(NP1) + C(i) 2: A(i) = A(i) - 1 do j = 1, L 3: D(j,NP1) = D(j-1,NP2) * C(j) + 1 enddo enddo

Badago antidependentziarik 1 eta 2 aginduen artean? Badago errekurrentziarik 3 aginduan?

Zoritxarrez, programaren hasieran definitutako NP1 eta NP2 aldagaiek dependentziak analizatzea oztopatu egiten dute. Analisia egin ahal izateko, beraz, konpiladoreak ordezkatu egingo ditu bi aldagai horiek haien definizioaz, programa osoan, eta gero erabakiko du datu-dependentziaren bat dagoen ala ez. Ez ahaztu: indizeen balioak analizatu ezin baditu, dependentzia dagoela erabakiko du konpiladoreak (eta, beraz, dependentzia-grafoan gehituko du).

do i = 1, L 1: B(i) = A(L+1) + C(i) 2: A(i) = A(i) - 1 do j = 1, L 3: D(j,L+1) = D(j-1,L+2) * C(j) + 1 enddo enddo

Orain garbi dago: ez dago antidependentziarik 1 eta 2 aginduen artean, bi bektoreen indizeak (i eta L + 1) ez baitira inoiz berdinak izango; eta ez dago errekurrentziarik 3 aginduan, L + 1 ≠ L + 2 delako.

Aldagai laguntzaileez gain, konstante-definizio guztiak ere desegin behar dira dependentzien analisia errazteko.

1.5.3.2. Indukzio-aldagaiak

Analizatu adibide hau:

j = 2 k = 2 do i = 1, L j = j + 5 R(k) = R(j) + 1 k = k + 3 enddo

▪ 52 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Badago errekurrentziaren bat R bektorean? Dagoen moduan, konpiladoreak ezin ditu dependentziak analizatu, j eta k ezezagunak direlako (ez dira i-ren funtzioak). Baina analisi sinple batek egiazta dezake ez dagoela dependentziarik. Berez, honela aldatzen dira j eta k aldagaiak i-rekin:

i = 1 2 3 4 5 ... j = 7 12 17 22 27 ... k = 2 5 8 11 14 ...

Progresio aritmetikoan aldatzen diren bi aldagai dira j eta k, indukzio-aldagaiak, alegia, eta ez dugu batere arazorik i-ren funtzio gisa birdefinitzeko:

j = 5i + 2 eta k = 3i – 1

Ondorioz, honela geratuko da begizta, indukzio-aldagaiak kendu ondoren:

do i = 1, L R(3*i-1) = R(5*i+2) + 1 enddo

Orain bai, konpiladorea gauza izango da dependentziak analizatzeko. Ohikoa izaten da aldagai laguntzaile mota hori kalkuluko begiztetan, eta, beraz, konpiladoreak detektatu beharko ditu aldagai horiek, eta ordezkatu dagozkien funtzioez, dependentziak analizatu ahal izateko (eta, kasu, begizta bektorizatu ahal izateko).

1.5.3.3. Antidependentziak (WAR)

Dagoeneko aipatu dugunez, dependentzia ahulak dira antidependentziak eta, eskuarki, erraz desagerraraz daiteke bektorizatze-prozesuaren gainean duten eragina, jatorrizko kodean eraldaketa txikiak eginez.

Kontuan hartu adibide hau:

do i = 0, N-2 1: A(i) = B(i) + C(i) 2: D(i) = A(i) + A(i+1) enddo

Begizta horren dependentzia-grafoan, dependentzia-ziklo bat ageri da.

Beraz, zerbait egiten ez badugu, begizta ezin da bektorizatu. Baina, zikloa

2

1

A, 0 A, 1

1.5. BEKTORE KODEA SORTZEKO TEKNIKA NAGUSIAK ▪ 53 ▪

osatzen duten dependentzien artean antidependentzia bat dago: bigarren aginduak irakurri behar du A(i+1) bektorea lehenengoak A(i) idatzi baino lehen (bestela, balio berriak irakurriko genituzke, eta ez zaharrak, begiztak adierazten duen moduan). Zer egin? Bada, irakurri lehenago A(i+1) bektorea!

Esaterako, berridatzi begizta honela:

do i = 0, N-2 0: [T(i)] = A(i+1) 1: A(i) = B(i) + C(i) 2: D(i) = A(i) + [T(i)] enddo

Begiztaren bertsio berrian ez dago ziklorik dependentzia-grafoan eta, ondorioz, bektoriza daiteke. Begizta berrian bektore laguntzaile bat, T, erabili badugu ere, eskuarki ez da beharrezkoa bektore hori erabiltzea (memorian gordetzea), eta nahikoa da irakurri den bektorea erregistro batean uztea, gero handik irakurtzeko. Noski, erregistro librerik ez balego, orduan bai, memoriara eraman beharko litzateke.

Honela geratuko da kodea:

MOVI VL,#N-1 MOVI VS,#1

(2/0) LV V1,A+1(R1) ; aurreratu A+1 bektorearen irakurketa

(1) LV V2,B(R1) LV V3,C(R1) ADDV V4,V2,V3 SV A(R1),V4

(2) ADDV V5,V1,V4 ; erabili lehen irakurritakoa (V1) SV D(R1),V5

1.5.3.4. Irteera-dependentziak (WAW)

Aurreko kasu bera gerta daiteke irteera-dependentziekin. Adibidez:

do i = 0, N-3 1: A(i) = B(i) + C(i) 2: A(i+2) = A(i) * D(i) enddo

2

1 T, 0 A, 1

0

A, 0

1

2

A, 0 A,2

▪ 54 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Dependentzia-grafo horretan ere ziklo bat ageri da, irteera-dependentziarekin osatzen dena. Eraldaketaren bat egiten ez badugu, ezin da bektorizatu. Izan ere, programaren esanahia mantentzeko, 2 aginduak 1 aginduak baino lehen idatzi behar du, edo, baliokidea dena, atzeratu egin behar da 1 aginduaren idazketa; honela, esaterako:

do i = 0, N-3 1: [T(i)] = B(i) + C(i) 2: A(i+2) = [T(i)] * D(i) 3: A(i) = [T(i)] enddo

Berriro ere, eskuarki ez da erabiltzen bektore laguntzailea (T), eta emaitza

bektore-erregistro batean uzten da, gero handik memoriara eramateko. Honela geratuko da bektore-kodea, egoki ordenatuta:

MOVI VL,#N-2 MOVI VS,#1 (1) LV V1,B(R1) ; jatorrizko 1 agindua, idazketa izan ezik LV V2,C(R1) ADDV V3,V1,V2 (2) LV V4,D(R1) MULV V5,V3,V4 SV A+2(R1),V5 (1/3) SV A(R1),V3 ; jatorrizko 1 aginduaren idazketa

1.5.3.5. Begizta-trukea (loop-interchanging)

Bi dimentsioko bektoreek (n dimentsiokoek, oro har) bektorizazio modu bat baino gehiago onartzen dute, bektoreen definizioaren arabera (errenkada, zutabea, eta abar). Bat edo beste aukeratzeko, aginduen arteko dependentziak kontuan hartu behar dira. Esaterako:

do i = 0, N-1 do j = 1, N-1 A(i,j) = A(i,j-1) + 1 enddo enddo

1

2

3

T, 0

A, 2

T, 0

j

i 1

A, (0, 1)

1.5. BEKTORE KODEA SORTZEKO TEKNIKA NAGUSIAK ▪ 55 ▪

Dependentzia-grafoaz gain (agindu bakarra dago; beraz, dependentzia bat dagoenez, ziklo bat izango da), iterazio-espazioa ere marraztu dugu, dependentziak denboran zehar nola banatzen diren ikusteko. Grafo horretatik nabarmen ondorioztatzen da ezin dela begizta bektorizatu, ez behintzat idatzita dagoen bezala, hots, errenkadaka, barneko begiztako j iterazioan j–1 iterazioan sortutako osagaia erabili behar baita.

Aldiz, ez dago batere arazorik eragiketa zutabeka bektorizatzeko, zutabe bakoitzaren osagaiak independenteak direlako; hau da, beste modu honetan:

do j = 1, N-1 do i = 0, N-1 A(i,j) = A(i,j-1) + 1 enddo enddo

Nahikoa da, lehen ikusi dugunez, zutabeak (s = N) prozesatzea bektore

gisa, hots, begizta-trukea egitea (begizten jatorrizko ordena aldatzea). Begizta-trukea ezin da kasu guztietan erabili, aginduen arteko

dependentzien esanahia errespetatu behar baita, beti. Esaterako, hurrengo adibideko kasuan ezin da erabili; begizta ezin da zutabeka prozesatu, j zutabean j+1 zutabeko emaitzak behar baitira.

do i = 1, N-1 do j = 1, N-2 1: A(i,j) = B(i-1,j+1) + 1 2: B(i,j) = A(i,j-1) enddo enddo

Begizten ordena aldatzen denean, dependentzien distantzia-bektoreak ere

aldatzen dira; esaterako, (2, 1) distantziako dependentzia (1, 2) distantziako dependentzia bihurtzen da. Begiztak trukatu ahal izateko, jatorrizko esanahia errespetatuz, honako hau bete behar da: distantzia-bektore berrietan, 0 ez den lehen osagaiak (pisu handienekoak) positiboa izan behar du.

Esaterako, aurreko grafoko kasurako, honako hau gertatzen da:

j

i

j

i 1

2

A, (0, 1)

B, (1, -1)

▪ 56 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

- begiztak trukatu gabe - begiztak trukatu ondoren d1 → (0, 1) d1 → (1, 0) arazorik ez d2 → (1, –1) d2 → (–1, 1) kontuz! hau ez da posible

Beraz, ezin da errenkadaka bektorizatu, eta ezin da begizta-trukea erabili. Zenbait kasutan, egokia izan daiteke begizten fisioa eta trukea batera

erabiltzea, begizta bektorizatu ahal izateko. Adibidez,

do i = 1, N-1 do j = 1, N-1 1: A(i,j) = A(i-1,j) + 1 2: B(i,j) = B(i,j-1) * 2 enddo enddo

Iterazioen espazioan ageri diren dependentziak direla eta, begizta ezin da

bektorizatu, ez errenkadaka, ez zutabeka. Baina, adibide honetan, errenkadetako dependentzia agindu bati dagokio (2), eta zutabekoa beste bati (1), dependentzia-grafoan ageri den moduan. Beraz, begizta bitan banatu daiteke; gero, lehenbiziko agindua (A bektorea) errenkadaka bektoriza daiteke, eta bigarrena (B bektorea), berriz, zutabeka, begiztak trukatuta.

Dena den, nahiz eta posible izan, begiztak bakarrik trukatzen dira horrekin kodearen bektorizazioa errazten bada, edo, kasu, exekuzio-abiadura hazten bada. Esaterako, begizta-trukea erabil daiteke adibide honetan:

do i = 0, 99 do j = 0, 9 A(i,j) = A(i,j) + 1 enddo enddo

Batere dependentziarik ez dago iterazioen artean; beraz, errenkadaka

bektoriza daiteke, idatzita dagoen bezala, bai eta zutabeka ere, begizten ordena aldatuta. Errenkadaka egiten bada, 10 osagaiko 100 bektore prozesatzen dira. Bektoreak txikiak dira eta, segur aski, errendimendua ere txikia izango da (N-ren araberakoa da eta). Aldiz, begizten ordena aldatuta, 100 osagaiko 10 bektore prozesatuko dira, eta, bektoreak luzeagoak direnez, kalkulu-abiadura handiagoa lortuko dugu.

1 A, (1, 0)

2 B, (0, 1)

j

i

A

B

1.5. BEKTORE KODEA SORTZEKO TEKNIKA NAGUSIAK ▪ 57 ▪

1.5.3.6. Hedapen eskalarra (scalar expansion)

Begiztak idaztean, oso ohikoa da aldagai laguntzaileak erabiltzea. Esaterako,

do i = 0, N-1 batura = A(i) + B(i) C(i) = batura * batura D(i) = batura * 2 enddo

Bektoreak prozesatzen badira ere, tartean aldagai eskalar bat erabiltzen da, batura. Eta aldagai horrek galarazi egiten digu bektorizazioa, dependentziak sortzen baititu iterazio guztien artean. Hala ere, batura ez da berez erabili behar dugun aldagai bat, aldagai laguntzaile bat baizik. Beraz, zergatik ez idatzi kodea honela?

do i = 0, N-1 batura(i) = A(i) + B(i) C(i) = batura(i) * batura(i) D(i) = batura(i) * 2 enddo

Lehen aldagai bakar bat zena, orain bektore oso bat da: batura(i). Dagoeneko ez dago arazorik begizta bektorizatzeko. Teknika horri, eskalar bat bektore bihurtzeari, hedapen eskalarra deritzo.

Aurreko kasuetan bezala, hedapen eskalarrak ez du eskatzen bektore berria memorian gordetzea; nahikoa izan ohi da bektore-erregistroak erabiltzea. Begiztaren bukaeran, ez ahaztu, azken iterazioko balioa utzi behar da jatorrizko batura aldagaian:

batura = batura(N-1)

1.5.3.7. Begizten fusioa (loop fusion)

Optimizazio honen bidez, begizta bakar batean bilduko ditugu bi begizta (edo gehiago), begiztekin erlazionatzen den gainkarga guztia arintzeko asmoz, eta, ahal bada, bektore-eragiketen emaitzak berriz erabili ahal izateko. Adibidez,

▪ 58 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

do i = 0, N-1 Z(i) = X(i) + Y(i) enddo do i = 0, N-1 R(i) = Z(i) + 1 enddo

do i = 0, N-1 Z(i) = X(i) + Y(i) R(i) = Z(i) + 1 enddo

Bi "programa" horiek berdinak dira, baina bigarrena "errazagoa" da

exekutatzeko. Lehenik eta behin, konpiladoreak aprobetxatu egingo du lehenengo aginduan egindako kalkulua bigarrenerako, zuzenean erregistro batetik irakurriz (ez du SV Z eta gero LV Z egingo); horrez gain, begiztekin erlazionatzen den kode guztia (helbideratzea, bektoreen luzera, pausoa...) behin baino ez da egingo.

Jakina, ez da beti posible bi begizta bat bihurtzea. Adibidez, bi programa hauek, argi eta garbi, desberdinak dira:

do i = 1, L Z(i) = X(i) + Y(i) enddo ≠ do i = 1, L R(i) = Z(i+1) + 1 enddo

do i = 1, L Z(i) = X(i) + Y(i) R(i) = Z(i+1) + 1 enddo

Begizten fusioa ez da automatikoki erraz egiten den optimizazioa, aginduen arteko dependentzien analisia oinarrizko blokeak (begiztak) baino harantzago zabaldu behar baita, eta, eskuarki, konpiladoreek ez dute hori egiten.

1.5.3.8. Begizten kolapsoa (loop collapsing)

Aztertu berri dugunez, dimentsio bat baino gehiagoko begiztak errenkadaka, zutabeka... bektoriza daitezke hainbat kasutan. Hala ere, iterazio kopurua (bektoreen tamaina) txikia baldin bada, egokiagoa izan daiteke bi dimentsio (edo gehiago) batean biltzea. Adibidez,

float A(10,10) do i = 0, 9 do j = 0, 9 A(i,j) = A(i,j) + 1 enddo enddo

1.5. BEKTORE KODEA SORTZEKO TEKNIKA NAGUSIAK ▪ 59 ▪

Begizta hori bektorialki exekuta daiteke, arazorik gabe, baina definitzen diren bektoreak (errenkadak zein zutabeak) txikiak dira. Bektore-erregistroak ondo aprobetxatzeko, badaukagu aukera hau:

float A(100)

do i = 0, 99 A(i) = A(i) + 1 enddo

Izan ere, memoria-espazioa lineala da, eta matrizearen errenkadak bata bestearen ondoan daude metatuta; beraz, A[N,N] matrizea A[N×N] bektore gisa ere prozesa daiteke.

1.5.3.9. Beste zenbait optimizazio

Aztertu ditugun optimizazioak ohikoenak dira, eta badaude gehiago. Hala ere, askotan gertatzen da bektorizatzeko erraza dirudiena benetan zaila izatea automatikoki (konpiladoreak) egiteko. Kasu horietan, programatzailearen laguntza da irtenbide egokiena. Laguntza hori konpiladorearentzako sasiaginduen bidez egiten da eskuarki: bektorizatu behar dituen kode zatiak adierazten zaizkio konpiladoreari, dependentzien analisia egin beharrik gabe. Esaterako, aztertu begizta hau:

do i = a, b X(i) = Y(i) + X(i+M) enddo

Informazio gehiagorik izan gabe, konpiladoreak ezin du begizta bektorizatu, X bektorean errekurrentzia bat egon daitekeelako, M aldagaiaren arabera: M ≥ 0 bada, ez dago arazorik bektorizatzeko; aldiz, M < 0 bada, begizta ezin da bektorizatu (M ez da konstante bat; hala balitz, konpiladoreak konstante hori bere balioaz ordezkatuko luke).

Baina baliteke programatzaileak M-ri buruzko informazio gehiago izatea. Adibidez, jakin dezake M-k parametro fisikoren bat adierazten duela eta beti positiboa dela (edo, esaterako, aldez aurretik M = A(i) * A(i) exekutatu dela). Hala izanik, begizta bektorizatu egin behar duela adieraziko dio programatzaileak konpiladoreari.

Bestalde, konpiladoreak berak erabaki lezake begizta honela exekutatzea:

▪ 60 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

if (M ≥ 0) then do i = a, b X(i) = Y(i) + X(i+M) enddo else do i = a, b X(i) = Y(i) + X(i+M) enddo endif

Lehenbiziko partea (then) bektore-kode gisa exekutatuko da; bigarrena, aldiz, eskalarki.

1.5.4. Maskara- eta Indize-bektoreak

Orain arte erabili ditugun bektore-eragiketa guztiak oso "sinpleak" izan dira. Baina, zoritxarrez, bektore-eragiketa konplexuagoak exekutatu behar dira, maiz, programa errealetan. Hurrengo lerrootan, bi kasu berezi aztertuko ditugu, kalkulu zientifikoan asko agertzen dira eta: maskaren erabilera eta pauso aldakorreko bektoreak.

1.5.4.1. Maskaren erabilera

Behin baino gehiagotan, bektore-eragiketetan ez dira kalkulatu/gorde behar bektore baten osagai guztiak, bakan batzuk baizik. Esaterako,

do i = 0, N-1 if (B(i) > 5.0) then A(i) = A(i) + 1.5 enddo

Orain arte ikusi dugunarekin, aurreko begizta ezin da bektorialki exekutatu, ezin baita aurreikusi zein bektore-osagai prozesatu behar diren eta zein ez. Hala ere, ohiko kasu bat da, eta irtenbide bat dago: maskara-erregistroa. Maskara-erregistroa (VM, vector mask) bektore-erregistro boolear (1/0) berezia da, eta eragiketa logiko baten emaitzak gordetzen ditu. Bektore-eragiketa guztiek kontuan hartzen dute VM erregistroaren edukia, honek adierazten baitie zein bektore-osagai prozesatu behar diren eta zein ez.

Ohikoa da agindu bereziak izatea maskara-erregistroarekin lan egin ahal izateko. Esaterako,

1.5. BEKTORE KODEA SORTZEKO TEKNIKA NAGUSIAK ▪ 61 ▪

SxxV V1,V2 Bi bektoreak osagaiz osagai konparatzen dira, eta emaitza boolearrak (1/0) VM erregistroan uzten dira (xx = konparazio-eragiketa: EQ, NE, GT...)

SxxVS V1,F1 Gauza bera, baina eskalar bat erabiliz konparaziorako.

CVM Clear vector mask, maskara hasieratzeko.

POP R1,VM VM erregistroko zenbat bit dauden aktibatuta kontatzen da; emaitza R1 erregistroan uzten da.

Honela bektorizatuko da aurreko begizta maskara-erregistroa erabiliz:

MOVI VL,#N MOVI VS,#1 MOVI F1,#5.0

LV V1,B(R1) SGTVS V1,F1 ; Set Greater Than Vector/Scalar VM := V1~F1

LV V2,A(R1) ADDVI V3,V2,#1.5 SV A(R1),V3

CVM ; Clear Vector Mask

SGTVS aginduak V1 eta F1 erregistroak konparatzen ditu, eta VM erregistroan uzten ditu emaitzak: VM[i] := (V1[i] > 5.0). Hurrengo bektore-aginduek VM erregistroan adierazitako posizioetan bakarrik utziko dute emaitza. CVM aginduak hasieratzen du berriro VM erregistroa.

Kontuz! Eragiketaren exekuzio-denbora ez da aldatzen; ADDVI exekutatzen denean, helburu-erregistroko idazketak baino ez dira maskaratzen. Hori dela eta, adi egon behar da unitate funtzionalean sor daitezkeen salbuespenekin, osagai guztiak prozesatzen ari baitira. Makina batzuetan, aldiz, eragiketa unitate funtzionalean zein idazketa erregistroan, biak, maskaratzen dira.

1.5.4.2. Indize-bektoreak

Aplikazio zientifiko askotan, datu-egitura oso handiak erabiltzen dira (esaterako, 10.000×10.000-ko matrize bat). Hala ere, zenbait kasutan, osagai horietatik guztietatik bakar batzuk baino ez dira prozesatu behar. Irudi honetan, adibide bat ageri da.

▪ 62 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Matrizea handia izanda ere, markatutako osagaiak bakarrik prozesatu

behar dira. Osagai horiekin bektore bat osa daiteke, baina badago horretarako funtsezko arazo bat. Orain arte, bektore bat definitzeko, hasiera-helbidea, luzera eta pausoa erabili ditugu, eta osagai batetik bestera heltzeko <helbidea + pausoa> eragiketa egin dugu, beti bera. Irudian ageri den moduan, definitu nahi dugun bektore berriaren pausoa ez da konstantea; beraz, ezin dugu erabili aurreko prozedura osagaiak memoriatik eskuratzeko edo memoriara eramateko.

Oro har, hau da arazoa: nola prozesatu bektorialki pauso konstantea ez duten bektoreak? Hori egin ahal izateko, beste atzipen modu (helbideratze-modu) bat erabili beharko dugu.

Atzipen berri hori indize-bektoreak erabiliz lortzen da: indize-erregistro batean gorde egin behar dira, irakurketa edo idazketa egin baino lehen, atzitu nahi diren bektore-osagaien posizioak.

Halako bektore-eragiketa hiru fasetan banatu ohi da:

1. Biltze fasea (gather): memorian barreiatuta dauden osagaiak indize-erregistroa erabiliz irakurtzen dira —oinarria + desplazamendua—, eta bektore-erregistro arrunt batean kargatzen dira.

2. Eragiketa fasea: behar den eragiketa egiten da.

3. Barreiatze fasea (scatter): emaitzak memoriara eramaten dira, dagozkien posizioetara, berriro indize-erregistroa erabiliz.

Biltze eta barreiatze faseak gauzatzeko, eta, oro har, indize-erregistroekin lan egiteko, honako agindu hauek erabil daitezke (adibidez):

LVI V1,A(V2) Irakurri memoriatik A + V2(i) osagaiak, V2 indize-erregistro gisa erabiliz.

SVI A(V2),V1 Idatzi memorian A + V2(i) osagaiak, V2 indize-erregistro gisa erabiliz.

CVI V1,R1 Indize-bektore bat sortu: 0, R1, 2R1, ..., (Lmax–1)R1.

s = 3

5

14

4

1 8

1.5. BEKTORE KODEA SORTZEKO TEKNIKA NAGUSIAK ▪ 63 ▪

Ikus dezagun adibide bat:

do i = 0, M-1 A(i*i) = B(i*i) + 1 enddo

Dagoen moduan, zaila da begizta horren bektorizazio arrunta egitea, A eta B bektoreen pausoa ez baita konstantea (0, 1, 4, 9...). Hala ere, badaukagu aukera bat honela bektorizatzeko:

MOVI VL,#M

MOVI R1,#1 CVI V4,R1 ; 0, 1, 2... MULV V5,V4,V4 ; indize-erregistroa: i*i LVI V1,B(V5) ; helbideratze indizeduna ADDVI V2,V1,#1 SVI A(V5),V2

Indizeak adierazteko, V5 erregistroa erabili dugu, non i*i funtzioaren emaitzak kargatu baititugu. Gero, helbideratze indizeduna erabili dugu bektoreak atzitzeko: oinarria + indize-bektorea.

Konputagailuen arabera, mota horietako memoria-atzipenak atzipen arruntak baino motelagoak ohi dira (ziklo gehiago behar da).

Helbideratze-modu indizeduna erabil daiteke, halaber, aurreko atalean analizatu dugun adibidea —if (B(i)>5.0) then A(i) = A(i) + 1.5— beste modu honetan exekutatzeko:

MOVI VL,#N MOVI VS,#1

MOVI F1,#5.0 LV V1,B(R1) SGTVS V1,F1 ; maskara sortu (VM) MOVI R2,#1 ; create vector index: 0, 1, 2... VM-ren arabera CVI V2,R2 ; adibidez: VM = 10011101 → V2 = 03457 POP R1,VM ; zenbatu 1ekoen kopurua VM erregistroan (5) MOV VL,R1 ; kargatu VL erregistroa (osagai kopurua) CVM ; hasieratu maskarak

LVI V3,A(V2) ; erabili V2 indize-erregistro gisa, ADDVI V4,V3,#1.5 ; eta prozesatu soilik VL osagai SVI A(V2),V4

▪ 64 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Hala, azkeneko zatian (LVI / SVI) ez dira irakurtzen edo idazten osagai guztiak (LV edo SV arruntekin egiten den moduan), baizik eta prozesatu behar direnak baino ez.

1.6. LABURPENA

Bektore-konputagailuak bektoreak (begiztak) prozesatzeko espresuki diseinatutako konputagailuak dira. Bi atal bereizten dira bektore-konputagailuetan: bektoreak prozesatzen dituena eta eskalarrak prozesatzen dituena, aurrekoa bezain garrantzitsua (programa errealetan, bi kode motak izango ditugu, bektoriala eta eskalarra, batera; beraz, beharrezkoa da kode eskalarra ere eraginkorki exekutatzea). Makina horien agindu-multzoak bektore-aginduak ditu (LV, SV, ADDV...), eta horietako agindu bakar batekin bektore oso bat prozesatzen da. Hauek dira bektore-prozesadoreen arkitektura-ezaugarri nagusiak: bektore-erregistroak erabiltzea, aginduen arteko kateaketa egitea, memoriako banda-zabalera oso handia izatea (bus asko memoriarekin lan egiteko), eta memoriako modulu kopurua handia izatea. Arkitektura hori dela eta, honela eman daiteke begizten exekuzio-denbora: TB = th + tb × N (th = hasiera-denbora; tb = osagai bat prozesatzeko denbora, ziklo bat kasurik onenean); eredu eskalar tradizionalean, ordea, TE = te × N (te = osagai bat eskalarki prozesatzeko denbora, eskuarki begizta baten iterazio bat).

Bektore-konputagailuen abiadura adierazteko ohiko parametroak, programa jakin baterako, bi hauek dira: R∞ (kalkulu-abiadura bektoreak oso luzeak direnean) eta N1/2 (bektoreen tamaina minimoa gutxienez abiadura maximoaren erdia eskuratzeko). Beste prozesadore-ereduekin gertatzen den bezala, bektore-prozesadoreen kalkulu-abiadura "gorena" (peak performance) ezin da kalitate-parametro gisa erabili. Izan ere, hasiera-denborak (start-up) biziki garrantzitsuak dira, ez baitira beti bektore oso luzeak prozesatzen.

Edonola ere, badaude kalkulu-abiadura mugatzen duten hainbat faktore. Batetik, hardwarea bera: bektore-erregistroen tamaina eta kopurua, memoriarako bus kopurua, unitate funtzionalen kopurua... Baina abiaduraren gainean eragin handiena duen parametroa bektorizazio-faktorea da, f: bektore moduan exekutatzen den programaren ehunekoa.

1.6. LABURPENA ▪ 65 ▪

Hori dela eta, konpiladoreen eginkizuna funtsezkoa da makina horietan. Bektore-konpiladorearen esku geratzen da bektore-kodea sortzeko ardura, ohiko programetatik/begiztetatik abiatuta. Eta bektorizazio-faktorerik ahalik eta handiena lortu beharko du; bestela, Amdahl-en legeak erakusten duen moduan, kalkulu-abiadura txikia izango da. Konpiladorearen eginkizuna errazteko eta emaitzak hobetzeko, garrantzitsua da beti erabiltzaile adituaren laguntza izatea. Hainbat bektorizazio-teknika "klasiko" bihurtu dira dagoeneko, eta konpiladore guztiek erabiltzen dituzte. Dependentzien analisian oinarritzen dira teknika horiek, eta erabilgarriak dira, halaber, kodea paralelizatu behar denean, hots, programa hainbat prozesadoreren artean exekutatu behar denean. Beraz, berriro analizatu beharko dugu hurrengo kapituluetan.

▪ Bektore-konputagailuen historia laburra

Konputazioaren historia laburraren zehar, bektore-konputagailuak izan dira beti azkarrenak kalkulu zientifikoa exekutatzen. Teknologia aurreratuenak (ECL) eta arkitektura berriak erabiliz, konputazio-abiaduraren erreferentzia izan dira duela gutxi arte. Hala ere, multiprozesadoreen eboluzioa dela eta, bazterrean geratzen ari dira.

Nahiz eta lehenbiziko bektore-konputagailua CDC STAR-100 (1972) izan, makina hauen historia markatu zuen lehen konputagailua Cray-1 izenekoa izan zen (1975). Bektore-erregistroak eta kateaketa erabiltzen zituen makina horrek lehenengo aldiz. Horrekin batera, eta Amdahl-en legea aintzakotzat hartuz, prozesadore eskalarra oso azkarra zen (garaiko azkarrena). Hala ere, eta muga teknologikoak zirela medio, memoria-unitate bakarra zuen (hots, LV edo SV bakarra exekutatu zitekeen aldi berean).

1981ean, CDC etxeko CYBER 205 konputagailua merkaturatu zen, STAR makinaren ondorio naturala: M/M eredua mantentzen zuen, baina memoria-unitate asko zituen (izan ere, gutxienez hiru behar dira M/M motako bektore-konputagailuetan). Konputagailu horretan erabili ziren lehen aldiz indize-bektoreak, dentsitate gutxiko (sparse) matrizeak prozesatzeko.

Cray-1 makinaren hurrengoa Cray X-MP izan zen; aurreko diseinuaren eboluzioa zen, besterik ez (erloju azkarragoa, bus gehiago memoriarekin, prozesadore bat baino gehiago izateko aukera). Laster atera zuten Cray-2 konputagailua: 4 prozesadore; 156 MB DRAM memoria (60 biteko hitzak); erloju azkarragoa, baina unitate funtzionalen latentzia handiagoa (ziklotan); kateaketarik gabe; eta bus bakarra. Egia esan, ez zuen merezi hura erabiltzea, batik bat haren memoria handia beharrezkoa ez bazen.

▪ 66 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

80ko hamarkadan, superminikonputagailuak agertu ziren merkatuan, aurrekoen aldean askoz merkeagoak; esaterako, Convex-eko C-1 eta C-2 (2 prozesadore). Makina horien arrakastaren zioa, prezioa ez ezik, haien konpiladorea izan zen, kodea bektorizatzen oso eraginkorra zelako.

Japoniako konputagailuak etorri ziren gero. Fujitsu-ko VP100 eta VP200 konputagailuak 1983an merkaturatu ziren, eta, pixka bat geroxeago, Hitachi S810-a eta NEC SX/2-a agertu ziren. Oro har, Japoniako konputagailu horien kalkulu-abiadura gorenak oso handiak ziren, baina hasiera-denborak (start-up) oso luzeak ziren (gogoratu: bektoreen luzera minimoarekin erlazionatuta dago hasiera-denbora). Ondorioz, askotan X-MP-k baino "motelagoak" ziren.

1988a da Cray-Y-MP konputagailuaren urtea, X-MP-ren eboluzio "naturala" zena (8 prozesadore, erloju azkarragoa). Cray etxeak aurrera jarraitu zuen, eta C90-a —16 prozesadore, 240 MHz (eta 15 milioi dolar)— eta, geroxeago, T90-a sortu zituen. Era berean, beste bat ere merkaturatu zuten, J90-a, CMOS bertsio bat, merkeagoa (miloi bat dolar).

Cray etxeak Cray Inc. SV1(ex) izeneko bektore-konputagailua merkaturatu zuen gero, J90 eta T90 konputagailuen ondorengoa, non dagoeneko CMOS teknologia erabili zen (eta ECL garestia albo batera utzi, lehenago Fujitsu eta NEC etxeek egin zuten moduan). Memoria partekatuko multiprozesadore bat da, konfigurazio maximoan 128 bektore-prozesadore onartzen dituena. Prozesadore bakoitza 450 MHz-ekoa da, eta 1,8 Gflop/s-ko abiadura lor dezake. Aipatu behar den beste ezaugarri bat eskalarretarako eta bektoreetarako erabiltzen den 256 kB-ko cache partekatua da. Cray etxeko aurreko diseinuetan ez zen cachea erabiltzen, baina azken honetan memoria-sistemaren abiadura ez da nahikoa prozesadoreak lanpetuta mantentzeko (memoriaren eta prozesadorearen abiaduren arteko gap ohikoa).

Horrez gain, Fujitsuk VPP5000 konputagailua aipatu daiteke, aurreko VPP700 konputagailuen ondorengoa: erloju azkarragoa (300 MHz) eta 16 multiply-and-add motako vector pipe ditu. Teorian, beraz, prozesadore bakoitzak 9,6 Gflop/s-ko abiadura lor dezake. Prozesadore eskalarrak segundoko 1,2 Gflop exekuta ditzake. Konfigurazio zabalenean, 128 prozesadoreko memoria banatuko multiprozesadore bat da, non puntutik punturako komunikazioa 1,6 GB/s-ko abiaduraz egiten den. Komunikazio-sarea full distributed crossbar bat da.

Azkenik, Japoniako beste makina bat: NEC SX-5/16A konputagailua, memoria banatuko bektore-multiprozesadorea ere. Hauek ziren ezaugarri nagusiak: 313 MHz-eko erlojua, 16 bektore-unitate, 10 Gflop/s prozesadore

1.6. LABURPENA ▪ 67 ▪

bakoitzeko. Prozesadore horren SX-6 bertsioa izan zen Earth Simulator superkonputagailuaren muina.

Aipatutako makina horiek guztiak azkarrenak izan dira beti beren garaian, baina, era berean, oso garestiak ere. Mikroprozesadoreen eboluzioak, eta, oro har, paralelismoaren erabilerak, "bazterrean" utzi ditu makina horiek azken urteetan, eta, etorkizun hurbilean, gero eta leku gutxiago izango dute, segur aski, kalkulu zientifikoko munduan. Baina, horretarako, ikasi egin beharko dugu nola programatu eta erabili eraginkorki prozesadore anitzeko sistemak, haien balizko kalkulu-abiadura itzela erdiesteko.

Nolanahi ere, ohikoa da oraingo prozesadore (super)eskalarretan bektoreak prozesatzeko agindu bereziak izatea (SIMD motakoak), bektore-konputagailuetatik heredatutakoak; adibidez, hitz baten 64 bitak 8 biteko 8 hitzetan banatzen dira, eta bektore txiki bat gisa prozesatzen dira, MUL/ADD eragiketa kateatuak eginez.

Gero eta gehiago, bektore-prozesadoreak multiprozesadoreen nodo berezitu gisa ageri dira. Izan ere, kalkulu paraleloko etorkizuna MPP (massive parallel processors) izeneko sistemetan dago; konputagailu horietan, milaka prozesadore lotzen dira abiadura handiko komunikazio-sare baten bidez, eta problema jakin bat prozesadore guztien bidez ebazten da. Sare horren barruan, prozesadore batzuk espezializatuta daude eragiketa edo kalkulu mota jakin batean, esaterako, bektore-kalkuluan.

Dena den, 2002ko ekaineko top500 zerrendan (munduko 500 konputagailu azkarrenen zerrenda, urtean bitan argitaratzen da) "ezustea" gertatu zen. Azken urteetako joeraren aurka, bektore-konputagailu bat ageri zen lehen posizioan, lehen aipatu dugun Japoniako Earth Simulator konputagailua, 5.120 bektore-prozesadorerekin (NEC SX-6). Rmax = 36 Teraflop/s-ko kalkulu-abiadura lortu zituen (bigarrena, une horretan, ASCI White superkonputagailua zen, 8.192 prozesadorekoa eta 7,2 Teraflop/s-koa). Aipatutako top500 zerrendan (2002ko ekaina), beste 41 bektore-konputagailu ziren.

2009an, bektore-superkonputagailu horren bertsio berria dago (1.280 NEC SX-9 prozesadore, 3,2 GHz, 350 milioi transistore) eta 122,4 TF/s-ko kalkulu-abiadura lortu du. CPU bakoitzak unitate supereskalar bat (4 gradukoa) eta bektore-unitate bat ditu. Bektore-unitateak 256 osagaiko 72 bektore-erregistro ditu, eta bektore-eragiketak (+, ×, /, logikoak, maskarak, eta LV/SV) egiteko 8 multzo (pipe) desberdin. Txip bakoitzak 102,4 GF/s-ko kalkulua abiadura maximoa lor dezake.

▪ 68 ▪ 1. kapitulua: BEKTORE KONPUTAGAILUAK

Earth Simulator berria top500 zerrendako 31. da (2009ko abendua), baina

bektore-arkitektura bakarra da dagoeneko; dirudienez, desagertzear dagoen arkitektura da.

Bukaeran, top500 zerrenda errepasatuko dugu, hor agertzen diren

makinak, arkitekturak eta azken joerak analizatzeko.

▪ 2 ▪

Konputagailu Paraleloak (oinarrizko kontzeptuak)

2.1. SARRERA

Prozesadoreak gero eta azkarragoak badira ere, prozesadore bakar batekin lor daitekeen kalkulu-abiadura ez da behar adinakoa hainbat eta hainbat problema ebazteko. Abiadura handiagoak (bi... sei ordena handiagoak) lortzeko, estrategia desberdina beharko genuke, eta estrategia hori paralelismoa da. Paralelismo hitzarekin honako hau adierazi nahi dugu: programa baten exekuzioa hainbat prozesadoreren artean banatzen da, eta prozesadoreek paraleloan, batera, lan egiten dute.

Paralelismo mota asko erabil daitezke. Esaterako, programa baten aginduen exekuzioa segmentatzen denean, agindu-mailako paralelismoa (ILP) erabiltzen da: une jakin batean, agindu asko daude exekuzioan, batera, fase edo urrats desberdinetan. Bestalde, datuetan ere ustia daiteke paralelismoa; paralelismo mota horren adibide arrakastatsuena bektore-prozesadoreak dira. Baina, aurreko kasu guztietan (edo beste batzuetan: VLIW...), programaren kontagailu bakar bat erabiltzen da, hau da, programa

▪ 70 ▪ 2. kapitulua: KONPUTAGAILU PARALELOAK (oinarrizko kontzeptuak)

bakar bat exekutatzen da, kontrol-unitate bakar baten mende. Hurrengo kapituluetan, programa-mailako paralelismoa aztertuko dugu, hau da, nola erabili P prozesadore programak azkarrago exekutatzeko.

Gogora dezagun sarreran aurkeztu dugun Flynn-en sailkapena: ▪ SISD konputagailuak: datu- eta agindu-jario bakarra exekutatzen da,

prozesadore (super)eskalar bakar batean. Paralelismoa unitate funtzionalen aldi bereko erabileran ematen da, aginduen exekuzio segmentatua dela eta.

▪ SIMD konputagailuak: agindu-jario bakarra (programaren kontagailu bat), baina datu-jario asko exekutatzen dira. Memoriaren erabileraren arabera, bi familia bereizi dira: bektore-prozesadoreak (memoria partekatua), eta memoria banatuko array processors izeneko konputagailuak.

▪ MIMD konputagailuak: datu- eta agindu-jario asko exekutatzen dira aldi berean. Benetako paralelismoa, beraz, prozesu (edo hari) asko exekutatzen baitira, aldi berean. Makina horiek izango ditugu ikasgai aurrerantzean.

Horri ekin baino lehen, zehaztapen bat egin nahi dugu. Arlo bat baino gehiagotan erabil daitezke P prozesadore batera, eskuarki helburu desberdinekin:

• Konputagailu-sareak antolatzeko (LAN, WAN...). P erabiltzailek programa bana exekutatzen dute, batera, baina programa horiek independenteak dira (agian, noizbehinka, datu-transmisioren bat egiten da batetik bestera). Programa bakoitza eredu sekuentzialaren arabera exekutatzen da.

• Hutsegiteekiko tolerantzia lortzeko. Aplikazioen arabera, hainbat modu daude hutsegiteei aurre egiteko. Esaterako, programen exekuzioa errepikatu egin daiteke P prozesadoretan, dela emaitzei buruzko fidagarritasun handiena izateko —egoera berezietan, satelite batean esaterako—, dela konputagailu bat matxuratzen denean beste bat erabili ahal izateko (high reliability) —banku batean, adibidez—. Zenbait kasutan, prozesadore bakar batek eskaintzen du zerbitzu jakin bat, eta beste bat (edo gehiago) zain dago, lehenbizikoaren funtzionamendu egokia egiaztatzen; hutsa detektatutakoan, bere gain hartuko du zerbitzua (high availability).

• Programa baten P kopia aldi berean exekutatzeko, datu desberdinak erabiliz. Adibidez, prozesu fisiko baten hainbat simulazio

2.2. DM-SIMD KONPUTAGAILUAK ▪ 71 ▪

independente egiteko, throughput edo emaria hobetzeko. Edo, zerbitzarietan, eskaera asko batera eta modu orekatuan zerbitzatu ahal izateko (adibidez, datu-base batean).

• Programa bat P aldiz azkarrago exekutatzeko edo, denbora berean, datu-egitura handiagoak prozesatzeko (high performance). Hau da interesatzen zaigun paralelismo mota. Aurrekoen aldean, desberdintasun nagusia komunikazioan dago. Paraleloan exekutatzen diren prozesuak ez dira independenteak, eta informazioa trukatuko dute elkarren artean exekuzioan zehar, zenbait kasutan maiztasun handiz. Gainera, komunikazio-eragiketak oso denbora laburrean bete behar dira (mikrosegundotan), exekutatzen ari den aplikazioaren parte direlako. Arkitektura askotarikoak aurki ditzakegu arlo honetan, parametro asko kontuan hartuz: prozesadore kopurua, prozesadoreen arteko uztartze-maila (komunikazioa sarritan edo noizbehinka bakarrik egiten da), prozesadoreen ahalmena eta konplexutasuna, kontrol- eta sinkronizazio-mekanismoak, atazen tamaina (alea)...

Hurrengo kapituluetan, exekuzio-eredu berri horren ezaugarri eta arazo nagusiak aztertuko ditugu, baina, hasi baino lehen, egokia da arkitektura horien kontzeptu eta termino nagusiak azaltzea.

2.2. DM-SIMD KONPUTAGAILUAK

Memoria partekatuko SIMD konputagailuak, bektore-konputagailuak, alegia, aztertu ditugu aurreko kapituluan. Liburu honen helburuetatik kanpo badaude ere, merezi du aipatzea, laburki, beste SIMD konputagailuen, hots, memoria banatuko (DM = distributed memory) SIMD konputagailuen ezaugarri behinenak. Makina horiei array processors edo prozesatze-matrizeak deritze.

Aipatu bezala, datu-paralelismoa ustiatzen da SIMD konputagailuetan: agindu bakar batekin (array-etan, agindu bera prozesadore guztietan) hainbat datu prozesatzen da.

Kontrol-prozesadorea

Front-end konputagailua

Pr + M + S/I

Komunikazio-sarea

Prozesatze-matrizea (array)

▪ 72 ▪ 2. kapitulua: KONPUTAGAILU PARALELOAK (oinarrizko kontzeptuak)

Hauek dira, oro har, ezaugarri behinenak:

• Prozesadoreak: hainbat aukera badago ere, eskuarki prozesadore asko eta oso sinpleak erabiltzen dira; esaterako, bit bateko 1.024 prozesadore (merkeak, nahiz eta oso azkarrak ez izan). Serieko prozesadoreak izanik, edozein tamainatako datuak prozesa ditzakete, exekuzio-denbora datuen tamainarekiko proportzionala izanik.

• Kontrola: kontrol zentralizatua erabiltzen da. Prozesadore guztiek agindu bera eta une berean exekutatzen dute (lock-step), datu desberdinen gainean. Behar izanez gero, maskara batzuen bidez kontrolatu daiteke eragiketa bat zein prozesadoretan (azpimultzo batean) exekutatuko den.

Kontroleko prozesadore berezi batek banatzen ditu aginduak, eta sistema osoa kontrolatzen duen front-end konputagailu nagusiarekin komunikatzen da. Bektore-prozesadoreetan gertatzen den moduan, prozesatze-matrizean exekuta ezin daitekeen kodea kontrol-prozesadorean zein prozesadore nagusian exekutatuko da, seriean.

Eskuarki, matrizeko prozesadoreek sarrera/irteera eragiketak ere egiten dituzte, eta hori oso egokia da datuak modu intentsiboan prozesatu behar dituzten aplikazioetarako.

• Egitura: array edo matrize bat osatzen da prozesadoreekin, 2 edo 3 dimentsiotan. Komunikazio-sare bat erabiltzen da prozesadoreen arteko komunikazioa gauzatzeko; ohiko sareak mailak, toruak, eta antzekoak dira. Oro har, eta eraginkortasuna hobetzeko asmoz, sarea hainbat "planotan" (azpisare) banatzen da: datuetarako, kontrolerako...

• Aplikazioak: konputazio-egitura hauek egokiak dira aplikazio jakin batzuetarako; esaterako, seinale- edo irudi-prozesamendurako, edo zenbait simulazio motatarako (Montecarlo...). Memoria-espazioa bakarra izan arren, sistemaren eraginkortasuna hobea da komunikazio "lokalak" (auzokoekin bakarrik) erabiltzen dituzten aplikazioetan (aipatu ditugunetan, esaterako).

Prozesatzen diren datu-egituren erregulartasuna eta exekutatu ohi diren eragiketak direla medio, memoria-atzipenak eta komunikazioak "permutazioak" deitzen diren patroi jakin ezagunen arabera egin ohi dira.

ILLIAC IV, Solomon, CM1, BSP, DAP, Quadrics Apemille, prozesadore sistolikoak... izan dira eredu horretako konputagailu ezagunenak. Duela urte

2.3. MIMD KONPUTAGAILUAK ▪ 73 ▪

batzuk makina hauek garrantzitsuak izan baziren ere, batik bat aipatu ditugun aplikazioetarako, SIMD motako konputagailuak desagertu dira merkatutik. Oraingo sistema paraleloak, beraz, MIMD motako arkitekturakoak dira. Ikus ditzagun, bada, horien ezaugarri nagusiak.

2.3. MIMD KONPUTAGAILUAK

Aipatu dugunez, MIMD motako konputagailuetan, aplikazioak hainbat prozesutan banatzen dira, eta prozesu horiek paraleloan exekutatzen dira P prozesadore erabiliz. Konputagailuaren egituraren ikuspuntutik, hau da erantzun behar dugun lehenengo galdera: nola antolatzen dira P prozesadoreak? Jakina, erantzuna nahi dugun bezain zabala izan daiteke; hala ere, eta SIMD motako konputagailuetan ikusi dugun modu berean, bi dira eredu nagusiak, memoriaren erabileraren arabera: memoria partekatua eta memoria banatua edo pribatua.

2.3.1. Memoria partekatua (shared memory)

Memoria partekatuko sistema paraleloetan, prozesadore guztiek partekatzen dute sistemaren memoria osoa; hots, prozesadore guztiek helbide-espazio bera erabiltzen dute: hitz baten helbidea bakarra eta bera da prozesu guztietan.

Hori dela eta, prozesuen arteko komunikazioa oso erraz egin daiteke, aldagai partekatuak erabiliz. Hala, datu bat prozesu batetik beste batera pasatzeko, nahikoa da datu hori memoriako posizio jakin batean idaztea, bigarrenak hortik irakurri ahal izango baitu.

P0

M0

Mm–1

P1

Pp–1

Prozesadoreak (+ CM)

Komunikazio-sarea

Memoria nagusia

S/I-ko sistema

▪ 74 ▪ 2. kapitulua: KONPUTAGAILU PARALELOAK (oinarrizko kontzeptuak)

Prozesadoreak eta memoria-moduluak konektatzeko, sare bat erabili behar da. Sarerik sinpleena busa da; oso ondo ezagutzen da eta ez da zaila kontrolatzeko. Zoritxarrez, denboran partekatzen den sarea da busa: ez ditu bi "komunikazio" batera onartzen. Hori dela eta, arazo bat ager daiteke: busera konektatuta prozesadore asko badago, litekeena da busak onar dezakeen trafiko-maila maximoa gainditzea, eta, ondorioz, erantzun-denborak luzeak izatea. Beste sare batzuk ere erabil daitezke, eta aurrerago analizatuko ditugu sare horiek. Une honetan, eta sinplifikatzeko, komunikazio-sarea bus bat izango da.

Arkitektura mota horri askotan multiprozesadore deritzo, bai eta SMP (symmetric multiprocessor), UMA (uniform memory access) edo sistema paralelo oso uztartua (tightly coupled) ere. Memoria atzitzeko erabiltzen den sarea dela eta, SMP sistemetako prozesadore kopurua txikia da —adibidez, 32raino prozesadore— eta, ondorioz, paralelismo-maila mugatua da.

2.3.2. Memoria banatua edo pribatua (distributed memory)

Bigarren ereduan, irudian ikus daitekeen moduan, prozesadore bakoitzak memoria pribatu bat erabiltzen du. Helbide-espazioa ez da, beraz, komuna; helbide guztiak lokalak dira eta bertako memoriari dagozkio. Prozesuen aldagai guztiak pribatuak dira. Beraz, prozesuen arteko komunikazioa ezin da egin, aurreko kasuan egin den moduan, memoria-posizioa komunak erabiliz.

Horregatik, komunikazioa mezu-ematearen bidez egiten da, komunikazio-sarea erabiliz. Pi-tik Pj-ra datuak pasatu behar direnean, mezu bat antolatzen da informazio horrekin, eta sarera bidaltzen da; sareko

Nodoak: Prozesadorea (+ CM) + Memoria nagusia + S/I + Komunik. kontr.

Komunikazio-sarea

P0

M

S/I

K

Pp–1

M

S/I

K

2.3. MIMD KONPUTAGAILUAK ▪ 75 ▪

kontrolagailuek (mezu-bideragailuek) birtransmitituko dute mezua helburura heldu arte.

Eredu honen helburuetako bat paralelismo masiboa eskuratzea da, hau da, prozesadore kopuru handia izatea. Horregatik, ez da bus bat erabiltzen prozesadoreen arteko komunikazioa erdiesteko, eraginkorragoak diren beste sare batzuk baizik: hiperkuboak, bi eta hiru dimentsioko mailak eta toruak, arbolak... Geroago aztertuko ditugu sare horiek.

Egitura horri multikonputagailu deitu ohi zaio, bai eta MPP (Massively Parallel Processors), sistema gutxi uztartua (loosely coupled)... ere.

2.3.3. Memoria logikoki partekatua baina fisikoki banatua (distributed shared memory)

Memoria-espazioa bakarra denean, errazagoa izan ohi da aplikazioak programatzea, baina memoria bera gatazka-gune bihurtzen da, zentralizatuta baitago: busa (memoria) erabili ahal izateko itxaron behar den denbora luzea izan daiteke, prozesadore guztiek erabili behar baitute memoria "bakarra". Memoria pribatua denean, ordea, memoria erabiltzeko gatazka horiek desagertu egiten dira (prozesadore bakoitzak bere memoria erabili behar du), baina prozesadoreen arteko komunikazioa zailagoa da, eta programazio-ereduak ere konplexuagoak dira.

Programen portaera analizatzen bada, erraz ikusten da prozesadoreek ez dutela memoria-espazioa modu homogeneoan erabiltzen, hau da, ez dituzte atzitzen memoria-posizio guztiak probabilitate berarekin. Horretan oinarrituta, beste eredu bat proposa daiteke, aurreko bien nahastea edo: memoria-espazioa partekatu egiten da, baina memoria banatuta dago. Eredu horri dagokion egitura fisikoa aurreko bigarren irudikoa da, baina memoria partekatua da eta prozesadore guztiek izango dute aukera edozein prozesadoretako memoria erabiltzeko.

Arkitektura hori erabiltzen denean, memoria hierarkikoki antolatzen da: bertako atzipenak, nodoko memorian egiten direnak, azkarrak izango dira, baina kanpokoak askoz motelagoak, komunikazio-sarea erabili beharko baita beste nodoetako memoria atzitu ahal izateko. Beraz, eraginkorra izateko, atzipen gehienak bertako memorian egin beharko dira, eta erabili prozesuen arteko komunikaziorako bakarrik beste prozesadoreetako memoriak.

Arkitektura mota honi DSM (Distributed Shared Memory), NUMA (Non-Uniform Memory Access), edo MPP ere deritzo.

▪ 76 ▪ 2. kapitulua: KONPUTAGAILU PARALELOAK (oinarrizko kontzeptuak)

2.3.4. Clusters, constellations... eta abar

Aipatu ditugun arkitekturak aukera nagusiak dira, baina haien arteko nahasteak gero eta ohikoagoak dira. Esaterako, oraingo superkonputagailu gehienetan, komunikazio-sarera konektatuta dauden nodoak ez dira prozesadore soilak, baizik eta SMP sistema txikiak (4-8 prozesadore, bus batean konektatuta); horrela, arkitektura mistoko sistema paraleloak lortzen dira: nodo bakoitzaren barruan, memoria partekatua da, baina nodoen artekoa pribatua da.

Bestalde, eta diseinu bereziko superkonputagailuek duten kostu itzela murriztu nahian, hardware sinple eta merkeko sistema paraleloak ageri dira merkatuan, indartsu: helburu orokorreko hainbat konputagailu, sare-teknologietatik eratorritako sareen bidez konektatuta. Oro har, sistema horiei cluster ("multzo" edo "talde") deritze. Cluster-a osatzeko, beraz, konputazio-nodo batzuk eta komunikazio-sare bat behar da (kudeaketa- eta programazio-softwareaz gain, jakina). Konputazio-nodoen eta komunikazio-sarearen kalitatearen arabera izango da cluster-aren eraginkortasuna. Kasurik sinpleenean, nodoak PC soilak dira eta komunikazio-sarea (Gigabit) Ethernet. Sistema horiei Beowulf deitu ohi zaie. Aukera merkeena da, noski, eta komunikazio asko eta maiz behar duten aplikazioetan ez dituzte kalkulu-abiadura handiak lortzen, baina "abiadura/kostu" erlazioa oso ona izan daiteke hainbat aplikaziotarako.

Cluster eraginkorragoak osatu nahi bada, konputazio-nodoak SMP sistemak izan daitezke, eta komunikazio-sarea ethernet hutsa baino sofistikatuagoa (Myrinet, Infiniband, Quadrics...); nodo bakoitzaren prozesadore kopurua cluster-aren nodo kopurua baino (askoz) handiagoa denean, constellation izena ere erabiltzen da.

Fabrikatzaile guztiek eskaintzen dituzte dagoeneko cluster motako sistemak haien katalogoetan (custom clusters), kalkulu-abiadura handia "arrazoizko" kostuaz lortzeko; gainera, nahi izanez gero, ez da zaila behe-mailako cluster bat sortzea PC solte batzuk erabiliz (commodity clusters).

Sistema paraleloaren egitura edo arkitektura dena delarik, antzeko arazoei

aurre egin behar diegu sistema horiek modu eraginkorrean erabili ahal izateko. Laburpen moduan, azter ditzagun, gaingiroki bada ere, arazo horiek.

2.4. ARAZOAK ▪ 77 ▪

2.4. ARAZOAK

Dela lehenengo aukerarekin, dela bigarrenarekin, MIMD konputagailuek arazo asko proposatzen digute ebazteko. Esaterako:

▪ Sistemaren kudeaketa. Hainbat prozesadorerekin (askotan hainbat konputagailu autonomorekin) egindako sistemak konputagailu bakar bat gisa agertu behar du erabiltzailearen aurrean. Horretarako, besteak beste, honako hauek beharko ditugu: sistema eragile bereziak, atazen kudeaketa-sistema egokiak, exekuzioa analizatzeko tresna berriak, segurtasun-kontrol aurreratuak... Gai garrantzitsuak dira guztiak, baina ez ditugu hemen tratatuko.

▪ Lan-banaketa. Badakigu nola banatu programa sekuentzial bat P prozesadoreren artean? Zenbait kasutan erraza izango da; esaterako, do i = 1,N {A(i) = A(i) + 1} begizta exekutatzeko, garbi ikusten da nola erabili konputagailu paraleloa: N prozesadore batera, bakoitza begiztaren iterazio bat exekutatzen, edozein. Jakina, iterazio guztiak independenteak direnez, ez dugu batere arazorik izango lan-banaketa egiteko. Baina hori ez da kasu orokorra, eta, askotan, oso zaila da algoritmo batek izan dezakeen paralelismoa azalaraztea; izan ere, kasu askotan, problema zaharrak ebazteko algoritmo berriak asmatu behar dira. Oro har, programazio paraleloa programazio sekuentziala baino zailagoa da.

Horrez gain, prozesadoreen arteko lan-banaketaren oreka (load balancing) ere mantendu behar da; bi prozesadoreen arteko lan-banaketa % 80 - % 20 gisa egiten bada, sistema ez da, inolaz ere, bi aldiz azkarrago joango, ataza luzeenak markatuko baitu programaren exekuzio-denbora. Lan-banaketa estatikoa —programa konpilatzen denean— zein dinamikoa —programa exekutatzen denean— izan daiteke. Aurrena sinpleagoa da eta ez dio gainkargarik gehitzen programaren exekuzioari, baina zailagoa da lan-oreka ziurtatzea; bigarren kasuak, berriz, konputazio-kostu handiagoa du, baina emaitza egokiagoak lortzen ditu zenbait kasutan, lan-orekari begira.

▪ Datuen koherentzia. Aldagai partekatuak erabiltzen direnean, aldagai horien kopiak egiten dira prozesadoreen cacheetan. Kopia horietako bat aldatzen bada, nola enteratuko dira gainerako prozesuek aldagaiaren balio berriaz? hau da, nola mantenduko dira datuak

▪ 78 ▪ 2. kapitulua: KONPUTAGAILU PARALELOAK (oinarrizko kontzeptuak)

"koherente"? Hurrengo kapituluetan ikusiko dugunez, soluzio desberdinak erabiltzen dira makinaren arkitekturaren arabera.

▪ Komunikazioa. Paralelismoaren arazo nagusietako bat prozesuen arteko komunikazioa da. Eta, horrekin batera, komunikazio-sarea (batik bat DSM edo MPP sistemetan). Izan ere, honela adieraz daiteke sistema paralelo batean programa bat exekutatzeko behar den denbora:

Tp = Texe + Tkom

non Texe exekuzio-denbora bera den eta Tkom komunikaziokoa. Exekuzio-denbora txikiagotu egiten da prozesadore kopurua hazten den neurrian (idealki, 1/P moduan), baina komunikaziokoa, aldiz, handiagotu egiten da. Irudi honetan, portaera hori ageri da (sinplifikatuta).

Irudian ageri denaren arabera, ez da beti komeni prozesu/prozesadore kopuru handia izatea; komunikazio-beharrak bertan behera utz ditzake abantaila guztiak. Beraz, oreka-puntua bilatu beharko da.

Badago komunikazio mota berezi bat: sinkronizazioa. Hainbat prozesadore sinkronizatzen dira, esaterako, ataza bat bukatu eta gero beste bati ekiteko. Sinkronizazio-prozedurek trafiko handia sor dezakete komunikazio-sarean, dela aldagai partekatuak erabiltzen direlako, dela sinkronizazio-mezu bereziak bidali behar direlako (maiz, prozesu guztiak batera).

Lan-banaketa eta komunikazioa kontuan hartuz, honako paralelismo mota hauek bereizi ohi dira:

• Ale xeheko (fine grain) paralelismoa: paraleloan prozesatzen diren atazak "txikiak" dira, eta haien arteko komunikazioa oso maiz gertatzen da, baina ez da informazio asko trukatzen komunikazio bakoitzean.

Prozesadore kopurua

Texe Tkom

Tp

2.5. SISTEMA PARALELOEN ERAGINKORTASUNA ▪ 79 ▪

• Ale larriko (coarse grain) paralelismoa: paraleloan prozesatzen diren atazak "handiak" dira, eta haien arteko komunikazioa gutxitan gertatzen da, baina, egiten denean, informazio asko trukatzen da.

2.5. SISTEMA PARALELOEN ERAGINKORTASUNA

(Amdahl-en eta Gustafson-en legeak)

Sistema paraleloen helburua programak P aldiz azkarrago exekutatzea da, P prozesadore erabiliz. Prozesadore bakarreko sistemen eta sistema paraleloen arteko konparazioak egiteko, bi parametro erabili ohi dira: azelerazio-faktorea (speed-up) eta eraginkortasuna (efficiency).

Azelerazio-faktoreak programa zenbat bider azkarrago exekutatu den adierazten du; beraz:

af = Ts / Tp

non Ts serieko exekuzio-denbora eta Tp paralelokoa baitira. Bestalde, eraginkortasuna honela definitzen da:

erag = af / P (maiz, ehunekotan)

hau da, balizko azelerazio-faktore maximoko ehunekoa.

Kasurik onenean, Tp = Ts / P izan daiteke, hau da, P prozesadore erabiliz, P aldiz azkarrago exekutatzen da programa; kasu horretan,

af = Ts / (Ts / P) = P erag = af / P = 1 (% 100)

Egoera ideala da hori, noski, eta, tamalez, arazo asko direla medio —lan-banaketa desorekatua, komunikazioa, sinkronizazioa...—, ohiko kasuetan ez dugu hori lortuko. Edonola ere, nahiz eta azelerazio-faktorea P izan ez, lortu beharko genuke azelerazio-faktorea lineala13 izatea prozesadore 13 Zenbait kasutan, azelerazio-faktore superlinealak lor daitezke, hau da, P baino handiagoak. Hori

ulertzeko, kontuan hartu behar dugu memoria, S/I-rako ahalmena eta abar ere gehitzen dela sistema paraleloetan. Esaterako, prozesadore bakar baten memorian kabitzen ez diren programa edo datuak, agian P prozesadoreetako memorian sartuko dira, eta, jakina, horrek ere exekuzio azkarragoak lortzeko laguntzen du.

▪ 80 ▪ 2. kapitulua: KONPUTAGAILU PARALELOAK (oinarrizko kontzeptuak)

kopuruarekin (edo, baliokidea dena, eraginkortasuna konstantea izatea, eta ez P-ren mendekoa); hau da, prozesadore kopurua bikoizten badugu, azelerazio-faktore bikoitza eskuratzea.

Programa guztiek ez diote, ordea, portaera horri jarraitzen, Amdahl-en legea dela medio. Bektore-prozesadoreetan gertatu zaigun legez, programa arruntak ezin dira ehuneko ehunean paraleloan exekutatu prozesadore guztiak erabiliz. Oro har, beti izango ditugu seriean (prozesadore bakar batean), edo prozesadore guztien azpimultzo batean, exekutatu beharko diren kode zatiak.

Adibide gisa, demagun kodearen frakzio bat, f, prozesadore guztiak erabiliz exekuta daitekeela, eta beste bat, 1–f, prozesadore bakar batean exekutatu behar dela. Kasu horretan, honela idatzi behar da exekuzio-denbora:

Tsp = f × Tp + (1–f) × Ts (oro har, ∑=

=P

i

sisp i

TfT

1

)

Lehen esan dugun moduan, kasurik onenean (arazoak kontuan hartu gabe) Tp = Ts / P izango da; beraz, honela geratuko zaigu speed-up edo azelerazio-faktorea:

af = Ts / Tsp = P / [f + P (1–f)]

Adibidez, P = 1.024 eta f = 0,98 badira, af = 47,7 besterik ez da izango. Irudian ageri den moduan, azelerazio-faktorea ase egiten da (asintota bat du 1/(1–f) balioan), eta oso urruti geratzen da portaera lineal idealetik.

2.5. SISTEMA PARALELOEN ERAGINKORTASUNA ▪ 81 ▪

Amdahl-en legeak dioenez, nahitaez seriean exekutatu behar den kodearen eragina izugarria da prozesadore kopurua handia denean. Legeak adierazten duena gauzatzen bada, zaila izango da azelerazio-faktore handiak lortzea. Aurreko adibidean ikusi dugunez, nahikoa da seriean exekutatu behar den frakzioa % 2 izatea azelerazio-faktorea balizko 1.024tik 47ra jaisteko (% 5 baino gutxiagora).

Hala ere, hainbat aplikaziotan lortzen diren azelerazio-faktoreak aurreikusitakoak baino askoz handiagoak dira. Non dago kontraesana? Amdahl-en legea sortzean, hipotesi hau kontuan hartu dugu: algoritmo jakin bat azkarrago exekutatzeko erabiltzen dira P prozesadoreak. Errealitatean, hala ere, tamaina handiagoko problemak exekutatzeko erabiltzen dira askotan P prozesadoreak, tamaina txikiagokoek behar zuten denbora berean. Esaterako, prozesadore gehiago erabiliz, simulazio-ziklo gehiago exekutatzen dira, edo analisi finagoak egiten dira datu gehiago kontuan hartuz; hots, exekuzio-denbora da konstante mantentzen dena, ez problemaren dimentsioa.

Problema baten tamaina handiagotzen den hainbat kasutan (esaterako, matrize handiagoak prozesatzeko), egiaztatu egin da, esperimentalki, seriean exekutatu behar den kode zatiaren exekuzio-denbora ez dela hazten, hots, konstante mantentzen dela. Horrek esan nahi du problemaren tamaina hazten denean f ere hazten dela (ez dela konstante mantentzen). Hori guztia dela eta, hauek dira azelerazio-faktorea lortzeko benetan konparatu behar diren bi aukerak:

problemaren tamaina konstantea exekuzio-denbora konstantea

(1–f) Ts f Ts

f Ts × P (1–f) Ts

(1–f) Ts f Ts (1–f) Ts f Ts / P

paraleloan

problema-tamaina handiagoa

prozesadore bat

P prozesadore

seriean exekutatu behar den zatia

paraleloan exekuta daitekeen zatia

paraleloan

▪ 82 ▪ 2. kapitulua: KONPUTAGAILU PARALELOAK (oinarrizko kontzeptuak)

Beraz, exekuzio-denbora konstantea denean, hau gertatzen da:

Ts = (1–f) Ts + f Ts P Tp = (1–f) Ts + f Ts = Ts → af = Ts / Tp = (1–f) + f P

Azelerazio-faktorerako lortu dugun adierazpide horri Gustafson-en legea

deritzo. Azelerazio-faktorea lineala da P-rekiko, eta horrek ziurtatzen du, neurri batean, balio handiak lortuko direla. Esaterako, aurreko adibidean, P = 1.024 eta f = 0,98, hau da lortzen den azelerazio-faktorea: af = 1.003,5.

Konparazio baterako, irudi honetan aurreko bi azelerazio-faktoreak erkatzen dira, Amdahl-ena eta Gustafson-ena, f = 0,9 den kasurako.

Errealitatean, aplikazio askoren azelerazio-faktoreak bi mutur horien

artean kokatuko dira. Hurrengo kapituluetan, MIMD sistema paraleloak modu eraginkorrean

erabiltzeko ebatzi behar diren arazoetako batzuk analizatuko ditugu, hala nola datuen koherentzia (SMP zein DSM sistemetan), prozesuen arteko sinkronizazioa, sistemaren kontsistentzia-eredua, komunikazio-sarea eta begiztak paralelizatzeko estrategiak. Azken kapituluan, kalkulu-abiadura handiko sistema paraleloen merkatua eta adibide esanguratsuenak, eta programazio-tresna nagusiak (OpenMP eta MPI) aurkeztuko ditugu.

▪ 3 ▪

Datuen Koherentzia SMP Konputagailuetan

3.1. PROBLEMAREN NONDIK NORAKOA ETA KONTZEPTUEN BERRIKUSPENA

Memoria-sistemaren egiturak eta funtzionamenduak eragin zuzena du prozesadoreek lor dezaketen exekuzio-abiaduran. Izan ere, memoria nagusiaren erantzun-denbora (latentzia) prozesadorearena baino luzeagoa da beti, eta, gainera, abiadura-diferentzia hori gero eta handiagoa da. Horregatik, datuak (eta aginduak) ahalik eta azkarren eskuratu ahal izateko, memoria hierarkikoki antolatzen da: erregistroak / barne-cachea / kanpo-cachea / memoria nagusia / (diskoa...). Maila bakoitza hurrengo mailaren azpimultzo bat da. Erregistroak azkarrenak dira, baina haien edukiera txikia da (64 biteko 128 erregistro, esaterako). Beste muturrean, memoria nagusia dago; edukiera handia da (adibidez, 2 GB edo gehiago), baina atzipen-denbora askoz luzeagoa da (adibidez, 50 ns).

▪ 84 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

Memoria-hierarkiaren funtsa datuen eta aginduen erabileran datza, erabilera ez baita zorizkoa. Ezaugarri hori memoria-atzipenen batez besteko latentzia laburtzeko aprobetxa daiteke, baldin eta ustez prozesadoreak erabiliko dituen datuak (aginduak) memoria azkarrenera eramaten badira erabili behar diren baino lehen.

Hori da, beraz, cache memoriaren funtzioa: ustez "laster" eta "gehien" erabiliko diren datuak (eta aginduak) kargatzen dira cache memorian (datu-cachean eta agindu-cachean), haren erantzun-denbora memoria nagusiarena baino 5-10 aldiz txikiagoa baita. Hori dela eta, memoria nagusiko datu-bloke14 batzuk datu-cachean ere izango dira; hau da, datuen kopiekin lan egingo du prozesadoreak.

Datuen kopiekin lan egiten denez, arazo bat ageri da memoria partekatuko multiprozesadoreetan: ziurtatu egin behar da prozesadoreetako cacheetan errepikatuta egon daitezkeen datu-blokeen edukia berdina dela; hots, koherenteak mantendu behar dira datuen kopiak. Hori egin ezean, multiprozesadore baten prozesadoreek ezin izango dituzte aldagaiak partekatu, inoiz ez baitira seguru izango haien balioez.

3.1.1. Datuen koherentzia prozesadore bakarreko konputagailuetan

Datuen koherentzia, berez, prozesadore anitzeko sistemetako arazoa izan arren, prozesadore bakarreko sistemetan ere ageri da, kasu horietan ere datuen kopiak erabiltzen direlako: bi kopia, hain zuzen ere, cachean bata eta memoria nagusian bestea15. Dena den, arazoa ez da hain larria, kopia horien aldaketak prozesadore bakarraren kontrolpean daude eta.

Cacheko hitz bat idatzi behar denean, zer egin behar da hitz hori duen datu-blokearen bi (cacheko eta memoria nagusiko) kopiekin? Hauek dira ohiko bi idazketa-politikak:

▪ Write-through (WT): bi kopiak eguneratzen dira, cachekoa zein memoria nagusikoa. Hala, memoria-sistema koherentea da une oro,

14 Blokea memoria nagusiaren eta cachearen arteko transferentzia-unitatea da, eskuarki memoria

nagusiaren tartekatze-mailarekin erlazionatua. Beraz, ez da hitz bakar bat, ondoz ondoko memoria-posizioetako hitz multzo bat baizik; ohikoak dira, esaterako, 64 byteko blokeak (32 biteko 16 hitz edo 64 biteko 8 hitz). Ingelesez line (lerro) ere deitzen zaio.

15 Oraingo prozesadoreetan, cache memoria ere bi (edo hiru) mailatan dago banatuta; beraz, datu-bloke baten kopiak hiru (edo lau) izan daitezke.

3.1. PROBLEMAREN NONDIK NORAKOA ETA KONTZEPTUEN BERRIKUSPENA ▪ 85 ▪

baina, ordainean, idazketa (ST) guztiak MNan ere egin behar dira, eta horrek denbora gehiago beharko du, MNa "motela" baita.

▪ Write-back (WB): cachean dagoen kopia bakarrik eguneratzen da, eta balio zaharra uzten da memoria nagusian. Helburua memoriako atzipen kopurua, eta, beraz, idazketen latentzia eta buseko trafikoa gutxiagotzea da; oraingo konputagailuetan gehien erabiltzen den estrategia da.

Kontuz! sistema ez da koherente mantentzen (datuen bi kopiak ez dira berdinak). Beraz, noiz eguneratzen da MNko informazioa? bada, eskuarki datu-blokea cachetik kendu behar denean (ordezkapena dela eta, esaterako). Datu-blokeak kudeatzeko eta informazio baliagarria non dagoen jakiteko, zenbait kontrol-bit erabiltzen dira cacheko direktorioan, eta haien bidez blokeen egoerak zehazten dira. Nahikoa da bi bitekin: valid, dagoen informazioa erabilgarria dela adierazteko; eta dirty, blokeko daturen bat aldatuta dagoela markatzeko.

Lehen esana dugu prozesadorea dela kopiak aldatzeko ahalmena duen

bakarra, eta horrek asko errazten du kopien kudeaketa, baina hori ez da beti egia, sarrera-eragiketa bat egiten denean (DMAren bidez, esaterako) kontrolagailu jakin batek hartuko baitu memoria-sistemaren kontrola. Eragiketa horren ondorioz datu-bloke batzuk aldatuko direnez gero, zer egin behar da cachean egon daitezkeen bloke horien kopiekin? Kasu gehienetan, arazoa errotik desagerrarazten da, debekatu egiten baita sarrera/irteerako aldagaiak dituzten datu-blokeak cachera eramatea (atzipen guztiak MNan egiten dira); bestela, sistema eragileak hartu beharko du bere gain datuen koherentzia mantentzeko ardura (cachea husteko, flush). Nolanahi ere, idazketa horiek oso gutxitan egin ohi dira ("ohiko" idazketekin alderatuta).

3.1.2. Datuen koherentzia memoria partekatuko multiprozesadoreetan (SMP)

Memoria partekatuko multiprozesadoreetan, koherentzia-arazoa larriagoa da. Prozesuen arteko komunikazioa gauzatzeko, aldagai partekatuak erabiltzen dira. Prozesadoreek cache memoria bana izango dute, eta, beraz, datu-bloke baten balizko kopiak ez dira 2 bakarrik izango (oro har, memoria-hierarkiari dagozkionak), askoz gehiago baizik; P prozesadoreko sisteman P+1 kopia izan daitezke: P kopia cacheetan eta beste bat memoria nagusian.

▪ 86 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

Gainera, eta hau da arazoaren muina, edozein prozesadorek aldatu (idatzi) egin ditzake, bakoitzak bere cachean, partekatzen diren datu-blokeak. WB eta WT idazketa-politikak baliagarriak dira cachearen eta memoria nagusiaren arteko koherentzia mantentzeko prozesadore bakarreko kasuan; multiprozesadore batean, ordea, zer egin behar da beste cacheetan egon daitezkeen balizko kopiekin? Nola jakin "urrutiko" prozesadore batek aldatu duela datu-bloke bat, eta, ondorioz, cachean daukagun kopia ez dela dagoeneko egokia? Jakina, partekatzen eta aldatzen diren datuekin bakarrik izango ditugu koherentzia-arazoak; bloke pribatuekin, arazoa prozesadore bakarrekoa bezalakoa da, definizioz.

Lehen aipatu dugun moduan, arazoa desagerrarazi egiten da, baldin eta partekatzen diren aldagaiak (esaterako, prozesadoreen arteko komunikazioa gauzatzeko erabiltzen direnak) cacheetara ez eramatea erabakitzen bada (beraz, kopiak ez egitea). Hala ere, erabaki horrek eragin latza izango du sistemaren errendimenduan. Partekatuko bloke horiek asko erabiltzen badira, memoria nagusira jo beharko da behin eta berriz, trafiko handia izango da prozesadoreak lotzen dituen komunikazio-sarean (bus bat, esaterako), memoria atzitzeko denbora luzatuko da (atzipen-gatazkak direla medio), eta programen exekuzio-abiadurak behera joko du. Ikus adibide hau.

Multiprozesadore baten busaren transferentzia-abiadura 1 GB/s da, eta erlojua 800 MHz-ekoa da. Agindu bat zikloko exekutatzen dute prozesadoreek, eta aginduen % 2 partekatuko aldagaien irakurketak edo idazketak dira (LD/ST aginduak). Datuak 8 bytekoak dira. Zenbat prozesadore konekta daitezke busera berau ase gabe, aldagai partekatuak memoria nagusian uzten badira?

Segundo bakoitzean, 800 106 ziklo × 0,02 agindu (LD/ST) × 8 byte = 128 MB atzitu behar dira memorian, prozesadore bakoitzeko, datu partekatuak bakarrik kontuan hartuz! Beraz, 8 prozesadorek 1.024 MB/s-ko trafikoa sortuko dute aldagai partekatuak atzitzeko, busak onar dezakeen trafiko maximoa alegia.

Nahitaez, datu-blokeen kopiak izatea eta aldatzea bermatzen duen

estrategiaren bat behar dugu (tarteko irtenbidea litzateke prozesadore guztietarako cache partekatua erabiltzea, baina antzeko arazoak aurkituko genituzke). Ondo dakigunez, cache memoria (kopiak, beraz) erabiltzeak bi hobekuntza nabarmen dakarzkigu: buseko trafikoa zein atzipen-latentzia gutxiagotu egiten dira.

3.1. PROBLEMAREN NONDIK NORAKOA ETA KONTZEPTUEN BERRIKUSPENA ▪ 87 ▪

3.1.3. Partekatze faltsua

Partekatzen eta aldatzen diren aldagaiekin gertatzen da koherentzia-arazoa. Aldagaiak pribatuak badira, cache bakar batean egongo dira (izatekotan), eta, beraz, arazoa prozesadore bakarreko sistemetako bera izango da.

Cachearen edukiaren kontrola, datuen koherentziarena barne, blokeka egiten da, ez hitzez hitz: datu-blokeak kargatzen dira, kentzen dira, baliogabetzen dira, eta abar. Hori dela eta, datu-bloke bat bi prozesadoreko cacheetan egon daiteke, nahiz eta bi prozesadore horiek blokearen inongo aldagairik partekatu ez. Adibidez,

Lau hitzeko datu-bloke bat

X Y Z T

Hau da, prozesadore bakoitzeko aldagaiak pribatuak badira ere, datu-bloke berean daude, eta, ondorioz, bloke hori partekatu egin behar da, eta koherentzia-eragiketetan parte hartuko du. Hori gertatzen denean, partekatze faltsua (false sharing) dagoela esaten da. Partekatze faltsuaren eragina arintzeko, egoki banatu behar dira aldagaiak memorian (eta, aukera badago, ona da datu-blokeak oso handiak ez izatea).

3.1.4. Koherentziaren definizioa

Memoria-sistema koherentea da, baldin eta aldagai bat irakurtzean aldagai horretan idatzitako "azken" balioa lortzen bada. Definizio ez-formal horretan bi kontzeptu sartzen dira: bata, koherentzia bera —zer balio lortzen den— eta, bestea, kontsistentzia —noiz ikusiko den, beste prozesadoreetan, idatzitako balio berria—. Bigarren kontzeptua geroago aztertuko dugu.

Zehatzagoak izanik, memoria-sistemaren koherentzia hiru baldintza hauek betetzen badira ziurtatzen da:

1. Prozesadore bakar bat kontuan hartuta, irakurketa (LD) batek itzuli egin behar du beti prozesadore horrek aldagai horretan idatzitako azken balioa (tartean beste prozesadoreek aldagai hori aldatu ez

Pi prozesadoreko aldagaiak

Pj prozesadoreko aldagaiak

▪ 88 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

badute). Hau da, mantendu egin behar da LD eta ST aginduen arteko ordena (aldagai beraren gainean). Ez da multiprozesadoreen ezaugarri berezi bat, prozesadore bakar batekin ere bete behar baita.

2. Prozesadore guztiak harturik, Pi_rd_A irakurketak beti itzuli behar du azkeneko Pj_wr_A eragiketan idatzitakoa, baldin eta idazketa egin zenetik "denbora nahikoa" igaro bada. Hori da, gutxi gorabehera, koherentziaren definizioa: prozesadore guztiek "ezagutu" behar dituzte beste prozesadoreek egiten dituzten aldaketak.

3. Aldagai beraren gaineko idazketak (aldaketak) ordena berean ikusi behar dira prozesadore guztietan.

Memoria-sistema koherentea mantentzeko garatu diren estrategiak desberdinak dira sistemen arkitektura edo egituraren arabera. Aurreko kapituluan azaldu dugunez, bi dira egitura nagusiak memoria partekatuko konputagailuetan: SMP multiprozesadoreak —zenbait prozesadore, 8-16 gehienez, bus batean konektatuta (edo agian urrats anitzeko sare batean)—; eta DSM konputagailuak —prozesadore asko, eskuarki komunikazio-sare sofistikatuagoaz lotuta—. Lehenengo kasuan, prozesadoreak eta memoria konektatzeko bus bat erabiltzen denean, zelatari (snoopy) izeneko koherentzia-protokoloak erabiltzen dira oro har; bigarrenean, aldiz, direktoriotan oinarritutako koherentzia-protokoloak.

Kapitulu honetan, SMP sistemetan erabiltzen diren koherentzia-protokolo behinenak aztertuko ditugu (geroago, 7. kapituluan, koherentzia-direktorioak analizatuko ditugu).

3.2. ZELATATZE MOTAKO KOHERENTZIA PROTOKOLOAK

Aurreko kapituluan azaldu dugunez, SMP sistemetan memoria nagusia "toki batean kontzentratuta" dago, eta, oro har, prozesadoreek bus16 bat erabiltzen dute memoria atzitzeko. Multiprozesadore horietan, datuen koherentzia hardwareaz mantentzen da, snoopy (zelatari, begiluze) deitzen den gailuaren bidez, hain zuzen ere. Memoria eta prozesadoreak konektatzeko erabiltzen den sarea bus bat denez, memoria nagusiarekin 16 Bus baten eredu sinpleena erabiliko dugu: busa erabiltzeko eskaerak banan-banan prozesatzen dira,

eta ez zaio hurrengoari ekiten aurrekoa bukatu arte. Multiprozesadoreen busak, ordea, konplexuagoak izan ohi dira.

3.2. ZELATATZE MOTAKO KOHERENTZIA PROTOKOLOAK ▪ 89 ▪

egiten diren eragiketa guztiak "publikoak" dira; hots, edozein prozesadorek ikus ditzake besteok memoriarekin egiten dituzten eragiketak (LD / ST), bera ere busera konektatuta dago eta. Prozesadore bakoitzeko zelatariaren eginkizuna horixe bera da, hain zuzen: busa une oro zelatatzea, beste prozesadoreen eragiketak antzemateko, eta, dagokionean, kontrol-informazio berezia zabaltzeko. Lortzen duen informazioa erabiliz, koherentzia kontrolatzeko hardware berezi horrek kudeatu ahal izango ditu cachean dituen datu-blokeak.

Prozesadore batean datu-bloke bat (hitz bat) aldatzen denean, zer egin behar zaie beste prozesadoreetako cacheetan egon daitezkeen bloke (hitz) horren kopiei? Bi aukera ditugu:

▪ Baliogabetzea cacheetan dauden bloke horren gainerako kopia guztiak, eta, ondorioz, bakarra uztea, aldatu dena, hain zuzen ere.

▪ Eguneratzea blokearen kopia guztiak, aldatu den aldagaiaren balio berria prozesadore guztietara zabalduz.

Baliogabetzea Eguneratzea

Irudian, bi aukera horien adibide bat ageri da. Lehenbiziko kasuan, P1 prozesadoreak aldatu egiten du A aldagaiaren balioa bere cachean, 4tik 3ra. Aldaketa egiten du eta, horrekin batera, P2ko kopia baliogabetu egiten du (horretarako, INV izeneko kontrol-seinalea erabiltzen da); ondorioz, bloke17 horren kopia bakar bat geratuko da sisteman, berea. Bigarren kasuan, aldiz, P1 prozesadoreak egiten duen aldaketa beste prozesadorera zabaltzen da (BC —broadcast— kontrol-seinalea erabiliz), aldagaia balio berriarekin egunera dezan. Beraz, bloke horren bi kopiak mantentzen dira, biak berdinak noski. 17 Adi. Adibidean hitz bakar bat ageri bada ere, bloke batean hainbat hitz dago.

CM1 CM2

wr A,#3

MN

P1

P2

INV A

A = 4→3

A = 4

A = 4→3?

CM1 CM2

wr A,#3

MN

P1

P2

BC A,3

A = 4→3

A = 4→3

A = 4→3?

▪ 90 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

Baliogabetzea zein eguneratzea erabilita, memoria nagusia eguneratuko da, edo ez, idazketa-politikaren arabera: idazketa guztietan write-through (WT) erabiltzen bada, eta une jakin batzuetan bakarrik write-back (WB) erabiltzen bada.

Aipatu dugunez, blokea da koherentziarako unitatea; datuen koherentzia kontrolatzeko, datu-blokeei zenbait kontrol-bit gehitzen zaie cacheko direktorioan. Kontrol-bit horien bidez, egoera berriak definitzen dira blokeetarako. Cache bakoitzean, automata bat (zelataria) datu-blokeen egoeraz arduratuko da, bertako prozesadorearen eragiketak zein busean antzematen dituen gainerako prozesadoreenak kontuan hartuz.

3.2.1. Bloke baten egoerak, eta kontrol-seinaleak

Datuen koherentzia mantentzeko, bost egoera erabili ohi dira blokeetarako. Bi ezaugarri kontuan hartzen dira egoerak definitzeko: batetik, datu-blokearen kopia kopurua eta, bestetik, edukia koherentea (berdina) den, edo ez, memoria nagusian dagoen informazioarekin.

Hauek dira bost egoerak (adi! izenak desberdinak izan daitezke makinaren arabera):

I Baliogabea (invalid) Bloke bat I egoeran dago, baldin eta duen informazioak esanahirik ez

badauka; cachean egongo ez balitz bezala tratatuko da (hutsegite bat, beraz, edozein eragiketatan).

Horrez gain, (-) ikurra erabiliko dugu bloke bat cachean ez dagoela adierazteko; esaterako, bloke bat ordezkatzen denean ez da baliogabetzen, desagerrarazi egiten baizik. Beraz, bi kasuak, I edo (-), guztiz baliokideak dira.

E Esklusiboa (exclusive, reserved) Bloke bat E egoeran dago, baldin eta kopia bakarra bada

multiprozesadoreko cache guztietan, eta, gainera, memoria nagusian dagoen informazioarekin bat badator; hau da, koherentea da (berdina).

M Aldatua (modified, dirty, exclusive rd/wr) M egoeran dagoen blokea kopia bakarra da, baina ez dago eguneratuta

memoria nagusian. Aldatu egin da cachean une jakin batean, baina ez MNan (write-back erabili da, beraz).

3.2. ZELATATZE MOTAKO KOHERENTZIA PROTOKOLOAK ▪ 91 ▪

S Partekatua (shared, shared rd only) Badago (edo egon daiteke) bloke horren kopia gehiago

multiprozesadoreko beste cacheetan; kopia guztiak berdinak dira eta, eskuarki, koherenteak memoria nagusiarekin (memoria nagusiko informazioa eguneratuta dago, edo, ez badago, egongo balitz bezala tratatuko da).

O Jabea (owner, owned, shared dirty) Badago (edo egon daiteke) bloke horren kopia gehiago

multiprozesadoreko beste cacheetan, baina, elkarren berdinak izan arren, ez datoz bat memoria nagusian dagoen informazioarekin: ez dira koherenteak. Kopia bakar bat egongo da O egoeran, azken aldaketa jasan duena, eta kopia hori izango da, dagokionean (esaterako, ordezkatzen denean), memoria nagusian idatziko dena koherentzia mantentzeko. Gainerako kopiak, baldin badaude, S egoeran egongo dira (erne! ez dira koherenteak izango memoria nagusiko kopiarekin).

Bost egoera horiek definitzeko, nahikoak dira hiru bit. Esaterako:

balioduna (valid)

aldatuta (dirty)

partekatuta (shared) Egoera

0 – – I 1 0 0 E 1 0 1 S 1 1 0 M 1 1 1 O

Hasieran esan dugunez, aurreneko bi bitak prozesadore bakarreko sistemetan ere erabili behar dira (idazketa-politika WB bada); beraz, nahikoa da, oraingoz, bloke bakoitzeko kontrol-bit bat gehitzea direktorioan.

Cachean dauden datu-blokeen koherentzia mantentzeko, honako ekintza hauek kontuan hartu behar ditu bertako zelatariak:

1. Bertako prozesadoreko ekintzak.

PR: processor read Aldagai bat (datu-bloke jakin batean) irakurri behar da. Blokea cachean badago (asmatzea) ez da ezer egin behar; bestela (huts egitean), bloke hori irakurtzeko eskaera bidali behar da memoria-kontrolagailura, busaren bidez: BR (bus read).

▪ 92 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

PW: processor write Aldagai bat (datu-bloke jakin batean) idatzi behar da. Oro har, beste prozesadoreei abisatu behar zaie egindako eragiketaz, blokearen egoera haien cacheetan egokitu dezaten: INV (baliogabetu) edo BC (eguneratu), koherentzia-protokolo motaren arabera. Gainera, cachean hutsegitea gertatu bada, aldagaia ez dagoelako, datu-blokea eskatu behar da (BR).

2. Busean atzematen diren ekintzak (beste zelatariek bidalitako kontrol-seinaleak), beste prozesadoreetan gertatukoaren ondorio zuzena. Kontrol-seinaleen kopurua, izena eta abar, protokoloen gauzatzeen araberakoak dira. Honako hauek erabiliko ditugu:

BR: bus read Prozesadore batek hitz bat irakurri nahi izan du eta hutsegite bat sortu da, ez baitago haren cachean. Beraz, blokea eskuratu behar du, dagoen tokitik, eta kontrol-seinale hori sortu du horretarako (BR kontrol-busean eta helbidea helbide-busean). Prozesadore guztien zelatariek kontuan hartu beharko dute seinale hori, blokearen egoera egokitzeko (haien cacheetan badago).

INV: invalidate [ baliogabetze-protokoloetan ] Hitz bat idatzi da cache batean; ondorioz, gainerako cacheetan egon daitezkeen kopiak baliogabetu behar dira. INV kontrol-seinalea aktibatu behar da kontrol-busean, eta aldagaiaren helbidea eman helbide-busean. Kontrol-seinalea detektatzean, zelatari guztiek begiratu behar dute bertako cachearen direktorioan aldagai hori dagoen ala ez, eta, baldin badago, blokea baliogabetu egin behar dute.

BC: broadcast [ eguneratze-protokoloetan ] Hitz bat idatzi da cache batean; ondorioz, hitz hori duen blokearen gainerako kopiak eguneratu behar dira. BC seinalea aktibatu behar da kontrol-busean, eta aldagaiaren helbidea eta balio berria eman helbide- eta datu-busean. Kontrol-seinalea detektatzean, gainerako zelatariek eguneratu beharko dute aldagaia haien cacheetan (baldin eta cachean badute).

Zenbait kasutan, kontrol-seinale bat baino gehiago aktibatu behar da; esaterako, cachean ez dagoen aldagai batean idatzi behar denean

3.2. ZELATATZE MOTAKO KOHERENTZIA PROTOKOLOAK ▪ 93 ▪

(hutsegite bat): BR, datu-blokea eskatzeko, eta INV edo BC, kopiak kudeatzeko (kasu horietan, INV edo BC seinaleek lehentasuna dute)

Definitu ditugun kontrol-seinale horiek aukera bat baino ez dira, eta hainbat aldaera izan daitezke, makinen arabera. Esaterako, BR eta INV seinaleak batera aktibatu behar direnean, bien esanahia biltzen duen beste kontrol-seinale bat erabil daiteke (BRinv edo RdEx, "irakurketa esklusiboa"; gauza bera egin daiteke BR eta BC seinaleekin).

3. Beste zenbait kontrol-seinale Aurreko kontrol-seinaleek aldatu ohi dute blokeen egoera. Horiez

gain, beste bi hauek ere erabili behar dira zenbait kasutan, nahiz eta cacheetako blokeen egoeretan eraginik izango ez duten.

BW: bus write Prozesadoreren batek bloke oso bat idatzi nahi du memoria nagusian. Oro har, write-back erabiltzen denean gertatuko da, aldatutako bloke bat memoria nagusian eguneratu behar denean (adibidez, ordezkapena dela eta).

BW*: Prozesadoreren batek hitz bat idatzi nahi du memoria nagusian (WT ari da erabiltzen, beraz). Eskuarki, kontrol-seinale hau ez da beharrezkoa, nahikoa baita INV (edo BC) seinalea erabiltzea, memoria idazten denean balizko kopiak baliogabetu edo eguneratu egin behar baitira. (* ikurra erabiliko dugu hitz bateko transferentziak adierazteko.)

Zelatatze motako koherentzia-protokoloak algoritmo banatuak dira, non hainbat automata finituk (prozesadore bakoitzeko bat) kolaboratzen baitute datuen koherentzia ziurtatzeko. Hala, azaldu ditugun egoerak erabiliz, datu-blokeen kopiekin lan egitea ahalbidetzen dute. Zelatariaren automatak prozesadoretik zein busetik heltzen diren eskaerak edo abisuak kontrolatu behar ditu, eta, haien arabera, datu-blokeen egoera berriak eta kontrol-seinale egokiak erabaki.

Hainbat koherentzia-algoritmo defini daitezke, aurreko egoeretatik batzuk zein guztiak erabiliz. Desberdintasunak, jakina, idazketetan ageri dira, write-through, write-back, edo haien arteko nahasteak erabiltzen baitira (kopia kopuruaren, idazketa kopuruaren, cache-hierarkiaren, eta abarren arabera). Erabiltzen dituzten egoeren araberakoak izan ohi dira protokoloen izenak: MESI, MOSI... Azter ditzagun, bada, koherentzia-protokolo behinenak.

▪ 94 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

3.2.2. Baliogabetze-protokoloak

Aipatu dugunez, baliogabetze-protokolo bat erabiltzen denean, blokearen gainerako kopia guztiak desagerrarazten dira multiprozesadoretik idazketa bat egiten denean. Protokolo sinpleenak bi egoera (I-E edo I-S) eta write-through (WT) idazketa-politika erabiltzen ditu, baina ez da oso eraginkorra. Hurrengo ataletan aztertuko ditugunak gutxienez hiru egoerakoak dira, eta, ahal den kasuetan, write-back (WB) motako idazketa erabiltzen dute.

3.2.2.1. Hiru egoerako protokolo bat, MSI (Silicon Graphics)

Hiru egoerako koherentzia-protokolo arrunt bat Silicon Graphics konputagailuetan erabili dena da. Datu-blokeen egoerak I, M eta S izan daitezke; beraz, idazketa-politika write-back da (M egoera erabiltzen da), eguneratuta ez dagoen datu-bloke baten kopia bat baino gehiago onartzen ez bada ere.

Koherentzia-protokolo bat (automata finitu bat) definitzeko, datu-blokeen egoerako trantsizioak (uneko egoera → hurrengo egoera) eta sortu behar diren kontrol-seinaleak adierazi behar dira: batetik, bertako prozesadorearen eragiketak (PR eta PW) direla medio, eta, bestetik, beste prozesadoreen eragiketak sortutakoak (busean antzemandako BR eta INV kontrol-seinaleen arabera). Horiek guztiak taula honetan ageri dira MSI koherentzia-protokolorako:

Uneko egoera

Hurrengo egoera / Kontrol-seinaleak PR PW BR INV

hurs

a

I, - S BR M BR,INV

asm

atze

a S S M INV S I

M M M S BW I BW

Trafikoa (datuak) MN → CM: BR // I → S, M CM → MN: BW // M → S, I (+ordezkapena)

Grafo baten bidez ere adierazi ohi dira koherentzia-protokoloak, irudian

ageri den moduan. Marra jarraituak (letra lodia) erabili ditugu bertako prozesadoreak abiarazitako trantsizioak adierazteko, eta marra etenak busean

3.2. ZELATATZE MOTAKO KOHERENTZIA PROTOKOLOAK ▪ 95 ▪

(beste prozesadoreetan) ikuskatu diren ekintzek sortutakoak adierazteko; parentesi artean eta etzanean, busera bidalitako kontrol-seinaleak ageri dira.

Prozesadoreak cachean dagoen aldagai bat irakurtzen duenean (PR),

blokearen egoera ez da aldatzen, eta ez dira kontrol-seinalerik sortzen. Ordea, aldagaia cachean ez badago (I), datu-blokea eskatu behar da, BR kontrol-seinalearen bidez. Blokea heltzen denean, S egoeran kargatuko da cachean, aukera bakarra horixe baita (ezin da M egoera erabili, blokea aldatuko ez baita).

Idazketaren kasuan (PW), blokearen hurrengo egoerak M izan behar du beti: kopia bakarra geratuko da, aldatuta (write-back). Blokea M egoeran badago, ez da ezer egin behar, kopia bakarra zelako, baina S egoeran badago, balizko18 kopia guztiak baliogabetu behar dira (INV kontrol-seinalearen bidez). Blokea cachean ez badago (I egoera), datu-blokea eskuratu behar da, "modu esklusiboan", eta, beraz, BR eta INV kontrol-seinaleak sortzen dira (BR: blokea irakurri + INV: kopia guztiak baliogabetu).

Analiza dezagun orain busean antzemandako eragiketen ondorioak. Prozesadore batek datu-bloke bat eskatu du, eta BR seinalea jarri du busean. Bloke hori bertako cachean egon daiteke, S edo M egoeran. S egoeran badago, ez da ezer egin behar: aurretik zeuden kopiei, denak koherenteak,

18 S egoeran izateak ez du ziurtatzen datu-bloke horren kopia gehiago dagoenik sisteman, blokeak

cacheetatik desager daitezkeelako, ordezkapenak direla medio (beste bloke batzuk kargatu ahal izateko); gainera, protokolo honetan, aldagai baten lehen kopia irakurtzen denean, S egoeran kargatzen da cachean beti, ez baitira bereizten E (kopia bat) eta S (kopia asko) egoerak.

PW (BR,INV)

PR (BR)

PW (INV) INV (BW)

BR (BW)

INV

PR - PW

PR - BR

M

S

I, -

▪ 96 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

beste bat gehitzen ari zaio. Baina M egoeran badago, hau da, gurea kopia bakarra eta aldatua bada, haren egoera egokitu behar da: hemendik aurrera bi kopia izango dira sisteman. Kopia bat baino gehiago izateko aukera bakarra, protokolo honetan, S egoera da, hau da, koherentea izatea. Beraz, egoera berria S izango da, eta, ondorioz, memoria nagusia eguneratu behar da, hau da, bloke osoa idatzi behar da (BW).

Azkenik, bloke bat baliogabetzeko kontrol-seinalea (INV) detektatzen bada, erabakia garbia da: cachean badago, baliogabetu egin behar da (I egoera). Bere eragina dela eta (blokeak desagerrarazten ditu), INV kontrol-seinaleak lehentasuna du BR seinalearen aurrean biak batera aktibatzen direnean. Idazketa-politika write-back denez, litekeena da baliogabetu behar den blokea aldatuta izatea, M egoeran; kasu horretan, blokea memoria nagusian idatzi behar da (BW), informazio hori ez galtzeko.

Jakina, MNa eguneratu behar da beste kasu honetan ere: M egoeran dagoen bloke bat ordezkatzen denean.

▪ Trafikoa busean

Prozesadoreak eta memoria konektatzeko bus bat erabiltzen duten multiprozesadoreetan, busak jasan behar duen trafikoa gai kritikoa da. Baliabide partekatua da busa, eta haren komunikazio-ahalmena ase egin daiteke; hori gertatzen bada, atzerapen handiak izango ditugu memoria-atzipenetan, eta prozesatze-abiadurak behera joko du. Beraz, koherentzia-protokolo egoki batek minimizatu behar du sortzen duen datu-trafikoa, busera ahalik eta prozesadore kopururik handiena konektatu ahal izateko.

Egoeren arteko trantsizioetako taulan, datu-buseko trafikoa ere adierazi dugu. Datu-bloke bat transferitu behar da kasu hauetan: memoria nagusitik cachera, BR kontrol-seinalea sortzen denean (edo, baliokidea dena, bloke bat I egoeratik S edo M egoerara aldatzen denean); eta cachetik memoria nagusira, BW kontrol-seinalea aktibatzen denean (M egoeran dagoen bloke bat S egoerara igarotzen denean, baliogabetzen denean edo ordezkatzen denean).

▪ Nondik ekarri blokeak?

Datu-bloke bat cachean kargatu behar denean, eskuarki MNtik ekarriko da. Zenbait kasutan, aldiz, cachean kargatu behar den blokea beste cache batetik ere ekar daiteke (bloke horren kopia bat duelako). Aukera horrek ez

3.2. ZELATATZE MOTAKO KOHERENTZIA PROTOKOLOAK ▪ 97 ▪

du buseko trafikoa gutxiagotzen, bi kasuetan datu-bloke oso bat transferitu behar delako; aldiz, eragiketaren latentzia laburtzen du, cachea MNa baino azkarragoa delako. Dena den, hori egiteak interferentzia bat sortzen du beste prozesadore baten funtzionamenduan; cachetik cacherako kopia egiten ari den bitartean, bertako prozesadoreak ezin izango baitu bere cachea erabili! Gainera, arbitratze-sistema bat beharko genuke, balizko kopia guztietatik zein transferituko den aukeratzeko. Hori dela eta, eskuarki MNtik ekarriko da blokea.

Baina ekarri behar den datu-blokea beste cache batean M egoeran baldin badago ez dago aukerarik, MNan dagoen blokea ez baitago eguneratua. M egoeran dagoen kopiak S egoerara igaro behar du eta, horrekin batera, memoria nagusia eguneratu behar du. Beraz, bi aukera ditugu datu-transferentziak egiteko: eguneratu memoria nagusia eta, gero, eraman handik blokea behar duen cachera; edo MNa eguneratzen ari den bitartean (blokea datu-busean dago, beraz) kopiatu cachera:

(a) CM1 (M) → MN → CM2 edo (b) CM1 (M) → MN → CM2

Bigarren aukera oso egokia da, buseko trafikoa eta itxaron behar den denbora erdira laburtzen direlako.

Beste optimizazio bat ere egin daiteke: datu-blokea behar duen cacheak idatzi egin behar badu (blokearen azken egoera, beraz, M izango da) nahikoa litzateke CM1 (M) → CM2 (M) egitea eta MNa ez eguneratzea; azken batean, berriz aldatuko da blokea.

3.2.2.2. Illinois protokoloa, MESI (Papamarcos&Patel 84) (M88100)

Azter dezagun beste protokolo ezagun bat, Illinois izenekoa (Pentium, PowerPC eta MIPS R4400 prozesadoreetan erabili da, aldaketa batzuekin). Aurrekoaren antzekoa da, baina egoera bat gehiago (E) erabiltzen du, datu-blokeak baliogabetzeko ekintza kopurua txikiagotzeko asmoz.

E egoerak ziurtatzen digu blokearen kopia bakar bat dagoela sistema osoan (gogora ezazu S egoerak ez duela kopia kopurua zehazten) eta koherentea dela MNko informazioarekin. E eta S egoerak bereizten direnez, kontrol-buseko seinale bitar berezi bat —sh (shared)— erabili behar da, bloke baten aurreneko kopia edo beste kopia bat kargatzen ari den jakin ahal izateko.

▪ 98 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

Koherentzia-automatari dagokion trantsizio-taula eta grafoa honako hauek dira:

Uneko egoera

Hurrengo egoera / Kontrol-seinaleak PR PW BR INV

huts

a

I, - nsh: E sh: S BR M BR,INV

asm

atze

a

E E M S I

S S M INV S I

M M M S BW I BW

Trafikoa (datuak) MN → CM: BR // I → E, S, M CM → MN: BW // M → S, I (+ordezkapena)

Aurreko kasuarekin alderatuta, hau da desberdintasun nagusia: cachean

bloke bat kargatu behar denean (BR), E egoeran kargatzen da baldin bloke hori kopia bakarra bada, hau da, beste cacheetan ez badago; bestela, S egoeran kargatzen da.

Kopiak dauden edo ez jakiteko, sh kontrol-lerroa erabiltzen da; izan ere, busean helbide bat (kasu honetan BR kontrol-seinalearekin batera) ageri denean, zelatari guztiek bertako cacheen direktorioak arakatuko dituzte datu-bloke hori duten edo ez jakiteko, eta, baiezkoan, sh kontrol-lerroa

PW (BR,INV)

INV (BW)

INV

PW (INV)

BR (BW)

PW

PR

PR - PW

BR

PR - BR

I, -

S

M

E

PR (BR)

INV

sh nsh

3.2. ZELATATZE MOTAKO KOHERENTZIA PROTOKOLOAK ▪ 99 ▪

aktibatuko dute. Beraz, sh = 1 bada, badaude datu-blokearen kopiak (bat gutxienez) beste cacheetan, eta sh = 0 bada (nsh, not shared), aurreneko kopia ari da kargatzen.

Blokearen bigarren kopia kargatzean, biak S egoerara igaroko dira, eta, hortik aurrera, blokearen eboluzioa lehen aztertu dugun bera izango da.

E egoeraren helburua, beraz, bloke pribatuak (beti kopia bakarra izango dira, partekatze faltsuaren arazoa gaindituta) eta partekatuak bereiztea da, eta, ondorioz, buseko kontrol-trafikoa murriztea. Hala, E egoeran dagoen bloke batean idazten denean, M egoerara igaroko da blokea, busean trafikorik sortu gabe (S egoeran izan balitz, kopiak baliogabetzeko kontrol-seinalea eta helbidea bidali beharko genituzkeen). Izan ere, kontuan hartu behar da datu-bloke gehienak pribatuak izango direla, eta bakan batzuk bakarrik partekatuak.

3.2.2.3. Berkeley protokoloa, MOSI

Baliogabetze-protokoloen azken adibide gisa, Berkeley izenekoa aztertuko dugu; I, M, S eta O egoerak erabiltzen ditu, eta idazketa-politika write-back da, beti. Gogoratu: O egoera (jabea, owner) kopia ez-koherente asko eduki ahal izateko erabiltzen da (aurreko bi kasuetan, aldatutako kopia bakarra onartu dugu, M egoeran). E eta S egoerak bereizten ez direnez gero, koherentzia-protokolo honetan ez da sh kontrol-seinalea erabili behar.

Hurrengo irudian, Berkeley protokoloari dagozkion trantsizio-taula eta grafoa ageri dira.

Uneko egoera

Hurrengo egoera / Kontrol-seinaleak PR PW BR INV

huts

a

I, - S BR M BR,INV

asm

atze

a

S S M INV S I

M M M O I BW

O O M INV O I BW

Trafikoa (datuak) MN / CM → CM: BR // I → S, M CM → MN: BW // M, O → I (+ordezkapena)

▪ 100 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

O egoera berria dela eta, posible da orain kopia ez-koherente asko, elkarren berdinak, izatea (horrek ahalbidetzen du kasu guztietan write-back motako idazketa erabiltzea). Aurreko protokoloan, M → S trantsizioa egiten zen da datu-bloke baten bigarren kopia kargatu behar zenena; honetan, aldiz, M → O egingo da, eta ez da MNa eguneratuko. Ondorioz, bloke bat ez da memoria nagusian eguneratuko harik eta baliogabetzen edo ordezkatzen den arte.

Bloke bat cache batean M egoeran dagoenean, eta beste cache batean irakurri behar denean, lehenbizikoa O egoerara igarotzen da (jabea) eta kopia berria S egoeran sartzen da. Egon adi; S egoerak ez du beti adieraziko, bada, memoria nagusiarekin koherentea dela. Datu-blokearen gainerako kopiak ere S egoeran badaude, informazioa koherentea izango da, baina baldin badago blokearen kopia bat O egoeran, ez da koherentea izango memoria nagusiarekin; hori bai, kopia guztiak elkarren berdinak dira. O egoeran dagoen kopia desagerrarazi behar denean, ordezkapena dela medio, zelatari horrek eguneratuko du MNa; gainerako kopiek, S egoeran, jatorrizko definizioa berreskuratuko dute (koherenteak). Hain zuzen ere, horixe adierazten du O egoerak: zein kopiari dagokion memoria nagusia eguneratzea (nahikoa baita, noski, behin egitea).

Trafikoari dagokionez, ez dago aldaketa handirik. Hala ere, bloke bat S egoeran kargatu behar denean cachean (hutsegite bat irakurtzean), bi aukera kontuan hartu behar dira. Bloke hori beste cacheren batean ez badago, nahitaez, MNtik ekarri beharko da; baina, beste cache batean O edo M egoeran baldin badago, cache horretatik ekarri beharko da, ez baitago eguneratuta MNan. Datu-blokea duen cachearen koherentzia-kontrolagailuak erantzun egokia eman beharko du: datuak bertako cachetik busera bidali eta MNan hasitako irakurketa bertan behera utzi.

PR - BR

I, -

O BR

PR - BR

PW (BR,INV)

INV (BW)

INV

PW (INV) INV (BW)

PR (BR)

PW (INV) PR - PW

M

S

3.2. ZELATATZE MOTAKO KOHERENTZIA PROTOKOLOAK ▪ 101 ▪

3.2.2.4. Baliogabetze-protokoloen laburpena

Aurreko ataletan, baliogabetze-protokolo batzuk azaldu ditugu, eta horiek datu-blokeen kopiak baliogabetu egiten dituzte haietako bat aldatzen denean. Egoera, idazketa-politika... desberdinak erabiltzen badituzte ere, antzekoak dira guztiak.

Ez dira dauden guztiak, ezta hurrik ere. Ez dago problemarik, esaterako, bost egoerak erabiltzen dituen baliogabetze-protokolo bat definitzeko. Beste zenbait kasutan (Alpha prozesadoreko koherentzia-protokoloan, esaterako) blokeak baliogabetzen edo eguneratzen dira blokea cache-hierarkiaren zein mailatan dagoen kontuan hartuta. Beste kasu ezagun bat write-once izeneko protokoloa da, non WT eta WB idazketa-politiken arteko nahastea erabiltzen den: WT datu-blokea aurreneko aldiz idazten denean, eta WB hurrengoetan. Aukera horiek guztiak ariketetarako utziko ditugu.

3.2.3. Eguneratze-protokoloak

Memoria partekatuko multiprozesadoreen cacheetan dauden datu-blokeen kopiak kudeatzeko beste teknika datu-blokeen informazioa eguneratzea da. Baliogabetze-protokoloak erabiliz, gainerako kopiak desagerrarazten dira haietako bat aldatzen denean. Eguneratzearekin, aldiz, kopia guztiak mantenduko dira, baina eguneratuta. Idazketa egiten duen cacheko kontrol-automatak, zelatariak, abisatu egin beharko die beste zelatariei bertako cachean izandako aldaketaz, datu-blokea aldagaiaren balio berriaz egunera dezaten.

Aldagai bat gainerako cacheetan eguneratzeko, lehen aipatu dugun kontrol-seinalea erabiltzen da, BC (broadcast); horrekin batera, aldagaiaren helbidea eta balio berria dagozkien busetan jarriko dira. Zelatariek prozesatu beharko dituzte seinale horiek, eta, dagokienean, behar diren aldaketak egin datu-blokeetan, aldagaiaren balioan zein blokearen egoeran.

Nahiz eta teknika hori erabiliz beti eraginkortasun hobea lortuko dela iruditu (datuak mantendu egiten dira cacheetan), auzia ez dago batere garbi, eta, oro har, exekutatzen ari den aplikazioaren araberakoa izango da eraginkortasuna. Datu-bloke bat sistematikoki berrerabiltzen den kasuan, eguneratzea eraginkorra izango da, blokea cacheetan mantendu egingo baita; aldiz, datu-bloke hori berriz erabili behar ez bada, agian behin eta berriro jardungo dugu blokea eguneratzen, batere etekinik lortu gabe (egokiago

▪ 102 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

litzateke lehenbizikoan kopia baliogabetzea). Ez ahaztu: busa erabili behar da datuak transmititzeko, eta, gainera, zelatariak cachea eguneratzen duen bitartean, bertako prozesadoreak ezin izango du cachea erabili, eta itxaron egin beharko du.

Eguneratze motako koherentzia-protokoloek ez dituzte blokeak baliogabetzen; beraz, ez dute I egoera erabiltzen. Hala ere, I egoera erabili behar da, ez koherentzia mantentzeko, baina bai bloke bat baliogabetu behar denean, esaterako, testuinguru-aldaketak edo prozesuen migrazioak direla eta. Beraz, datu-blokea cachean ez dagoen kasua adierazteko, (I, -) erabiliko dugu.

Azter ditzagun protokolo mota horretako bi adibide esanguratsu.

3.2.3.1. Firefly protokoloa, MSE(I) (Archibald & Baer 85) (DEC)

Eguneratze-protokolo honek E, M eta S egoerak erabiltzen ditu. Idazketa-politika write-back da bloke pribatuekin, eta write-through bloke partekatuekin. Hau da, bloke baten kopia bakarra dagoenean, memoria nagusia ez da eguneratzen idazketetan; bestela, kopia asko dagoenean, idazketa guztiek memoria nagusia ere eguneratzen dute.

E eta S egoerak bereizten direnez, protokolo honetan ere sh (shared) kontrol-seinalea erabiltzen da: sh = 1 → badaude datu-bloke horren kopia gehiago beste cacheren batean; sh = 0 (nsh) → ez dago kopiarik.

Egoeren arteko trantsizioak eta kontrol-seinaleak ageri dira taula eta grafo hauetan.

Uneko egoera

Hurrengo egoera / Kontrol-seinaleak PR PW BR BC

huts

a

- nsh: E sh: S BR nsh: M

sh: S BR

BR,BC

asm

atze

a

E E M S S

S S nsh: E sh: S BC S S

M M M S BW S BW

Trafikoa (datuak) MN / CM → CM: BR // (I) → E, S, M CM → MN: BW // M → S (+ordezkapena) CM → CM*MN*: BC // (I) → S(wr); S → E, S(wr)

3.2. ZELATATZE MOTAKO KOHERENTZIA PROTOKOLOAK ▪ 103 ▪

Datu-bloke bat cachean kargatu behar denean, haren egoera sh

seinalearen araberakoa izango da. Sisteman kopiarik ez dagoela detektatzen bada (sh = 0), blokearen egoera E (irakurketetan) edo M (idazketetan) izango da; bi egoera horiei (kopia bakarra adierazten dutenei) write-back idazketa-politika aplikatzen zaie. Bestela, kopia gehiago dagoenean (sh), blokearen egoera S izango da, zeinari, memoria nagusia eta cachea koherenteak mantentzearren, write-through motako idazketa aplikatzen zaion.

Modu berean, S egoeran dagoen bloke baten gainean idatzi ondoren, E edo S egoera aukeratuko da, sh seinalearen arabera. Gogoratu: S egoeran egon arren —partekatua—, baliteke une horretan kopia bakarra izatea, beste kopia guztiak ordezkatu badira; idazketa-unea aprobetxatzen da, beraz, egoera egokitzeko. Adi: kopia bakarra geratu bada ere, blokearen egoera E izango da, ez M, aldagai partekatuekin erabiltzen den idazketa-politika beti bera delako: memoria nagusia eguneratu behar da.

Trafikoaren ikuspuntutik, kasurik interesgarriena (I, -) → S trantsizioa da. Irakurketa baten ondorioa bada, blokea cachera ekarri behar da, MNtik zein beste CM batetik. Kopiak baldin badaude eta koherenteak badira (E, S), eskuarki MNtik ekarriko da blokea; koherenteak ez badira (M), MNa eguneratu beharko da blokea ekarri baino lehen, edo, egokiago, aldi berean. Bestalde, idazketa baten ondorioz sortutako (I, -) → S trantsizioetan, blokea ekartzeaz gain, memoria nagusia zein beste kopiak eguneratu behar dira. Hori dela eta, BC seinalea sortzen denean, memoria nagusia ere eguneratzen da, hitz bat (hau da, hasieran definitu dugun WB* kontrol-seinalearen funtzioa ere betetzen du). Izan ere, eguneratze-trafikoa murriztearren, idazketa/hutsegitea kasuan, BC kontrol-seinalea sortu baino lehen zain

M

E PR BR - BC

BR (BW)

PW (BC)

PR

PW

S

PR - PW

nsh

sh

BR

PR (BR)

PW (BR)

( - )

PW (BC) nsh

nsh

sh

( - ) sh

(BC)

▪ 104 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

geratzen gara, sh kontrol-lerroaren erantzuna izan arte; bestela, eragiketaren hasieratik BC seinalea ere sor liteke.

3.2.3.2. Dragon protokoloa, MOES(I) (McCreight 84, Xerox Parc Dragon)

Azken adibide gisa, azter dezagun Dragon izeneko koherentzia-protokoloa. Protokolo honetan, bost egoerak erabiltzen dira: E, M, S eta O (protokolo honen aldaera bat Sun Sparc/Server makinetan erabili da). Berkeley protokoloan bezala, O egoeraren erabilerak ahalbidetzen du write-back idazketa-politika kasu guztietan erabiltzea. sh (shared) kontrol-seinalea erabiltzen da E eta S egoerak bereizteko eta eguneratze (BC) kopurua murrizteko. Taulan eta grafoan ageri da protokoloa.

Uneko egoera

Hurrengo egoera / Kontrol-seinaleak PR PW BR BC

huts

a

- nsh: E sh: S BR nsh: M

sh: O BR

BR,BC

asm

atze

a

E E M S S

S S nsh: M sh: O

- BC S S

M M M O S

O O nsh: M sh: O

- BC O S

Trafikoa (datuak) MN / CM → CM: BR // (I) → E, S, M, O CM → CM*: BC // (I), S, O(wr) → O [ CM → MN: ordezk. // M, O → (I) ]

PW (BR)

BR

BC

PR BR - BC

BC

PW PW sh (BC) PR - BR

BR PR - PW

PW PW

PR

M O

E S

nsh

PR (BR) ( - )

nsh

sh

sh (BC)

( - ) nsh sh

(BC) nsh

3.3. ZELATATZE PROTOKOLOEN GAUZATZEA ▪ 105 ▪

Taulan ageri denez, aldaketa gutxi dago Firefly kasuarekin alderatuta: eguneratu gabeko bloke baten kopia asko onartzen dira, besterik ez, eta horretarako M/S → O trantsizioak onartzen dira.

Gogoratu: trafikoari dagokionez, CM → CM* erabiltzen dugu hitz bat cachetik cachera pasatu behar denean; hau da, kopiak eguneratzeko broadcast-a egin behar denean.

3.2.4. Zelatatze-protokoloen laburpena

Zelatatze motako protokolo nagusiak azaldu ditugu aurreko paragrafoetan, baliogabetzekoak zein eguneratzekoak. Lehenengo SMP makinekin batera protokolo desberdin asko agertu baziren ere, azaldu ditugunak (edo haien aldaerak) dira erabilienak gaur egun. Gainera, gauzatzeko hainbat arazo dela medio, eguneratze-protokoloak ez dira ia erabiltzen. Beraz, arruntenak hiru edo lau egoerako baliogabetze-protokoloak dira, zeinetan WB idazketa-politika erabiltzen den.

3.3. ZELATATZE PROTOKOLOEN GAUZATZEA

3.3.1. Arazoak

Bus baten inguruan antolatzen diren multiprozesadoreetako datuen koherentzia mantentzeko, nahikoa da zelataria bezalako sistema bat. Izan ere, aztertu ditugun automatak (edo haien aldaerak) erabiltzen dira multiprozesadore komertzialetan.

Koherentzia-kontrolagailuek exekutatu behar duten "logika" nahiko sinplea da, hala baliogabetzekoa nola eguneratzekoa. Hala ere, automata horiek eraiki behar direnean, arazo gehiago agertzen dira, eta ez da hain erraza gailu sinpleak, eraginkorrak eta, batez ere, zuzenak lortzea. Zuzentasuna, jakina, nahitaez bete behar den baldintza da, zelatariak ziurtatu egin behar baitu datuen koherentzia sistema osoan. Hori lortu ezean, ezin izango ditugu memoria partekatuko sistema paraleloak erabili, ez behintzat modu eraginkorrean.

Automata banatu bat da zelataria, P prozesadoretan exekutatzen delako, aldi berean. Eta horrek, banatuta izateak, berezko arazoak sortzen ditu, koordinatu egin behar baita gailu guztien funtzionamendua azken emaitza

▪ 106 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

zuzena izan dadin. Arazo larriena, segur aski, koherentzia-protokoloen atomikotasun eza da: ezin da ziurtatu ez direla nahastuko, denboran zehar, bloke beraren gaineko koherentzia-ekintzak bi prozesadoretan, azkenik emaitza oker bat sortzeko. Arazoak eta irtenbideak azaltzeko, analiza dezagun koherentziaren kontrolagailua, zelataria alegia, nola egituratzen den. Irudian, cacheko kontrolagailu baten eskema logikoa ageri da (sinplifikatua). Azter ditzagun osagai nagusiak.

3.3.1.1. Cachearen direktorioa

Cacheetan egin behar diren eragiketak bi iturburutik datoz multiprozesadoreetan. Batetik, bertako prozesadoreak agintzen dituenak; eta, bestetik, busean ikusitakoaren araberakoak (beste prozesadoreen ekintzak). Beraz, interferentziak izan daitezke bien artean. Esaterako, zer egin busean INV seinalea ikusten denean, une horretan bertako prozesadorea cachea erabiltzen ari bada? (edo alderantziz).

Cache data RAM

tags + state

snoopy

Bus side

controller

compar.

Processor side

controller

P

compar.

Cmd

Addr

Addr

Cmd

tags + state

proc.

Write-back buffer

Data buffer

tag

state

system bus

to controller

data

to controller

addr contr

CM

3.3. ZELATATZE PROTOKOLOEN GAUZATZEA ▪ 107 ▪

Sistemaren eraginkortasuna handiagotzeko, eskuarki bitan banatzen da cacheko kontrolagailua: alde batetik, busa aztertzen duena (zelataria), eta, bestetik, prozesadorearen eskaerak prozesatzen dituena. Bi kontrolagailu horiek erabili behar dute cachearen direktorioa; eta ahalik eta interferentzia gutxienekin erabili behar dute: prozesadorea erabiltzen ari bada cachea, zelataria atzeratu egingo da (eta, ondorioz, beste prozesadoreen transferentziak); zelataria erabiltzen ari bada, ordea, prozesadorea da itxaron beharko duena.

Hori dela eta, eskuarki cacheko direktorioa bikoiztuta dago (edo bi portuko memoria erabiltzen da), eta kontrolagailu bakoitzak horietako bat erabiltzen du. Hala, paraleloan egin daitezke eragiketak (bilaketak, esaterako) bi direktorioetan. Hori bai, biak berdinak mantendu behar dira, hau da, batean aldaketa bat egiten bada, bestean ere egin behar da; zorionez, direktorioan egin behar diren aldaketak —idazketak— gutxi dira irakurketen ondoan.

Datuak, noski, ez dira bikoizten; askoz toki gehiago hartzen dute eta koherentzia-kontrolagailuak kontrol-informazioa baino askoz gutxiago erabili behar ditu datuak.

3.3.1.2. Idazketa-bufferrak

Write-back idazketa-politika erabiltzen denean (ohikoa), zenbait unetan, datu-bloke oso bat idatzi behar da memorian, dela ordezkatu edo baliogabetu behar delako (M → I, -), dela koherentzia mantentzeko (M → S). Esaterako, demagun M egoeran dagoen bloke bat ordezkatu behar dela. Bloke berria ekarri baino lehen, gorde egin behar da zaharra MNan, eta horrek denbora behar du, hainbat hitz idatzi behar direlako; bitartean, prozesadorea geldirik dago.

Badago hobekuntza arrunt bat eragiketa horretarako: <eguneratu (BW) / irakurri bloke berria (BR)> eragiketak ordena horretan egin beharrean, alderantzizko ordenan egitea: bloke berria ekartzea eta, gero, bloke zaharra memorian salbatzea. Eragiketak ordena horretan egin ahal izateko, eta lehenbiziko pauso gisa, ordezkatu behar den (M egoeran dagoen) blokearen kopia bat egin behar da (bestela, informazioa galduko litzateke); kopia hori idazketa-bufferrean egiten da. Bloke berria cachean dagoela eta prozesadorea berriro abian dela, idazketa-bufferrean utzi den blokea memoria nagusian idatziko da, eskuarki busa libre dagoen zikloak profitatuz.

▪ 108 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

Aurrekoa arrunta da prozesadore bakarreko sistemetan ere. Baina multiprozesadoreetan oso kontuz tratatu behar dira idazketa-bufferrak. Izan ere, zelatariak bilaketak egin behar dituenean, bloke bat cachean dagoen ala ez jakiteko, cacheko direktorioaz gain idazketa-bufferr(et)an ere begiratu beharko du, koherentziarako garrantzitsua izan daitekeen bloke bat hor egon daitekeelako. Beraz, bilaketa-hardwarea (konparagailuak) bikoiztu egin behar da: bata cacheko direktoriorako eta bestea idazketa-bufferrerako (ikus aurreko irudia).

3.3.1.3. Bus-eskaerako protokoloa

Prozesadore batek busean eskaera bat plazaratzen duenean, BR adibidez, beste prozesadoreen zelatarien erantzunari itxaron behar dio memoria nagusira joan baino lehen, eskuratu behar duen blokea benetan non dagoen jakin arte: memoria nagusitik ekarri behar al da blokea, edo beste cache batean dagoen kopia hartu behar al da, aldatuta dagoelako? Baina, zenbat denbora itxaron behar da zelatari guztien erantzunak lortu arte?

Hauek dira denbora hori kontrolatzeko erabiltzen diren estrategia nagusiak:

• Denbora finko eta jakin bat itxaroten da beti, zelatari guztiek erantzuna eman dutela seguru izan arte (sistemaren hardwareak zedarrituko du denbora maximo hori). Beraz, "kasurik txarreneko" denbora itxaroten da beti; ez da, noski, aukera eraginkorrena, baina, ordainean, gauzatzeko sinpleena da. (Pentium quad/HP/ SUN)

• Denbora aldakorra da: itxaron egiten da azken zelatariaren erantzuna izan arte, eta erabakia une horretan hartzen da. Horrela, jakina, itxaroten den denbora laburtu egiten da, beharrezko denbora baino ez baita itxaroten kasu bakoitzean, baina konplexua da egiteko, gailu guztien erantzunak kontrolatu behar baitira azkena detektatzeko.

Lehenbiziko zein bigarren kasuan, hobekuntza bat egin daiteke: zelatarien erantzunen zain dagoen bitartean, memoria nagusia irakurtzen da. Azkenean, blokea CM batetik hartu behar bada, nahikoa da MNko eragiketa bertan behera uztea, eta, aldiz, MNtik eskuratu behar bazen, ez da denbora galdu, eragiketa hasieratik abiatu delako. (SGI challenge)

• Bit bat gehitu, memoria nagusian, bloke guztiei, bloke hori cache batean dagoen ala ez adierazteko. Horrela, ez da erantzunik itxaron

3.3. ZELATATZE PROTOKOLOEN GAUZATZEA ▪ 109 ▪

behar, memoria irakurtzearekin batera jakingo dugulako erantzuna. Irtenbide hau garestia da, memoria nagusiko bloke guztietan eragina du eta; hori dela eta, ez da erabiltzen.

Aurreko estrategiak erabili ahal izateko, hardwarearen laguntza behar da: seinale gehiago kontrol-busean, hain zuzen ere. Batetik, sh seinalea, dagoeneko erabili duguna (datu-bloke baten kopiak dauden ala ez jakiteko). Ildo berean, egokia da mota bereko beste bi seinale izatea: dirty, blokea cache batean aldatuta dagoela adierazteko; eta inh (inhibitu), MNan hasitako atzipenak bertan behera uzteko edo geldiarazteko.

3.3.1.4. Atomikotasuna: koherentzia-kontrolagailuaren egoera

Aurreko irudian ageri den kontrolagailuaren analisia amaitzeko, gauza bakar bat falta zaigu: kontrolagailuaren egoera (state, irudian). Hasieran aipatu dugunez, P prozesadorek aldi berean lan egiten dutenean, arazo nagusietako bat atomikotasun eza da. Eragiketa bat atomikoa da beste prozesadoreen inongo interferentziarik gabe, hasieratik bukaera arte, exekutatzen bada.

Koherentzia mantentzeko prozedura osoa ez-atomikoa da berez, eragiketa asko egin behar direlako, eta ezin da ziurtatu tartean ez dela interferentziarik izango, prozesadore asko izango ditugulako lanean. Eragiketa horietan, busaren bidezko datu-transferentziak daude. Busa dela eta, sinplifikazio bat onartuko dugu: buseko eragiketak atomikoak dira; hots, ez da beste eskaera bat prozesatzen aurrekoa bukatu arte —ez da segmentatzen19—.

Prozesadore bakarreko sistemetan, komunikazio-protokolo ezagunak erabiltzen dira busarekin lan egiteko, honen antzekoak (idazketa batean, esaterako):

prozesadorea busaren kontrolagailua

bus-eskaera ... bus-onarpena

helbidea, kontrola ... onarpena

datuak

Bus-kontrolagailuak, beraz, ordena eta lehentasunak ezartzen ditu busaren erabileran. Buseko kontrola konplexuagoa da multiprozesadoreetan, batetik, 19 Prozesadore azkarrenetan aurrekoa ez da egia, busaren erabilera optimizatu egiten baita latentziak

txikiagotzeko.

▪ 110 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

busera konektatuta prozesadore asko daudelako, eta, bestetik, cacheko kontrolagailuak konplexuagoak direlako, zelatariaren funtzioak egin ahal izateko. Gainera, laguntzen badu ere, buseko eragiketen atomikotasunak ez du ziurtatzen koherentzia-prozedura osoaren atomikotasuna.

Beraz, koherentzia-protokoloa bera arduratu beharko da ekintzen atomikotasunaz, zuzentasuna ziurtatzeko. Adibide gisa, azter dezagun atomikotasuna nola lortu kasu jakin batean: Illinois protokoloan (MESI).

3.3.2. Illinois koherentzia-protokoloa berriz

3.3.2.1. Lasterketak: egoera iragankorrak, kontrol-seinaleak

MESI motako koherentzia-protokolo bat da Illinois, baliogabetzekoa (azalduko dugun guztia beste protokoloei ere aplika dakieke). Protokoloak sh kontrol-seinalea erabiltzen du, blokeak partekatzen diren ala ez jakiteko (E eta S egoerak bereizteko).

Analiza dezagun kasu hau. Bi prozesadorek datu-bloke bat partekatzen dute, S egoeran. Biek egiten dute, aldi berean, idazketa bat bloke horretan, eta, beraz, bestea baliogabetzen dute, eta, ondorioz, biak desagertzen dira. Nola konpontzen da arazoa20? Nola ziurtatu idazketa horiek erakarriko dituzten eragiketa guztiak egoki egingo direla (busa atomikoa izanda ere)?

Esaterako, P1ek eta P2k INV seinalea bidali dute busera. Haietako batek irabaziko du buseko kontrola (demagun P1 dela). Beraz, P2ren koherentzia-kontrolagailuak bere datu-blokea S egoeran utzi beharrean (gero M egoeran jartzeko), I egoeran jarri beharko du (bestela, blokea M eta S egoeratan geratuko litzateke cacheetan!). Baina hori eginez gero, busera bidalitako seinalea, INV, ez da dagoeneko nahikoa izango, orain BR seinalea ere bidali behar baita. Ondorioa garbia da: koherentzia-kontrolagailua ezin da geratu, besterik gabe, bere eskaeraren erantzunaren zain; izan ere, agian aldatu egin beharko du egindako eskaera, tartean beste prozesadore batek bloke beraren gainean eragiketa bat egin nahi izan duelako.

Arazo horri "lasterketa" (race) deritzo; lasterketak ekiditeko, egoera gehiago gehitu ohi zaizkio koherentzia-protokoloari, egoera iragankorrak, alegia. Gehitu behar diren egoera berri horiek ez dagozkie eskuarki datu- 20 Edo, bestela: bi prozesadorek batera idatzi nahi dute datu-bloke beraren gainean, baina datu-bloke

hori ez dago ez baten cachean ez bestearenean. Biek ekarri behar dute blokea eta, une horretan blokea inork erreklamatzen ez duenez –sh = 0–, biek jarriko dute blokea M egoeran.

3.3. ZELATATZE PROTOKOLOEN GAUZATZEA ▪ 111 ▪

blokeei, koherentzia-kontrolagailuari baizik; hori dela eta, erregistro berezi batean gordetzen dira, kontrolagailuan bertan (ikus kontrolagailuaren aurreko irudia). Egoera iragankor horien esanahia garbi dago: zerbait egiten ari da, baina oraindik ez da amaitu.

Aipatu dugunez, busaren erabilera atomikoa ari gara kontuan hartzen, eta, horretarako, bi kontrol-seinale gehiago erabiliko ditugu protokoloan:

- eskaera: BRQ (bus request) buseko eragiketa bat egin behar dut

- erantzuna: BGR (bus grant) busaren erabilera onartzen da

Aldibereko eragiketak ondo sekuentziatzeko, buseko erabilera eskatu behar da edozein transferentziarekin hasi baino lehen; eskaera horren onarpena hartutakoan exekutatuko da koherentzia-prozedura.

Analiza dezagun berriz Illinois protokoloa aurreko guztia kontuan hartuz. MESI protokoloa gauzatzeko, nahikoak dira 3 egoera iragankor: ISE, IM eta SM. Protokoloaren grafoa irudikoa da, eta hauek dira egoeren arteko trantsizio nagusiak:

• PR eta hutsegitea (I → S, E) Zuzenean E edo S-ra joan beharrean, ISE egoera iragankorrera joango

da. I → ISE trantsizioan, busaren erabilera eskatzen da (BRQ), eta hor geratuko da bus-kontrolagailuaren onarpena hartu arte (BGR). Onarpena heltzen denean, datu-blokea eskatuko da (BR), eta, blokea heldutakoan, cachean kargatuko da, dagokion egoeran, S edo E, uneko sh kontrol-seinalearen arabera.

• PW eta hutsegitea (I → M) Datu-blokea eskuratu eta aldatu baino lehen, busaren erabilera eskatu

behar da, eta IM egoera iragankorrean geratuko da onarpena hartu arte. Orduan, blokea eskatu eta gainerako kopiak baliogabetu behar dira (BR,INV) eta, azkenik, segurtasun osoaz, datu-blokea M egoeran kargatuko da cachean.

• PW eta asmatzea (S → M) Aurreko kasuetan bezala, egoera iragankor batera igaroko da, SM-ra.

Kontuz, S egoeran zegoen, eta baliteke beste kopia batean, aldi berean, antzeko trantsizioa gertatzea. Beraz, SM egoera iragankorrean dagoen bitartean, busa erabiltzeko (gainerako kopiak baliogabetzeko) baimenaren zain, bi gauza gerta daitezke:

▪ 112 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

- BGR seinalea, baimena, heltzea; beraz, datu-blokea M egoerara

igaroko da, eta INV seinalea sortuko da. - INV seinalea detektatzea busean; beste prozesadore batek aldatu

du datu-blokea. Bertako kopia, beraz, baliogabetu egin behar da, eta, ondorioz, automatak IM egoerara joan beharko du, idazketa exekutatu behar baita, baina I egoeratik abiatuta, blokea baliogabetuta dagoelako (datu-blokea eskatu behar da: BR,INV).

• PW eta asmatzea (M, E → M) Kasu honetan ez da batere arazorik izango; bertako kopia bakarra

denez, nahikoa da idazketa egitea eta egoera aldatzea.

3.3.2.2. Deadlock, livelock eta starvation arazoak

Atomikotasun eza ez da konpondu behar den arazo bakarra koherentzia-protokoloak gauzatu behar direnean. Automataren blokeoa (deadlock) da beste arazo arrunt bat. Komunikaziokoetan, blokeoa bufferren okupazioarekin erlazionatuta dago; koherentzia-protokoloetan, aldiz, beste blokeo mota bat ager daiteke: fetch deadlock deitutakoa.

INV (BW)

BR

INV

BR (BW) BGR (BR,INV)

INV

PW (BRQ)

INV

PR (BRQ)

BGR (INV)

PW (BRQ)

PR - PW

PR

PW

PR - BR

IM

ISE

SM

M

I, -

S

E

nsh sh

BGR (BR)

3.4. ZELATARI HIERARKIKOA ▪ 113 ▪

Adibidez, P1 prozesadoreko koherentzia-kontrolagailua egoera iragankor batean dago, buseko kontrolagailuaren erantzunaren zain (besterik ez). Bitartean, busaren erabilera lortu duen P2ko kontrolagailuak BR eragiketa exekutatu nahi du; zoritxarrez, berak nahi duen blokea P1ek dauka, eta gainera M egoeran. Ondorioa: P1ek ez du bloke hori bidaliko, BGR seinalearen zain dagoelako, eta P2k ez du busa askatuko, M egoeran dagoen blokea behar duelako. Sistema blokeatu egin da.

Beraz, aurreko arazoa saihesteko, zelatariak ezin dio utzi busa espiatzeari, ezta egoera iragankor horietan ere. Horietako batean izanik, adibidean aipatutako ekintza moduko bat ikusten badu, erantzun egokia eman beharko du.

Beste testuinguruetan gertatzen den bezala (prozesuen arteko komunikazioan, adibidez) blokeoaz gain beste arazo batzuk ere izan daitezke, hala nola livelock eta starvation izenekoak. Livelock arazoak kasu bat adierazten du non prozesuak geldituta ez dauden (blokeatuta edo hilak/dead), baina, hala ere, ez dira aurrera jarraitzeko gauza. Esaterako, bi prozesadorek idatzi egin behar dute, aldi bertsuan, cachean ez duten datu-bloke batean, berean; biok ekarriko dute blokea eta baliogabetuko dituzte gainerako kopiak; livelock egoera sortuko da protokoloa honela betetzen bada: rd1 – rd2 – INV1 – INV2 >> rd1 – rd2 – INV1 – INV2... Hau da, eragiketa ez da inoiz bukatzen. Bestalde, starvation ("gosetea") motako arazoa ageri da, eskuarki, lehentasun-estrategiei lotuta: zelatari guztiek aukera berdinak izan behar dituzte haien ekintzak betetzeko; esaterako, arazo bat dago, baldin eta prozesadore jakin batek inoiz busa erabiltzea lortzen ez badu, beste bati tokatzen baitzaio beti erabilera-txanda. Aztertu dugun adibidean, esaterako, aurreko bi problemak konponduta daude.

Laburbilduz, koherentzia-protokoloak kontu handiz diseinatu eta eraiki behar dira arazo guztiak gainditu eta zuzenak eta eraginkorrak izan daitezen. Ez dira kontrol-unitate bakar baten mende exekutatzen, P prozesadoreen artean banatuta baizik, eta horrek konplexuago bihurtzen ditu haien diseinua eta gauzatzea.

3.4. ZELATARI HIERARKIKOA

Bus bat erabili dugu SMP multiprozesadore baten prozesadoreen arteko komunikazioa gauzatzeko. Dakigunez, konekta daitekeen prozesadore kopurua (gutxi batzuk baino ez) da busaren arazo nagusia. Seigarren

▪ 114 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

kapituluan analizatuko ditugu komunikazio-sare konplexuagoak, baina une honetan merezi du beste konexio-sare bat aztertzea, busaren eboluzio naturala baita: bus-hierarkia. Bus-hierarkia bat busen arbola bat da: hostoetan, multiprozesadoreak daude (bus batean lotuta), eta, gainerako adabegietan, busak eta kontrolagailuak. Azken horiek erabili behar dira informazioa sare guztian zehar barreiatu ahal izateko. Irudian ageri den moduan, cluster bat antolatzen da, non nodoak SMP sistemak baitira.

Demagun bi mailako bus-hierarkia bat daukagula, non bus bat erabiltzen den, bigarren mailan, N multiprozesadore konektatzeko (bakoitzean P prozesadore bus batean, SMP). Memoria partekatua bada ere, egokiena memoria hori fisikoki banatzea da, eta horrela NUMA (non-uniform memory access) motako sistema bat lortzen da: atzipen-denbora desberdina da atzitu behar den memoria-posizioaren kokapenaren arabera (ez da "simetrikoa"). SMP multiprozesadore bakoitzaren barnean, zelatatze-protokolo bat erabiltzen da koherentzia mantentzeko. Baina, nola lor daiteke sistema osoaren koherentzia?

Geroxeago ikusiko dugunez, "zentralizatuak" ez diren konexio-sareak erabiltzen direnean, irtenbidea koherentzia-direktorioak dira. Konexio-sare gisa busen hierarkia bat erabiltzen bada, direktorioen funtzioa betetzen duten koherentzia-kontrolagailu bereziak erabil daitezke, bi bus-mailak konektatzeko eta zelatatzeko, eta maila batetik bestera informazioa pasatu behar den ala ez erabakitzeko.

Koherentziarako "monitore" berezi horiek bi eragiketa mota zelatatu beharko lituzkete: batetik, urrutiko cache batean kopiatu diren bertako MNko blokeen gaineko eragiketak; eta, bestetik, bertako cache batera ekarri diren urrutiko memorietako blokeen gainekoak. Nodo jakin baten barnean (MNa zein cachea) geratzen den informazioak, noski, ez du arazorik sortzen beste nodoetan, eta bertako zelataria arduratuko da haren koherentziaz.

P

C

koherentzia globalerako hardwarea

MN MN K K

zelatari lokala

SMP

B1

B2

3.4. ZELATARI HIERARKIKOA ▪ 115 ▪

Bi partetan banatuko ditugu koherentzia-monitore edo -direktorio berria:

• Batetik, KB kontrolagailua: "urrutiko" cacheetara eraman diren "bertako" datu-blokeen egoerak gordetzen dituen direktorioa (oro har, egoerak bakarrik gordetzen dira, ez datuak, kanpoan egon daitekeen bloke kopurua oso handia izan daitekeelako).

• Bestetik, KU kontrolagailua: cache moduko bat, non "bertako" cacheetara ekarri diren "urrutiko" memorietako datu-blokeak gordeko diren (eskuarki, datuak eta egoerak, trafikoa zein latentzia txikiagotzeko asmoz, nahiz eta egoerekin nahikoa izan; hori dela eta, gailu handia da, datuak gordetzen baititu).

Nola erabili behar da hardware hori koherentzia mantentzeko? Ikus ditzagun adibide batzuk.

3.4.1. Irakurketak (hutsak)

Cache batean huts egin da aldagai bat irakurtzean. Beraz, BR kontrol-seinalea bidali behar da B1 busera, datu-bloke hori eskuratzeko. Bi aukera daude:

1. Bertako helbide-espaziokoa da aldagaia.

• Ez dago kopiarik kanpoan (beraz, KB-k ez du erantzuten): eragiketa arrunta da eta nodoaren barnean ebazten da (zelatari arrunta).

• Badago kopiaren bat kanpoan (beraz, KB-k erantzuten du):

- S egoeran: beraz, bertako MNan dagoen kopia zuzena da, eta hortik irakurriko da blokea.

- E egoeran: aurreko egoera bera da; hala ere, KB kontrolagailuak abisatu egin behar dio blokea duen nodoari, B2 busa erabiliz, bloke hori S egoeran jar dezan (irudiko (a) eta (b) mezuak).

- M egoeran: blokea aldatuta dago kanpoan. Blokea eskuratzeko eskaera B2 busean jarriko da. Ondorioz, blokea duen nodoko KU kontrolagailuak detektatuko du eskaera. Hau izango da haren lana: (i) bertako cacheari abisatu, blokea M-tik S-ra pasatzeko, B1 busa erabiliz; eta (ii) datu-blokea bidali eskatu duenari (KU-n bertan badago, hortik; bestela, dagoen cachetik).

▪ 116 ▪ 3. kapitulua: DATUEN KOHERENTZIA SMP KONPUTAGAILUETAN

Azkenean, eskaera sortu duen KB kontrolagailuak B2 busetik hartuko du blokea, eta B1 busean jarriko du, behar den cachean kargatzeko eta memoria nagusia eguneratzeko (irudiko 1, 2, 3, 4 eta 5 mezuak).

2. Urrutiko helbide-espaziokoa da aldagaia.

• KU-k ez du erantzuten. Beraz, ez dago bertako beste cacheetan. Eskaera B2 busera pasatzen da. B2ra konektatuta dagoen KB batek detektatuko du eskaera eta bus lokalean jarriko du. Erantzuna (blokea) MNtik zein cache batetik helduko da, eta B2 busera pasako da. Bitartean, KB eta KU kontrolagailuen informazioa eguneratuko da.

• KU-k erantzuten du: blokea bertako beste cache batean dago eta hortik hartuko da (S egoeran badago, ez da ezer gehiago egin behar; E egoeran badago, S egoeran jarri behar da eta urrutiko KB kontrolagailua egokitu; M egoeran badago, aurrekoaz gain, MNa eguneratu beharko da).

3.4.2. Idazketak

Ikus dezagun adibide bat: N1 nodoko P0k ST A eragiketa exekutatu behar du, S egoeran dagoen bloke batean. A aldagaia beste nodoko helbide-espaziokoa da (N3), eta, gainera, S egoeran dago beste nodo batean (N2).

Honela beteko da ekintza:

MN

CM

MN

KB KU KB

B1 B1

B2

CM CM CM

a

b

M→S

M→S

E→S

E→S

E→S

M→S

rd, hutsa

BR @

KU 5

3

2

4 1

I→S

@ →

3.4. ZELATARI HIERARKIKOA ▪ 117 ▪

1. Bertako kopia M egoeran jarri behar da, eta INV seinalea sortu behar da B1 busean.

2. N1 nodoko KU kontrolagailuak helbidea kanpokoa dela detektatzen du; beraz, INV seinalea B2 busera pasatuko du.

3. N2 nodoko KU kontrolagailuak baliogabetuko du haren kopia eta pasatuko du INV seinalea B1 busera (bertako kopiak baliogabetzeko).

3´. N3 nodoko KB kontrolagailuak datu-blokearen egoera aldatuko du, S-tik M-ra.

Oro har, memoria partekatua baina fisikoki banatua denean, datuen

koherentzia mantentzeko prozedura ez da sinplea. Erabili behar diren koherentzia-kontrolagailuak konplexuak eta handiak dira, eta, zoritxarrez, eragiketa osoaren latentzia (oso) handia izan daiteke, batik bat bertako nodoez kanpoko informazioa erabili behar denean. Gainera, koherentzia-eragiketen atomikotasuna ziurtatu behar da

Aurrekoa adibide bat besterik ez da izan. Izan ere, busen hierarkiak erabili beharrean beste motako sareak erabiltzen dira (mailak, esaterako). Eta sare horietan ezin da zelatatze motako estrategiarik erabili koherentzia mantentzeko. Beraz, beste irtenbide bat bilatu beharko dugu: koherentzia-direktorioak (ikus 7. kapitulua).

MN

CM

KB KU

MN

KB KU

MN

KB KU

S→M

1

2

3

CM CM CM CM CM

A

N1 N2 N3

B1 B1

B2

B1

S→I S→I S→I

S→I S→M

INV A

INV A

INV A INV A

INV A INV A

S→M

wr A

▪ 4 ▪

Prozesuen Sinkronizazioa SMP Konputagailuetan

4.1. SARRERA

MIMD motako konputagailuetan, programen exekuzioa hainbat prozesutan (haritan, azpiprogramatan...) banatzen da, eta prozesu horiek batera exekutatzen dira, paraleloan, sistemaren prozesadoreetan. Hala ere, programa horien exekuzioa ez da, eskuarki, erabat independentea, eta ohikoa da prozesu horiek haien artean komunikatu behar izatea, dela emaitzak batetik bestera eramateko, dela prozesuen exekuzioa sinkronizatzeko. Kapitulu honetan, paraleloan exekutatzen diren prozesuen sinkronizazioa aztertuko dugu, berriro ere P prozesadoreko SMP multiprozesadoreetan.

▪ 120 ▪ 4. kapitulua: PROZESUEN SINKRONIZAZIOA SMP KONPUTAGAILUETAN

Prozesuen arteko sinkronizazioaren arazoa zertan den azaltzeko, azter dezagun adibide soil bat. Demagun kode hau exekutatu behar dela, paraleloan, P1 eta P2 prozesadoreetan (hasieran, A = 021):

P1

... FST A(R0),F1 ... ...

P2

...

...

... FLD F4,A(R0)

Zer balio irakurriko du P2 prozesadoreak A aldagaian? Aldagai partekatua da A, bi prozesuetan erabiltzen delako, eta, beraz, datuak koherente mantentzeko hardwareak (zelatariak) ziurtatzen du P1 prozesadorean egindako aldaketa (ST) P2 prozesadorera zabalduko dela... baina ez digu esaten noiz!

Gainera, aurreko programaren esanahia ez da oso garbia. Badago datu-dependentzia bat (RAW) P1en eta P2ren artean A aldagaian? Hala bada, adierazi egin beharko da, aldez edo moldez, P1en egindako aldaketa "ikusi" baino geroago irakurri behar dela A aldagaia P2n. Modu berean jokatu beharko genuke antidependentzia balego, P2ko irakurketa P1eko idazketaren ondorioa ikusi baino lehen egin beharko baikenuke. Laburbilduz, A aldagaiaren erabilera sinkronizatu egin behar da, programak esanahi garbia eduki dezan. Oro har, gertaeren bidezko sinkronizazioa erabiltzen da kasu horietan, prozesu bati (kontsumitzaileari) beste prozesu batean (ekoizlean) datu bat sortu dela abisatzeko.

Sinkronizazioaren beharra hainbat egoeratan agertzen da. Azter dezagun beste adibide hau. Bi prozesuk aldagai bat partekatzen dute: KONT, kontagailu bat alegia. Prozesuek gehitu egiten dute kontagailuaren edukia: KONT := KONT + 1.

P1

... LD R1,KONT ADDI R2,R1,#1 ST KONT,R2 ...

P2

... LD R1,KONT ADDI R2,R1,#1 ST KONT,R2 ...

21 Kodea argiagoa izan dadin, helbideratze absolutua erabiliko dugu kapitulu honen adibideetan; nahi

izanez gero, ez dago batere arazorik beste bat erabiltzeko, indizeduna edo erlatiboa esaterako. Ohikoa den moduan, R0 erregistroaren edukia beti 0 da.

4.1. SARRERA ▪ 121 ▪

Zer balio izango du KONT aldagaiak bi kode zati horiek paraleloan exekutatu ondoren? Datu-koherentziaren arazoa konponduta ere, emaitza ez da garbia. Azter dezagun kasu hau: bi prozesuek bateratsu exekutatzen dute kode zati hori, KONT = 0 izanik, baina, denboran zehar ikusita, honela tartekatzen dira haien aginduak:

LD (P1) - ADDI (P1) - - ST (P1) LD (P2) - - ADDI (P2) - ST (P2)

Emaitza ustekabekoa da: KONT aldagaia bi aldiz gehitu bada ere, azkenean KONT = 1 geratuko da. Non dago arazoa? Aldagai partekatu hori modu desegokian atzitu da, tartekatu egin baitira P1 eta P2 prozesadoreen aginduak. Zein da irtenbidea? Kasu horretan ere, aldagaiaren atzipena sinkronizatu (ordenatu) egin beharko genuke programaren exekuzioa zuzena izan dadin, hau da, kode zati horiek modu ordenatuan exekutatzeko: lehenik prozesadore batean, eta gero bestean. Izan ere, nahiz eta bi prozesuak paraleloan exekutatu, kode zati horiek seriean exekutatu behar dira; edo, baliokidea dena, zati horien exekuzioak atomikoa behar du izan.

Aurreko adibidean, aldagai bakar bat partekatzen dute prozesuek, KONT, eta eragiketa sinple bat egiten da harekin (+1). Ohikoa da hori aplikazio paraleloetan, baina, oro har, eragiketa gehiago egiten dira partekatzen diren datuekin. Hori dela eta, prozesu paraleloen zenbait kode zati sekzio kritiko gisa definitu behar dira, eta kontrolatu, modu egokian, nola eta noiz ekin diezaiokeen prozesu jakin batek kode hori exekutatzeari; kontrol horretarako, sarrailak erabiltzen dira, baita, laster ikusiko dugun moduan, agindu bereziak ere.

Laburbilduz: programa bat P prozesadoreren artean exekutatu ahal izateko, hainbat kasutan, sinkronizatu egin behar da aldagai partekatuen erabilera. Hardwarearen zein softwarearen bidez konpon daiteke sinkronizazioaren arazoa. Hardwarez egiten bada, irtenbidea azkarra baina zurruna izango da; softwareaz (liburutegiaz) eginez gero, soluzio malguagoak lortuko ditugu. Bien arteko nahastea erabili ohi da: prozesadoreen agindu-multzoak agindu bereziak ditu sinkronizazio-funtzioak gauzatu ahal izateko, eta, makina-mailako agindu horiek erabiliz, hainbat sinkronizazio-errutina idazten dira, liburutegiko funtzio gisa erabiltzeko.

Bi dira sinkronizazio-behar nagusiak: elkarrekiko esklusioa (lock / unlock funtzioak) eta gertaeren bidezko sinkronizazioa (puntutik

▪ 122 ▪ 4. kapitulua: PROZESUEN SINKRONIZAZIOA SMP KONPUTAGAILUETAN

puntura, adierazleen bidez, edo globala, hesien bidez). Sinkronizazio-eragiketetan, prozesuek itxaron egin beharko dute ekintza jakin bat gertatu arte (sarraila irekita ikusi arte, gertaera bat gauzatu arte...). Itxarote-algoritmoak bi motakoak izan daitezke: itxarote aktiboak edo blokeoak. Itxarote aktiboan, prozesua begizta batean sartzen da, non aldagai bat (sarraila) behin eta berriz irakurriko den, balio jakin baten bila; bitartean, prozesadoreak ez du beste lanik egiten. Blokeoa erabiltzen bada, aldiz, prozesua blokeatu egiten da, eta sistema eragileak testuinguru-aldaketa bat egingo du beste prozesu bat exekutatzeko. Sistema eragileak berak "esnatuko" du prozesua, dagokion gertaera gertatu eta gero (edo prozesua bera itzuliko da noizean behin sinkronizazioaren egoera egiaztatzera). Bi mekanismoak, itxarote aktiboa eta blokeoa, egokiak dira, eta aplikazioaren eta makinaren ezaugarrien arabera (itxaron behar den denbora, testuinguru-aldaketaren latentzia, hari (thread) gehiago dagoen exekutatzeko...) aukeratuko da bata edo bestea. Sistema mistoa ere erabil daiteke: denbora jakin batean itxarotea eta, gero, baldintza bete ez bada, testuinguru-aldaketa bat egitea. Adibideetan, itxarote aktiboa erabiliko dugu.

Eskuarki, sistemako liburutegian datozen errutinak (dagoeneko optimizatuta) erabiliko ditu programatzaileak, baina, hala ere, ondo aztertu behar da errutina horien portaera, oso egoera desberdinetan erantzun egokia eman beharko baitute. Egoera horietakoak dira, esaterako, bi hauek: prozesadore bakar bat dago sarraila motako aldagai bat erabili nahian, edo P prozesadore daude, bateratsu, aldagai bera erabiltzeko asmoz. Litekeena da lehenbiziko egoeran ondo erantzuten duen sinkronizazio-funtzioa bigarrenean egokia ez izatea.

Sinkronizazioa ez da exekutatu nahi den algoritmoaren berezko ezaugarria, baizik eta algoritmo hori paraleloan, P prozesadoretan, exekutatu nahi delako sortzen den kontrol-komunikazio berria. Hori dela eta, portaera egokia eduki behar dute sinkronizazio-mekanismoek; besteak beste, ezaugarri hauek izan beharko lituzkete:

• Latentzia txikia: ahalik eta denbora gutxien erabili behar da sinkronizazioa betetzeko, edozein egoeratan; esaterako, prozesu batek ez du denbora galdu behar sekzio kritikoko sarrailan, baldin eta sarrera irekita badago eta sartzeko lehiarik ez badago.

• Trafiko mugatua: sinkronizazioa dela eta sortzen den datu-trafikoak ahalik eta txikiena izan behar du beti, komunikazio-sarea, busa, ez asetzeko.

4.2. ELKARREKIKO ESKLUSIOA (mutual exclusion) ▪ 123 ▪

• Hedagarritasun ona (scalability): latentziak zein trafikoak ez dute hazi behar (ez asko, behintzat) sistemako prozesadore kopuruarekin.

• Memoriako "kostu" txikia: sinkronizazioa antolatzeko erabili behar den aldagai kopurua (memoria) mugatuta mantendu behar da.

• Zuzentasuna: prozesu guztiek aukera berdinak izan behar dituzte sinkronizazioa betetzeko. Esaterako, ezin da onartu hau bezalako egoera (starvation): prozesu batek ez du inoiz lortzen sekzio kritikoa exekutatzea, baina, bitartean, gainerako prozesuek behin eta berriz exekutatzen dute kode hori.

Problema definituta, bada, azter ditzagun SMP sistemetan gehien erabiltzen diren sinkronizazio-estrategiak.

4.2. ELKARREKIKO ESKLUSIOA (mutual exclusion)

Elkarrekiko esklusioa erabiltzen da kode zati berezi baten exekuzioa kontrolatu behar denean, "seriean" exekuta dadin. Kode zati hori sekzio kritiko bat da, eta, definizio gisa, prozesu bakar batek exekutatu ahal izango du, une jakin batean, sekzio kritikoko kodea. Sekzio kritikoko kodea babesteko, lock eta unlock funtzioak erabiltzen dira, zeinetan sarraila motako aldagai bat erabiltzen baita (semaforo gisa).

Bi balio hartzen ditu sarrailak: 0 eta 1. Sarraila 0 denean (irekita), ez dago arazorik sekzio kritikoa exekutatzeko; 1 denean (itxita), ordea, ezin da igaro sekzio kritikoa exekutatzera, beste prozesu bat ari baita kode hori exekutatzen: itxaron egin behar da.

Bi funtzio exekutatzen dira sarrailaren gainean: sekzio kritikora sartzen den prozesuak sarraila ixten du (lock funtzioa), eta sekzio kritikoa uzten duenean, sarraila irekitzen du (unlock funtzioa). Sekzio kritikoan sartu baino lehen, prozesuek sarrailaren egoera aztertzen dute, eta zain geratzen dira itxita dagoen bitartean. Hala, bi funtzio horiek erabiliz, sekzio kritikoko kodea babestu egiten da, prozesuek banan-banan exekuta dezaten:

lock(…)

[ sekzio kritikoa ]

unlock(…)

Elkarrekiko esklusioa hardwareaz ere egin daiteke. Esaterako, buseko kontrol-lerro batzuk erabil daitezke sarrailak definitzeko (or-wired, sh

▪ 124 ▪ 4. kapitulua: PROZESUEN SINKRONIZAZIOA SMP KONPUTAGAILUETAN

seinalea bezala). Ohikoa da, ordea, lock eta unlock funtzioak bibliotekako funtzioak izatea. Ikus dezagun bi errutina horiek nola egin (SAR, sarraila-aldagaia).

lock(SAR) funtzioa lock: LD R1,SAR BNZ R1,lock ; jauzi baldin "ez zero"

ADDI R2,R0,#1 ; R2 := 1 ST SAR,R2 ; itxi sarraila RET

unlock(SAR) funtzioa unlock: ST SAR,R0 RET

Sekzio kritikoan sartu baino lehen, sarraila irekita dagoen aztertzen da. Itxita badago (SAR = 1), zain geratzen gara begizta batean, sarraila behin eta berriz aztertzen; irekita badago (SAR = 0), sarraila itxi eta sekzio kritikora igaroko gara. Unlock funtzioa, sarraila irekitzea, sinplea da, nahikoa baita 0ko bat idaztea SAR aldagaian.

Tamalez, aurreko errutinak prozesadore bakarreko sistemetan (exekuzio-denbora nola banatzen den) egokiak izan badaitezke ere, ez dute ondo funtzionatzen multiprozesadoreetan. Zein da aurreko errutinen arazoa? Sekzio kritikoak duen bera, atomikotasun eza. SAR aldagaiaren erabilera (irakurri eta idatzi) ez da atomikoa, eta, beraz, ezin da ziurtatu prozesu bakar batek lortuko duela sekzio kritikoan sartzea. Jakina, programen exekuzioaren kontrol zentralizatua ez izatea da arazoaren iturburua, paraleloan ari baitira eta guztiz independenteki.

Sekzio kritikoak kudeatu ahal izateko, aldagai (sarraila) baten irakurketa/idazketa prozesua modu atomikoan betetzen duten aginduak behar ditugu: RMW (read-modify-write) motako aginduak. Eskuarki, eragiketaren atomikotasuna bermatzeko, horietako agindu bat exekutatzen ari den bitartean, memoria-sistemaren kontrolagailuak blokeatu egingo du erabiltzen ari den memoria-hitzerako edozein atzipen (beste prozesadoreenak).

RMW motako zenbait agindu atomiko garatu dira, eta oraingo prozesadoreen agindu-multzoan agindu horietako bat (edo gehiago) dago. Izan ere, prozesadore guztiak daude prestatuta multiprozesadore batean lan egin ahal izateko, eta beharrezko dira agindu horiek memoria partekatuko inguruneetan, aldagai partekatuak egoki erabiltzen direla ziurtatzeko. Azter ditzagun, bada, aukera nagusiak.

4.2. ELKARREKIKO ESKLUSIOA (mutual exclusion) ▪ 125 ▪

4.2.1. Test&Set eta Swap aginduak

Sarrailak kudeatzeko aurreneko aukera gisa, baliokideak diren bi agindu analizatuko ditugu. Bietan, RMW motako eragiketa bat betetzen da: memoria-posizio (aldagai) baten irakurketa eta idazketa atomikoa, beste prozesadoreen interferentziarik gabe.

4.2.1.1. Test&Set agindua

RMW motako eragiketa atomikoa da, zaharrena, eta hau egiten du:

▪ T&S R1,SAR R1 := MEM[SAR]; MEM[SAR] := 1;

Hau da, aldagai bat irakurtzen da (sarraila), eta 1eko bat idazten da aldagai horretan, memorian. T&S agindua erabiliz, honela idatz daitezke sarraila baten bi funtzioak

(itxi eta ireki):

lock: T&S R1,SAR BNZ R1,lock

RET

unlock: ST SAR,R0 RET

T&S aginduak ziurtatzen du prozesu bakar batek irakurriko duela SAR = 0, horrekin batera, atomikoki, 1eko bat idatziko baita aldagai horretan; beraz, gainerakoek SAR = 1 (itxita) irakurriko dute, eta itxarote-begiztan jarraitu beharko dute.

Sekzio kritikoa uztean, sarraila ireki behar da, eta horretarako nahikoa da 0ko bat idaztea SAR aldagaian, modu arruntean (prozesu bakarra baitzegoen sekzio kritikoan).

4.2.1.2. Swap agindua

Swap agindua T&S aginduaren antzekoa da, baina erregistro baten edukia gordetzen du memorian, konstante bat idatzi beharrean. Izan ere, memoriako posizio baten eta erregistro baten arteko edukien trukea egiten du:

▪ SWAP R1,SAR R1 ↔ MEM[SAR]; (exchange)

Beraz, lock bat osatzeko, nahikoa da 1eko bat erregistro batean kargatuta izatea. Honela izango dira lock eta unlock errutinak:

▪ 126 ▪ 4. kapitulua: PROZESUEN SINKRONIZAZIOA SMP KONPUTAGAILUETAN

lock: ADDI R1,R0,#1 ; R1 := 1

l1: SWAP R1,SAR BNZ R1,l1

RET

unlock: ST SAR,R0 RET

4.2.1.3. Trafikoaren analisia

Ikusi dugunez, RMW motako agindu atomikoak erabiliz eta lock eta unlock motako errutinen bidez, ez dago arazorik sekzio kritikoak antolatzeko. Hala ere, aztertu egin behar dugu modu eraginkorrean egiten den. Aipatu bezala, sinkronizazio-eragiketak latentzia txikikoa izan behar du, trafiko gutxi sortu, baliabide gutxi erabili, eta zuzentasunez jokatu eskaera guztiekin, eta hori guztia, ahal den neurrian, prozesadore/prozesu kopuruarekiko independente.

Zoritxarrez, ez da hori gertatzen azaldu ditugun errutinekin. Azter dezagun berriro T&S eragiketa; datuen koherentzia mantentzeko, MESI protokolo bat (baliogabetzekoa) erabiliko dugu (ondorioak antzekoak dira eguneratze-protokoloekin). T&S agindua exekutatzen den bakoitzean, idazketa bat egiten da aldagai partekatu batean, sarrailan, alegia. Sarraila-aldagaia S (shared) egoeran egongo da cachean, eta, idatziko denez, balizko kopia guztiak baliogabetu beharko dira, koherentzia mantentzeko (zelataria). Horrek ez du arazo handirik sortzen une horretan bakarrik baldin bagaude sekzio kritikoan sartu nahian; aldiz, sekzio kritikoan sartzeko prest prozesu asko badago, hurrengo saioak, prozesadore guztietan, cacheko hutsegiteak izango dira (sarraila baliogabetu egin da). Ondorioz, prozesadore guztiak, ia batera, sarraila-aldagaia duen blokea eskatuko dute eta datu-trafiko handia izango da busean: atzipen-gatazka asko izango dira eta, ondorioz, sarraila eskuratzeko latentziak (oso) handiak izango dira.

Hurrengo irudian, egoera horren simulazio bat ageri da. Hasieran, P0 prozesadorea sekzio kritikoan dago, eta badaude lau prozesadore sekzio kritikoan sartu nahian. Une jakin batean, P0 prozesadoreak sekzio kritikoa utzi behar du eta, beraz, SAR = 0 idazten du (unlock), eta, horrekin batera, SAR aldagaiaren kopia guztiak baliogabetzen ditu. Ondorioz, zain dauden prozesu guztiek, bateratsu, SAR aldagaia duen blokea eskatuko dute (BRQ, bus request) T&S agindua exekutatu ahal izateko (hutsegite bat cachean). T&S agindua atomikoa denez, busaren kontrolagailuak modu ordenatuan zerbitzatuko ditu eskaerak (FIFO moduan irudian). Atomikotasuna irudikatzeko, [ ] ikurren artean jarri ditugu T&S eragiketak.

4.2. ELKARREKIKO ESKLUSIOA (mutual exclusion) ▪ 127 ▪

Sekzio kritiko baterako sarreraren simulazioa Sinkronizazioa: Test&Set (TS)

BRQ = bloke baten eskaera / x = baliogabetuta / datu-bloke baten transmisioa

P0 S=0 INV

P1 ? x [TS BRQ TS INV] x SEKZIO KRITIKOA

P2 ? x [TS BRQ. . . . . . . . . . . . TS INV] [TS. . . . x BRQ. . . . . . . . . TS INV] [TS. . . . x BRQ. . . . . . . . . .

P3 ? x [TS BRQ. . . . . . . . . . . . . . . . . . . . . . . TS INV] [TS . . . x BRQ. . . . . . . . . . . TS INV] [TS. . . . x BRQ. .

P4 ? x [TS BRQ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . TS INV] [TS. . . . . x BRQ. . . . . . . . . . TS INV] [TS. .

hainbat aldiz errepikatu

Datu-trafikoa (blokeka) Prozesadore bat sekzio kritikora sartzeko → P + (P – 1) × k aldiz Prozesadorea sekzio kritikotik ateratzeko → 1

Simulazioaren ondorioa garbia da; sekzio kritikoa okupatuta mantentzen den bitartean, sartu nahi duten prozesuek behin eta berriz baliogabetuko dute sarraila duen datu-blokea, eta, ondorioz, behin eta berriz transmititu beharko da bloke hori, hau da, trafiko handia sortuko da busean. Ez ahaztu hori ez dela exekutatzen ari den algoritmoari dagokion berezko trafikoa, baizik eta paraleloan exekutatu nahi delako sortutako trafiko berria.

Beraz, aurreko lock funtzioa lehia (contention) gutxiko egoeretan ondo badabil ere, partekatze handiko egoeretan asko degradatzen da: ez da "eskalagarria" (scalable). Hala ere, hobekuntza batzuk egin daitezke sekzio kritikora sartzea ahalbidetzen duen lock errutinan, latentzia eta trafikoa murrizteko. Ikus ditzagun.

4.2.1.4. Test&Set with backoff prozedura

Buseko trafikoaren sorburua T&S eragiketetan datza (idazketa bat egiten da beti). Beraz, trafikoa gutxiagotzeko asmoz, T&S agindua exekutatzen den aldi kopurua gutxiagotu beharko genuke.

Lehen aukera gisa, honako hau egin daiteke: denbora jakin bat itxaron ondoz ondoko bi T&S eragiketen artean.

T&S – [ ... ] – T&S – [ ... ] – ...

▪ 128 ▪ 4. kapitulua: PROZESUEN SINKRONIZAZIOA SMP KONPUTAGAILUETAN

hau da, une jakin batean sekzio kritikora igaro ezin bada, ez saiatu behin eta berriz sartzen, buseko trafikoa handiagotzea baino ez baita lortuko, eta itxaron tarte batez, sekzio kritikoa aska dadin denbora emateko.

Itxarote-denborak ez du oso luzea izan behar (bestela, litekeena da prozesadorea ezer egin gabe uztea, sarraila dagoeneko ireki denean), ezta oso txikia ere (sartzeko alferrikako saioak ez egiteko). Beraz, erdibidekoa izan behar du: nahikoa luze, trafikoa gutxitzeko, baina ez gehiegi, denbora alferrik ez galtzeko. Hainbat esperimentutan egiaztatu egin da emaitza onak lortzen direla denbora hori esponentzialki aldatzen denean: ti = k ci (k eta c, bi konstante; eta i, sekzio kritikoan berriro sartzeko egin den saio kopurua: 0, 1, 2...); hau da:

t0 = k t1 = k c t2 = k c2 ... (c > 1)

Teknika horri Test&Set with backoff deritzo. Honela izango dira sarraila kontrolatzen duten errutinak:

lock: T&S R1,SAR BNZ R1,zain

RET zain: CALL ITXOIN(t1) ; t1 = itxarote-denbora [t1 := ...] ; t1 berria kalkulatu JMP lock unlock: ST SAR,R0 RET

4.2.1.5. Test-and-Test&Set prozedura

Ikus dezagun trafikoa gutxitzeko bigarren aukera. T&S egiten den bakoitzean, 1eko bat idazten da memorian... memoriaren edukia 1eko bat izanagatik! Zergatik egin beti alferrikako idazketa hori sarraila irakurtzen den bakoitzean? Ez ahaztu: 1eko bat idazten dugu 1eko bat duen memoria-posizio batean.

Hau da ideia: banatu lock errutina bi fasetan. Lehenengoan, sarrailaren balioa aztertzen da, eta, horretarako, nahikoa da irakurketa arrunt bat (LD);

4.2. ELKARREKIKO ESKLUSIOA (mutual exclusion) ▪ 129 ▪

fase hori errepikatu egiten da, behin eta berriz, sarraila irekita aurkitu arte. Sarraila irekita dagoenean, bigarren faseari ekiten zaio: T&S agindua exekutatzen da, orain bai, sarraila modu atomikoan ixten saiatzeko. Prozesu bakar batek lortuko du sekzio kritikoan sartzea; gainerakoak aurreneko fasera itzuliko dira, sarraila berriz aztertzera. Ondorioz, sarraila irekitzen denean, prozesu bakoitzak behin bakarrik idatziko du sarrailan.

Sekzio kritikoan sartu nahian dauden prozesuek, beraz, ez dute trafikorik sortzen sarraila itxita dagoen bitartean. Izan ere, sarraila-aldagaiaren baliogabetzeak (eta, ondorioz, datu-blokea irakurri behar izatea) bitan besterik ez dira gertatuko: prozesu batek sarraila ixten duenean (1eko bat idazten du sarrailan), eta sarraila irekitzen duenean (0ko bat idazten du) sekzio kritikoa uztean.

Estrategia horri Test-and-Test&Set deritzo. Hauek dira lock eta unlock errutinak estrategia hori erabiliz:

lock: LD R1,SAR ; test fasea BNZ R1,lock

T&S R1,SAR ; test-and-set fasea BNZ R1,lock

RET

unlock: ST SAR,R0 RET

T&S aginduaren erabilera sinpleenarekin alderatuta, sinkronizazioak

sortutako trafikoa asko mugatzen da Test-and-Test&Set prozedurarekin. Hurrengo irudian, sinkronizazio mota horren simulazio bat egin da. Hasieran, prozesu guztiak test fasean daude (LD). Sarraila irekitakoan, prozesu guztiek sarraila duen datu-blokea eskatu dute, baliogabetu egin baita haien cachean. Denek ikusiko dute sarraila irekita dagoela (SAR = 0), eta T&S agindua exekutatuko dute, atomikoki, baina bakar batek lortuko du sekzio kritikoan sartzea. Besteak test fasera itzuliko dira, T&S agindua exekutatu dutenean sarraila berriro itxita aurkitu dutelako (sartu denak itxi egin baitu).

▪ 130 ▪ 4. kapitulua: PROZESUEN SINKRONIZAZIOA SMP KONPUTAGAILUETAN

Sekzio kritiko baterako sarreraren simulazioa Sinkronizazioa: Test-and-Test&Set

BRQ = bloke baten eskaera / x = baliogabetuta / datu-bloke baten transmisioa

P0 S=0 INV

P1 LD x BRQ LD [TS . . . . . . . . . TS INV] x SEKZIO KRITIKOA

P2 LD x BRQ. . . . . LD [TS . . . . . . . . . x BRQ TS INV] LD. . . . x BRQ. . . . . . . . . . LD . . . . . . . . .

P3 LD x BRQ. . . . . . . . . . . . LD [TS . . . . x BRQ. . . . . . . . . . . . TS INV] LD . . . . x BRQ. . LD . . . . .

P4 LD x BRQ. . . . . . . . . . . . . . LD [TS x BRQ. . . . . . . . . . . . . . . . . . . . . . . . . TS INV] LD . . . . . . . . . . . . . .

Datu-trafikoa (blokeka) Prozesadore bat sekzio kritikora sartzeko → P + (P – 1) + (P – 2) Prozesadorea sekzio kritikotik ateratzeko → 1 Guztira → 3P – 2

P prozesadoreak sartzeko → 2

32

)13()23(2

1

PPPPP

p→

−=−∑

=

Ikus daitekeenez, trafikoa P2 ordenakoa da, P izanik sekzio kritikoan

sartzeko lehian dagoen prozesu kopurua. Ez da, beraz, oso eskalagarria, eta busa nahiko azkar ase egingo da, prozesadore kopurua handia den neurrian. Gainera, une jakinetan sortzen da trafiko osoa; prozesadore guztiek batera huts egiten dute cachean, sarraila irekitzen denean, eta, une horretan, bloke asko transferitu beharko da (kasu honetan ez du zentzurik itxarote-denborak sartzeak, T&S eragiketa behin baino ez baita exekutatzen).

4.2.1.6. Ezaugarrien laburpena

Ikusi dugunez, T&S motako sinkronizazio-funtzio sinpleenak sinkronizazio-trafiko handia sortzen du, baldin eta, sekzio kritikoa okupatuta dagoen bitartean, hara sartzeko eskaera asko badago. Baina, bestalde, oso egokia da lehia gutxiko egoeretan: ez du trafikorik sortzen, eta, gainera, sekzio kritikora sartzeko latentzia txikia da, agindu gutxi exekutatzen baitira.

Memoria gutxi erabiltzen da, nahikoa baita aldagai bat sarraila bakoitzeko; beraz, memoria-beharra ez da hazten lehiakide kopuruarekin. Zuzentasunaren ikuspuntutik aztertuta, estrategiak berak ez du inongo

4.2. ELKARREKIKO ESKLUSIOA (mutual exclusion) ▪ 131 ▪

esleitze-politikarik erabiltzen, eta, beraz, buseko kontrolagailuko lehentasun-irizpideen arabera izango da prozesu batek sekzio kritikoan sartzeko itxaron beharko duen denbora (esaterako, FIFO bada, denbora hori mugatuta egongo da).

Laburbilduz, T&S estrategia soila sekzio kritikoa partekatzen duten prozesu kopurua txikia denean baino ez da egokia (edo, oro har, sistemako prozesadore kopurua txikia denean). Izan ere, oso gaizki eboluzionatzen du prozesadore kopuruarekin.

T&S-BO estrategiak antzeko portaera erakusten du, baina trafiko gutxiago sortzen du eta, ondorioz, eskalagarriagoa da.

Test-and-T&S mekanismoa da hiruretan egokiena. Lehia handiko egoeretan sortzen den sinkronizazio-trafikoa mugatua da; hala ere, gatazkarik gabeko egoeretan, aurreko bi estrategiak baino latentzia handiagoa du sekzio kritikoan sartzeko, LD [test fasea] eta T&S [test-and-set fasea] exekutatu behar baitira.

Azken ohartxo bat lock errutinen eraikitzeari buruz. Eraman behar al da cachera Test&Set eragiketetan erabiltzen den sinkronizazio-aldagaia (sarraila), edo hobe da memoria nagusian mantentzea? Badakigu egokia dela erabili behar ditugun aldagaiak cachera eramatea, baina sarraila-aldagaia irakurtzean behin eta berriro huts egiten badugu, baliogabetuta dagoelako, eta, ondorioz, behin eta berriro datu-bloke osoa transferitu behar badugu MNtik CMra, agian egokiago litzateke MNan uztea eta kopiak ez egitea. Hori bai, MNan egingo genituzke atzipen guztiak; beraz, lehia gutxiko egoeretan, latentzia handiagoa izango litzateke.

4.2.2. Load Locked / Store Conditional eta Compare&Swap aginduak

Aipatu dugu, dagoeneko, Test-and-T&S estrategiak duen arazoa: T&S agindua exekutatzen dutenean, prozesu guztiek idazten dute sarrailan: aldagai horren kopiak hainbat aldiz baliogabetuko dira eta trafikoak gora egingo du, datu-blokeak ia batera eskatuko baitira. Sinkronizazioak sortutako trafikoa handia izatea ezin da onartu prozesadore kopurua handia denean. Beraz, zerbait egin behar da trafikoa gutxiagotzeko, eta horretarako murriztu egin beharko genuke sarrailan egiten den idazketa kopurua. Beste mota bateko agindu atomikoak behar ditugu.

▪ 132 ▪ 4. kapitulua: PROZESUEN SINKRONIZAZIOA SMP KONPUTAGAILUETAN

4.2.2.1. LL eta SC aginduak

Ohikoa da, oraingo prozesadoreetan, sinkronizaziorako behar diren eragiketa atomikoak bi agindutan banatzea; bi agindu horiek erabiliz, RMW eragiketa bat osa daiteke. Aginduez gain, irakurketa/idazketa eragiketaren exekuzioa atomikoa izan den ala ez jakiteko, hardwareko adierazle bat erabiltzen da. Sinkronizaziorako erabiltzen diren bi agindu berri horiek LL —Load Locked (edo linked)— eta SC —Store Conditional— deitzen dira.

LL aginduak memoria irakurtzen du, baina albo-ondorio batekin: sinkronizaziorako bakarrik erabiltzen den latch berezi batean (SinL deituko dugu), atzitu den helbidea eta adierazle edo flag berezi bat gordetzen dira, memoria-posizio hori modu berezian atzitu dela adierazteko.

▪ LL R1,SAR R1 := MEM[SAR]; SinL[helb] := SAR; SinL[adi] := 1;

SC agindua baldintzapeko memoria-idazketa bat egiten saiatzen da. Horretarako, SinL latch berezia aztertzen da. Idatzi behar den helbidea eta hari dagokion adierazlea aktibatuta badaude, idazketa egiten da eta baliogabetze-seinale berezi bat bidaltzen da busera, helbide horrekin elkartuta dauden sinkronizazio-adierazleak desaktibatzeko (SinL latch guztietan). Aldiz, adierazlea desaktibatuta badago, ez da ezer egiten (ez da idazten). Bi kasuetan, SC aginduak kode bat itzultzen du, eskuarki idazteko erabili den erregistro berean, zer gertatu den adierazteko: idatzi da ala ez da idatzi.

▪ SC SAR,R1 baldin (SinL[helb,adi] = SAR,1) { MEM[SAR] := R1; SinL[adi] := 0; (INV, denak) R1 := 1; (idatzi da) } bestela R1 := 0 (ez da idatzi)

Ikus dezagun nola erabili behar den agindu bikote hori sekzio kritikorako sarrera kudeatzeko. Hiru (edo bi) fase bereizten dira LL/SC aginduen bidezko sinkronizazioan:

1. LL aginduak sinkronizazio-aldagaia (sarraila) irakurtzen du. Horrekin batera, atzitu den helbidea gorde eta sinkronizazio-adierazlea pizten du, sinkronizazio-latch berezian.

2. Beharrezkoa izanez gero, kalkulua edo aldagai batzuen prozesamendua egiten da.

4.2. ELKARREKIKO ESKLUSIOA (mutual exclusion) ▪ 133 ▪

3. SC agindua idazten saiatzen da, sinkronizazio-aldagaian (eskuarki, 2. fasean prozesatu dena). Helbide horri dagokion sinkronizazio-adierazlea aktibatuta badago, idatzi egiten da, eta baliogabetze-seinale bat bidaltzen da, sarraila aldagaiaz gain, helbide/adierazle hori prozesadore guztietan ezabatzeko: eragiketa osoa, [LL — SC], modu atomikoan bete da, interferentziarik gabe.

Bestela, sinkronizazio-adierazlea desaktibatuta badago, ez da idazten, beste prozesu batek idatzi baitu, tartean, helbide horretan (horregatik baliogabetu da LL aginduarekin aktibatutako adierazlea). [LL — SC] eragiketa ez da modu atomikoan exekutatu, eta, beraz, atzera egin behar da, prozesu osoa berriz egiteko. SC aginduak idatzi ez duenez, ez da baliogabetzerik, ezta, ondorioz, datu-trafikorik, sortuko.

Laburbilduz, SC agindua ondo bukatzen bada, [LL — SC] kode zatia modu atomikoan exekutatu da (adi! horrek ez du esan nahi LL eta SC aginduen arteko aginduek sekzio kritiko bat osatzen dutenik).

Agindu bikote hori erabiliz, honela egin daitezke lock eta unlock errutinak:

lock: ADDI R2,R0,#1 ; R2 := 1

l1: LL R1,SAR ; sarraila aztertu BNZ R1,l1

...

SC SAR,R2 ; saiatu sarraila ixten BZ R2,lock ; SC ez bada bete, atzera jo RET

unlock: ST SAR,R0 RET

Test-and-T&S estrategiarekin gertatzen den bezala, kasu honetan ere

itxarote-begiztak (LL) ez du trafikorik sortzen (irakurketa soila da, test fasea bezala). Hobekuntza bigarren partean dator: test-and-set fasean, beti idazten da, berdin da sarraila nola dagoen; SC aginduak, aldiz, sarraila irekita dagoenean bakarrik idazten du memorian (hau da, LL exekutatu zenetik, aldagai hori inork aldatu ez badu). Beraz, ez da trafikorik sortzen busean, bi kasutan izan ezik: sekzio kritikoan sartzeko (SC agindua betetzen denean, sarraila ixteko), eta sekzio kritikotik irteteko (sarraila askatzeko).

▪ 134 ▪ 4. kapitulua: PROZESUEN SINKRONIZAZIOA SMP KONPUTAGAILUETAN

Hurrengo irudian, prozedura horren simulazio bat ageri da. Ikus daitekeenez, SC agindu bakar batek idazten du memorian, lehenbizikoak; gainerako kasuetan ez da idazten, LL aginduarekin aktibatutako adierazlea baliogabetuta geratu delako. Datu-trafikoa busean, beraz, jaitsi egin da. Hala ere, trafikoa oraindik handia da, eta ez da inongo zuzentasunezko estrategiarik erabiltzen. Beraz, kasu honetarako ere, hainbat hobekuntza egin daitezke.

Sekzio kritiko baterako sarreraren simulazioa Sinkronizazioa: LL / SC

BRQ = bloke baten eskaera / x = baliogabetuta / datu-bloke baten transmisioa

P0 S=0 INV

P1 LL x BRQ LL(1) [SC . . . . . .SC INV] SEKZIO KRITIKOA

P2 LL x BRQ. . . . . LL(1) [SC . . . . . . . (0)x BRQ SC] LL. . . . . . . . . . . .

P3 LL x BRQ. . . . . . . . . . . . LL(1) [SC . . . (0)x BRQ. . . . . SC] LL . . . . . . .

P4 LL x BRQ. . . . . . . . . . . . . . LL(1) [SC (0)x BRQ. . . . . . . . SC] LL . . .

Datu-trafikoa (blokeka) Prozesadore bat sekzio kritikora sartzeko → P + (P – 1) Prozesadorea sekzio kritikotik ateratzeko → 0 Guztira → 2P – 1

P prozesadoreak sartzeko → 2

1)12( PP

P

p∑=

=−

4.2.2.2. Compare&Swap agindua

Hobekuntzekin hasi baino lehen, ikus dezagun beste agindu atomiko bat, aurreko bikotearen ildo berean: Compare&Swap agindua. Honako eragiketa hau betetzen du C&S aginduak, modu atomikoan:

▪ C&S R1,R2,SAR baldin (R1 = MEM[SAR]) orduan MEM[SAR] ←→ R2

Beraz, memoriako idazketa konparazioa betetzen denean baino ez da egiten, ez beti. Aurreko kasuan hardwareko adierazle berezi batez lortzen zena, kasu honetan konparaketa batean sortzen den adierazle arrunt batekin lortzen da.

4.2. ELKARREKIKO ESKLUSIOA (mutual exclusion) ▪ 135 ▪

Hau da sarraila kontrolatzeko kodea C&S agindua erabiliz:

lock: ADDI R2,R0,#1 ; R2 := 1

l1: C&S R0,R2,SAR ; ez du beti idazten BNZ R2,l1 ; R2 = 1 → ez da idatzi

RET

unlock: ST SAR,R0 RET

C&S agindua aurrekoak baino konplexuagoa da, bi erregistro eta memoria-posizio bat erabiltzen dituelako (hiru eragigai, beraz, memoria-eragiketa batean). RISC motako hainbat arkitekturatan ez da formatu hori erabiltzen; hori dela eta, ohikoagoa da LL/SC bikotea erabiltzea.

4.2.2.3. Zenbait arazo LL eta SC aginduekin

LL eta SC aginduek hardwarearen laguntza behar dute haien funtzioa betetzeko. Batetik, prozesadore bakoitzak latch berezi bat izan behar du atzitu den helbidea eta adierazlea gordetzeko, eta, bestetik, memoriako/buseko kontrolagailuak ere parte hartu behar du atomikotasuna bermatzeko. LL exekutatzen denean, irakurri den aldagaiaren helbidea latch-ean gordetzen da, eta dagokion adierazlea aktibatzen da. Hortik aurrera, kontrolagailuak busa zelatatu beharko du; beste prozesadore batek aldagai horretan idazten duela detektatzean, LL aginduarekin aktibatutako adierazlea ezabatu egingo du. Gauza bera egin behar da, halaber, sinkronizazio-aldagaia duen blokea ordezkatzen denean edo testuinguru-aldaketetan. SC agindua exekutatu behar denean, helbide/adierazleak gordetzen dituen

latch-a aztertuko da. Adierazlea aktibatuta badago, ez dago arazorik: idatzi egingo da, eta helbide horri dagokion adierazlea desaktibatzeko seinalea bidaliko da prozesadore guztietara. Bestela, desaktibatuta badago, bertan behera utziko da SC agindua, eta dagokion errore-kodea itzuliko da. Protokolo hori ondo gauzatu behar da, livelock, deadlock eta bestelako arazoak ekiditeko. Esaterako, livelock arazoa (hau da, aurrera eta atzera ibiltzea, baina ezer gauzatu gabe) ager daiteke honako hau gertatuko balitz: LL – SC (hutsa) – LL – SC (hutsa) – ... (adibidez, sarraila duen blokea ordezkatzen delako).

▪ 136 ▪ 4. kapitulua: PROZESUEN SINKRONIZAZIOA SMP KONPUTAGAILUETAN

Arazoak ekiditeko, sarraila duen datu-blokea ez da ordezkatu behar sinkronizazio-eragiketa egiten ari den bitartean. Hori lortzeko, gomendatu egiten da LL eta SC aginduen artean memoria-agindurik ez exekutatzea, datu-bloke berriak cachean kargatu behar ez izateko (eta, ondorioz, ordezkapenak saihesteko).

Bestalde, nahiz eta datuak eskuratu behar ez, segur aski LL-ren eta SC-ren artean agindu gehiago izango dugu, baina, datu-cachea eta agindu-cachea banatuta egon ohi direnez, agindu horiek ez dute eraginik izango sarraila duen datu-blokean. Hala ere, egokia da LL-ren eta SC-ren artean agindu gutxi exekutatzea, hau da, sinkronizazio-eragiketa ahalik eta lasterren bukatzea, gainerako prozesuek denbora izan ez dezaten tartean sarrailan idazteko eta, ondorioz, gure sinkronizazio-eragiketa bertan behera uzteko.

4.2.3. Fetch&Op aginduak

Lehen ikusi dugunez, hainbat kasutan oso eragiketa sinpleak egin behar dira partekatzen diren aldagaiekin. Hori dela eta, eragiketa horiek atomikoki exekutatzen duten agindu bereziak daude: Fetch&Op motako aginduak. RMW motako aginduen kasu orokorra dira: memoriako hitz bat irakurri, prozesatu (op), eta berriro memorian idatzi. Mota horretako agindu bat baino gehiago dago, egiten den eragiketaren arabera; esaterako:

▪ Fetch&Incr R1,ALD R1 := MEM[ALD]; MEM[ALD] := MEM[ALD] + 1;

▪ Fetch&Dcr R1,ALD R1 := MEM[ALD]; MEM[ALD) := MEM[ALD] – 1;

▪ Fetch&Add R1,R2,ALD R1 := MEM[ALD]; MEM[ALD] := MEM[ALD] + R2;

Adibidez, KONT aldagaiaren balioa gehitu behar bada modu atomikoan, nahikoa da agindu hau exekutatzea:

Fetch&Incr R1,KONT

KONT aldagaiaren balioa R1 erregistroan utzi da, eta, horrekin batera, memoriaren edukia gehitu da. Hau da, KONT = 6 bazen, agindua exekutatu ondoren R1 = 6 eta KONT = 7 izango dira.

4.2. ELKARREKIKO ESKLUSIOA (mutual exclusion) ▪ 137 ▪

Elkarrekiko esklusioan exekutatu behar den eragiketa konplexuagoa bada, ohiko sekzio kritiko bat antolatu beharko da; agindu horiek erabiliz lock eta unlock funtzioak egin badaitezke ere, ohikoago da lantegi horretarako beste motako agindu atomikoak erabiltzea.

4.2.4. Trafikoa murrizteko hobekuntzak

Lehen aipatu dugunez, LL/SC aginduak erabiliz, sekzio kritikora sartzeko lehian dauden prozesadoreek trafiko gutxiago sortzen dute lock errutina exekutatzean. Baina, hala ere, hobekuntza batzuk egin daitezke oraindik. Azter ditzagun hobekuntza horiek.

4.2.4.1. Txartelak

Sekzio kritikorako sarrera "txartelen" bidez kontrolatu daiteke trafikoa gutxiagotzeko asmoz. Ideia sinplea da. Sekzio kritikora sartu nahi duen prozesuak txartel (ticket) bat eskuratu behar du lehenik, non bere txanda-zenbakia adieraziko zaion. Gero, zain geratuko da txanda heldu arte. Txanda heltzean, sekzio kritikorako bidea libre izango du, eta berak bakarrik, bere txanda baita. Sekzio kritikoa uztean, txanda-zenbakia gehitu egingo du, hurrengo prozesuari bidea irekitzeko.

Txartelen bidezko estrategiarekin ez da lehiarik sortzen sekzio kritikoan sartzeko, sarrera guztiak ordenatu direlako, eta, ondorioz, trafikoa murriztu egiten da. Hala ere, bi aldagai partekatu erabili behar dira: bata, txartelak banatzen dituena, kontagailu bat, hain zuzen ere; eta, bestea, txanda-zenbakia adierazten duena.

Txartelak banatzeko erabiltzen den kontagailua elkarrekiko esklusioan erabili behar da, eta horretarako, adibidez, Fetch&Incr agindu atomikoa erabil daiteke, edo, bestela LL/SC bikotea. Esaterako,

F&I R1,TXARTELA ; R1 := MEM[TXARTELA]; ; MEM[TXARTELA]:= MEM[TXARTELA]+ 1

edo, baliokidea dena:

tx: LL R1,TXARTELA ; eskuratu zure txartela ADDI R2,R1,#1 ; gehitu txartel-zenbakia hurrengorako SC TXARTELA,R2 ; baina modu atomikoan! BZ R2,tx ; errepikatu eragiketa atomikotasuna lortu arte

▪ 138 ▪ 4. kapitulua: PROZESUEN SINKRONIZAZIOA SMP KONPUTAGAILUETAN

Bata edo bestea erabiliko dugu, prozesadoreak erabil ditzakeen agindu atomikoen arabera.

Honela geratuko dira, azkenik, lock eta unlock errutinak22: lock: F&I R1,TXARTELA ; eskuratu zure txanda-zenbakia

itx: LD R2,TXANDA SUB R3,R1,R2 BNZ R3,itx ; itxaron zure txanda heldu arte

RET

unlock: LD R1,TXANDA ; txanda eguneratu behar da ADDI R1,R1,#1 ST TXANDA,R1 ; ireki bidea hurrengoari RET

Hurrengo irudian (pixka bat aurrerago), estrategia horren simulazio bat

ageri da. Prozesuek txartel bana lortu dute dagoeneko, eta zain daude sekzio kritikoan sartzeko. Behin bakarrik sortzen da trafikoa: sekzio kritikoan dagoen prozesadoreak txanda-zenbakia gehitzen duenean, sekzio kritikotik ateratzean. Horrekin batera, kontuan hartu beharko genuke, halaber, txartela eskuratzeko sortzen den trafikoa: kasu guztietan, TXARTELA aldagaia duen datu-blokea cachera ekarri behar da. Trafiko guztia batuta, aurreko maila bera lortzen dugu, nahiz eta orain denboran zehar banatuagoa (txartelak eskuratzekoa, denboran zehar banatu ohi da).

Dena den, aukeran, trafiko handiko uneak (hot spots) sortzen dira oraindik, kasu honetan TXANDA aldagaia eguneratzen denean, hutsegiteak gertatuko baitira zain dauden prozesadore guztien cacheetan, eta, ondorioz, hainbat bloke-eskaera sortuko dira, aldi berean.

Sekzio kritikoan sartzeko eskaera gutxi daudenean, sinkronizazio-estrategia honen latentzia handiagoa da, aurretik txanda hartu behar baita.

Zuzentasuna dela eta, sekzio kritikoan sartzeko eskaerak FIFO moduan prozesatzen dira, heldu diren ordenan, alegia. Nahi izanez gero, txandaren zain ezer egin gabe egon beharrean, txartelaren eta uneko txandaren arabera kalkulatutako denbora-tarte jakin bat erabil daiteke beste zerbait exekutatzeko, gure txanda heldu den berriz egiaztatu baino lehen. 22 Prozesu kopuru maximoa P bada, egokia litzateke TXARTELA eta TXANDA aldagaien gehikuntza

modulu P egitea, balizko gainezkatzeak saihesteko.

4.2. ELKARREKIKO ESKLUSIOA (mutual exclusion) ▪ 139 ▪

4.2.4.2. Sarraila-bektoreak

Esana dugunez, txartelen bidezko estrategian badaude oraindik trafiko handiko uneak TXANDA aldagaia eguneratzen denean, aldagai partekatua delako. Arazoa desagertu egiten da, baldin eta prozesu bakoitzak sarraila pribatu bat (sarraila-bektore baten osagai bat) erabiltzen badu sekzio kritikoan sartzeko.

Hala, lehenbiziko partean, sarraila-bektorea —INDIZEA erakuslearen balioak— banatzen da, txartelekin egin dugun modu berean; gero, prozesu bakoitza zain geratuko da bere sarraila pribatua, SAR_BEKT(INDIZEA), irekitzen den arte.

sarraila-bektorea: SAR_BEKT → ... 0 1 1 1 1 ...

sekzio kritikoan dagoena INDIZEA: itxaroteko hurrengo posizioa

Honela geratuko dira lock eta unlock errutinak:

lock: F&I R1,INDIZEA ; sarraila-bektoreko posizioa eskuratu ; adi: modulu funtzioa itx: LD R2,SAR_BEKT(R1) ; itxaron zure txanda izan arte BNZ R2,itx

ST NIRE_INDIZEA,R1 ; gorde indizea gerorako RET unlock: ADDI R2,R0,#1 ; R2 := 1

LD R1,NIRE_INDIZEA ; eskuratu zure txanda-indizea ST SAR_BEKT(R1),R2 ; itxi bidea zuretzat (1)

ADDI R1,R1,#1 ; adi: modulu funtzioa! ST SAR_BEKT(R1),R0 ; ireki bidea hurrengoari (0) RET

Hurrengo irudian, trafikoko simulazioa ageri da. Datu-trafikoa konstantea da, prozesadore kopuruarekiko independente, sekzio kritikotik ateratzean prozesu bakar baten sarraila eguneratzen (eta baliogabetzen) baita. Gainerako prozesuek ez dute horren berririk izaten, eta itxaroten jarraitzen dute (sarraila-bektoreko osagaiak datu-bloke desberdinetan daudela ari gara kontsideratzen, hau da, partekatze faltsua ez dagoela).

▪ 140 ▪ 4. kapitulua: PROZESUEN SINKRONIZAZIOA SMP KONPUTAGAILUETAN

Sekzio kritiko baterako sarreraren simulazioa Sinkronizazioa: Txartelak eta Sarraila-bektoreak

BRQ = bloke baten eskaera / x = baliogabetuta / datu-bloke baten transmisioa

Txartelak Sarraila-bektoreak

P0 TXANDA++ INV SB(i+1)= 0 INV

P1 LD x BRQ LD SEKZ. KRIT. LD x BRQ LD SEKZ. KRIT.

P2 LD x BRQ. . . . . LD . . . . . . . . . . . . . LD . . . . . . . . .

P3 LD x BRQ. . . . . . . . . . . . LD . . . . . . . . LD . . . . . . . . .

P4 LD x BRQ. . . . . . . . . . . . . . LD . . . LD . . . . . . . . .

Datu-trafikoa (blokeka) TX SB Txartela / Indizea hartzeko → 1 1 Prozesadore bat sekzio kritikora sartzeko → P 1 Prozesadorea sekzio kritikotik ateratzeko → 0 1 Guztira → P + 1 3

P prozesadoreak sartzeko → P(P+3) / 2 3P

Datu-trafikoa, beraz, asko murriztu da, baina, ordainean, memoria gehiago

behar da elkarrekiko esklusioa gauzatzeko (gehienez, P osagaiko bektore bat).

Ikusi dugunez, aukera bat baino gehiago dago sekzio kritikoak kudeatzeko (lock funtzioak sortzeko); beraz, aplikazioaren sinkronizazio-beharrak eta sistema paraleloaren ezaugarriak analizatu beharko ditu programatzaileak, egoera horietan egokienak diren sinkronizazio-funtzioak aukeratu ahal izateko.

Adibide gisa, eta laburpen moduan, hau izango da sortuko den buseko datu-trafikoa (blokeak), erabilitako estrategiaren arabera, zazpi prozesadore zain baldin badaude sekzio kritikoan sartzeko zortzi prozesadoreko SMP batean (P = 7):

T-T&S: P(3P–1) / 2 → 70 bloke LL/SC: P2 → 49 bloke

Txart: P(P+3) / 2 → 35 bloke Sar-Bek: 3P → 21 bloke

4.3. PUNTUTIK PUNTURAKO SINKRONIZAZIOA GERTAEREN BIDEZ (events) ▪ 141 ▪

4.3. PUNTUTIK PUNTURAKO SINKRONIZAZIOA GERTAEREN BIDEZ (events)

"Puntutik punturako" sinkronizazioa egiten dela esaten dugu, baldin eta bi prozesadorek (edo multzok) baino ez badute parte hartzen sinkronizazioan: batek abisatzen dio besteari eragiketa jakin bat egin dela. Sinkronizazio mota berezi hori itxarote aktibo baten bidez gauzatzen da, adierazle gisa funtzionatzen duen aldagai komun baten gainean (edo semaforoak erabiliz, prozesuak blokeatzen badira).

Prozesuak sinkronizatzeko erabiltzen den kontrol-aldagai bat da adierazlea. Esaterako, ekoizle/kontsumitzaile kasuan, honela egin daiteke sinkronizazioa:

P1 (ekoizlea) X = F1(Z); adi = 1;

P2 (kontsumitzailea) while (adi==0) {}; Y = F2(X);

(Zenbait kasutan, ekoizleak sortutako emaitza bera erabil daiteke adierazle gisa; esaterako, emaitza balio-tarte baten barruan egongo dela baldin badakigu, kontsumitzailea zain gera daiteke emaitza tarte horretatik kanpo dagoen bitartean.)

Sinkronizazio-adierazleen funtzioa hardwarearen bidez ere egin daiteke (eta hala egin da esperimentaziorako makina batzuetan, ale xeheko paralelismokoetan). Esaterako, memoria-posizio bakoitzari kontrol-bit bat gehitzen zaio, full/empty, irakurri zenetik memoriako hitz hori idatzi den edo ez adierazteko. Honela beteko litzateke ekoizle/kontsumitzaile motako sinkronizazioa kontrol-bit hori erabiliz: ekoizleak beste datu bat idazten du memoriako hitz batean, baldin eta haren kontrol-bita 0 bada, eta, ondorioz, 1era eramaten du kontrol-bit hori; kontsumitzaileak datu bat hartzen du memoriako hitz batetik, baldin eta haren kontrol-bita 1 bada, eta 0ra eramaten du bit hori. Ez da, hala ere, komertzialki erabili den irtenbidea, garestia delako (bit bat memoria-posizio bakoitzeko), memoria atzitzeko agindu bereziak eskatzen dituelako, eta arazoak dituelako kontsumitzaileak bat baino gehiago direnean.

Gertaeren bidezko sinkronizazioa idazketa baten eta itxarote-begizta baten bidez betetzen da. Testuinguru batzuetan, bi ekintza horiek funtzio jakinen bidez adierazten dira. Esaterako:

▪ 142 ▪ 4. kapitulua: PROZESUEN SINKRONIZAZIOA SMP KONPUTAGAILUETAN

adi = 1 → post(adi) [ signal(adi) ] while (adi == 0) {} → wait(adi)

Erraza da funtzio horiek orokortzea adierazle- edo gertaera-bektoreak erabili ahal izateko:

post(adi,i) → aktibatu gertaera-bektorearen i osagaia: adi(i) := 1

wait(adi,i) → itxaron gertaera-bektorearen i osagaia 1 izan arte

4.4. HESIEN BIDEZKO SINKRONIZAZIOA (barriers)

Programa baten exekuzio paraleloan beharrezkoa da, hainbat unetan, prozesu multzo bat elkarrekiko sinkronizatzea, denak batera; adibidez, prozesu guztiak exekuzio-puntu jakin batetik igaro direla ziurtatzeko. Sinkronizazio-eragiketa horretarako, hesiak erabiltzen dira.

Sinkronizazio-hesiak eraikitzeko, sarrailak, kontagailuak eta adierazleak erabiltzen dira. Hesi batean P prozesu sinkronizatzen dira. Hesira heltzen diren prozesuek kontagailu bat gehitzen dute, elkarrekiko esklusioan, eta, gero, zain geratzen dira, prozesu guztiak hesira heldu arte. Azken prozesuak, kontagailuaren balioa P egiten duenak, hesia ireki egingo du, adierazle bat aktibatuz, eta, hala, prozesu guztiak itxarote-begiztatik aterako dira. Ikus ditzagun adibide batzuk.

4.4.1. Hesi sinple bat

Adibidez, honako errutina hau erabil daiteke sinkronizazio-hesi bat egiteko. hesi_egitura motako struct partekatu (shared) bat erabili dugu, non hiru aldagai ezagutarazten baititugu: sarraila bat (sekzio kritiko bat antolatzeko), kontagailu bat, eta hesiaren egoera adierazten duen adierazle bat: 0, itxita; 1, irekita. Horrez gain, nire_kont aldagai pribatua ere erabiltzen da, hesira zenbat prozesu heldu diren jakiteko.

struct hesi_egitura { int sar; sarrailarako aldagaia int kont; hesira heldu den prozesu kopurua int egoera; hesiaren egoera };

4.4. HESIEN BIDEZKO SINKRONIZAZIOA (barriers) ▪ 143 ▪

struct hesi_egitura H; hesia ezagutarazteko HESIA (H,P) P = prozesu kopurua { LOCK(H.sar); sartu sekzio kritikoan if (H.kont == 0) H.egoera = 0; lehenengoa naiz, itxi hesia H.kont++; nire_kont = H.kont; zenbat heldu diren hesira UNLOCK(H.sar); utzi sekzio kritikoa if (nire_kont == P) azkena naiz { H.kont = 0; kontagailua hasieratu H.egoera = 1; ireki hesia } else while (H.egoera == 0) {}; itxaron hesia ireki arte }

Hesia exekutatzen dutenean, prozesuek H.kont kontagailua gehitzen

dute, sekzio kritiko baten barruan; gainera, hesira heldu den aurreneko prozesuak (H.kont = 0) itxi egiten du hesia (H.egoera = 0). Ondorioz, prozesuak zain geratzen dira begizta batean, harik eta hesia ireki arte. Helduko den azken prozesuak (H.kont = P) irekiko du hesia (H.egoera = 1), eta, ondorioz, zain zeuden prozesuak sinkronizazio-hesitik aterako dira, eta programa exekutatzen jarraituko dute.

Sekzio kritikoaren barruan kontagailua gehitu eta gero, nire_kont aldagaia erabili dugu, gero hesira zenbat prozesu heldu diren jakiteko eta hesia ireki behar den edo ez erabakitzeko. Kodea idatzita dagoen moduan, ezin dugu H.kont kontagailua erabili horretarako, beste prozesu bat egon daitekeelako, une horretan, kontagailu hori gehitzen. H.kont aldagaia erabili nahi badugu funtzio horretarako, if aginduaren konparazioa sekzio kritikoaren barruan egin beharko genuke, eta, gero, sekzio kritikoa bi adarretatik (then eta else) bukatu (unlock).

4.4.2. Hesi berrerabilgarriak

Arazoren bat aurreko hesiarekin? Bai, baldin eta behin eta berriz erabili behar bada (esaterako, begizta baten barruan): kalkulua / hesia / kalkulua / hesia... Ez ahaztu: liburutegiko (edo erabiltzailearen) sinkronizazio-funtzio bat da hesia, eta prozesuek behin eta berriz erabiliko dute exekuzioan zehar.

▪ 144 ▪ 4. kapitulua: PROZESUEN SINKRONIZAZIOA SMP KONPUTAGAILUETAN

Demagun sinkronizazio-hesia exekutatzen ari dela. Azken prozesuak hesia irekitzen duenean, prozesu guztiek hesitik atera eta programaren exekuzioarekin jarraituko dute. Exekutatuko den kodean hesi bera berriro erabiltzen bada, esaterako, begizta baten barruan, beste sinkronizazio-eragiketa baterako, litekeena da prozesu bat hesian berriro sartzea, bigarren aldiz, beste prozesu bat oraindik lehenbizikotik atera gabe dagoenean, ez baitu "jakin" hesia ireki dela (adibidez, exekuzioan ez zegoelako).

Hesian bigarren aldiz sartu den lehenbiziko prozesuak hesia itxi egingo du (une horretan H.kont = 0 delako), dagokion adierazlea desaktibatuz (H.egoera = 0). Hori dela eta, oraindik lehenbiziko sinkronizazio-hesian geratu d(ir)en prozesuak ezingo du hesia abandonatu, berriro itxi egin delako; gainera, bigarren hesian sartuko direnak ere han geratuko dira betiko, inoiz ez baitira P prozesuak sartuko, bat (edo gehiago) atzean geratu da eta. Sistema blokeatu egin da.

Nola gainditu arazo hori? Aukera batzuk daude; esaterako,

a. Beste kontagailu bat erabil daiteke, hesitik ateratzen diren prozesuak kontatzeko. Hala, prozesu batek ezin izango du hesian berriro sartu harik eta guztiak aurreko hesia utzi arte.

Prozedura hori erabiliz, batetik, sinkronizazioaren latentzia handiagoa izan daiteke (zenbait kasutan, itxaron egin behar da hesian sartu baino lehen; hala ere, hesiaren latentzia azken prozesuak markatzen duela kontuan hartu behar dugu); eta, bestetik, hesian sartzeko lehia (sortuko den trafikoa) ere handiagoa egin daiteke, prozesuak bildu egingo baitira hesian berriz sartzeko.

b. Hesia irekita dagoela adierazteko, hesitik hesira aldatzen den balio bat erabil daitezke (sense reversal, bit alternante). Nahikoa da bi baliorekin, 0 eta 1, ez baita posible hesi jakin baten bi aktibazio baino gehiago batera izatea. Hala, lehenbiziko hesia irekita dagoela adierazteko, 0 balioa erabiltzen da; hurrengo hesirako, 1 balioa; hurrengorako, 0a, eta abar. Prozesuek aldagai pribatu bana erabiliko dute balio hori kudeatzeko; beraz, ez dago aldagai partekatu bat (aurreko H.egoera) hesiaren egoera adierazteko.

Adibidez, honela izan daiteke sinkronizazio-hesia bigarren estrategiari jarraituz:

4.4. HESIEN BIDEZKO SINKRONIZAZIOA (barriers) ▪ 145 ▪

irt_bal aldagaia pribatua da, bat prozesuko; hesitik atera ahal izateko adierazlearen uneko balioa adierazten du.

HESIA (H,P) { irt_bal = !(irt_bal); egokitu hesitik ateratzeko balioa LOCK(H.sar); H.kont++; nire_kont = H.kont; UNLOCK(H.sar); if (nire_kont == P) azkena naiz { H.kont = 0; hasieratu kontagailua H.egoera = irt_bal; ireki hesia } else while (H.egoera != irt_bal) { }; itxaron hesia ireki arte }

4.4.3. Eraginkortasuna

Sinkronizazio mota honetan erabiltzen diren eraginkortasun-irizpideak aurrekoak berak dira: latentziak txikia izan behar du (ez da eragiketa asko egin behar hesian sartzeko); trafiko gutxi sortu behar da; eraginkortasuna mantendu egin behar da prozesadore kopurua hazten denean (scalability); eta abar.

P prozesuko hesi batek sortzen duen datu-trafikoa dela eta, honako balioespen hau egin daiteke. Demagun hesi-egituraren aldagaiak (sar, kont eta egoera) datu-bloke desberdinetan daudela (partekatze faltsua saihesteko). Oro har, Pi prozesuak lau datu-bloke eskuratu behar ditu: sar aldagaiarena, sekzio kritikoan sartzeko; kont aldagaiarena, kontagailua gehitzeko; egoera aldagaiarena, itxarote-begiztan geratzeko; eta, azkenik, egoera aldagaiarena berriz, itxarote-begiztatik ateratzeko, azken prozesuak baliogabetuko baitu bloke hori hesia irekitzean. Beraz, datu-trafikoa 4P ordenakoa izango da (zehatzago, 4P – 2 datu-bloke, aurreneko eta azken prozesuek bloke bat gutxiago eskatuko baitute).

Denboran zehar begiratuta, datu-trafiko hori honela banatuko da eskuarki: 2 - 3 - 3... - 3 - P–1; hau da, hesian sartzeko sortzen den trafikoa denboran

▪ 146 ▪ 4. kapitulua: PROZESUEN SINKRONIZAZIOA SMP KONPUTAGAILUETAN

banatzen da (baldin eta hesian sartzeko lehiarik ez badago; bestela, lock funtzioak trafiko gehiago sortuko luke, aurreko ataletan ikusi dugun moduan), baina azken P–1 eskaerak aldi berean sortuko dira, prozesu guztiak (azkena izan ezik) zain daudelako hesitik ateratzeko; une horretan, beraz, blokeak zerbitzatzeko latentziak handiagoak izango dira.

Aurreko kasuetan bezala, honetan ere hainbat hobekuntza egin daitezke; aldagai bera atzitzen duten prozesuen kopurua txikiagotzea da helburua. Esaterako, hesia arbola moduan antola daiteke; esaterako, prozesuak binaka sinkronizatzen dira, dagozkien datu-egiturak erabiliz; gero, bikote bakoitzeko bat, binaka ere sinkronizatzen dira; eta abar (bus batean ez da ezer irabazten, trantsizio guztiak busean azaltzen dira eta; sarea deszentralizatua bada, abantailak handiak izan daitezke). Hala ere, ikusi ditugun hesiak ondo dabiltza SMP makinetan, eta eskuarki ez da beharrezkoa, salbuespenak salbuespen, beste egitura mota bat.

Sinkronizazio-hesiak hardwareaz ere egin daitezke, kontrol-bus berezia baldin badago. Hori egiteko, zelatarientzako sh kontrol-lerroa gauzatzeko erabiltzen den estrategia bera erabili behar da (AND wired).

4.5. LABURPENA

Ohikoa da paraleloan exekutatzen diren prozesuen exekuzioa sinkronizatu behar izatea, aldagai partekatuen erabilera egokia izan dadin. Hainbat kasutan, sekzio kritikoak eratu egin behar dira, eta horretarako makina-mailako agindu atomiko bereziak erabili behar dira, zeinen bidez aldagai baten irakurketa eta idazketa modu atomikoan betetzen den. Beste batzuetan, sinkronizazioa gertaeren bidez gauzatu behar da, banan-banan, adierazleen bidez, edo prozesu multzo bat sinkronizatzeko, hesien bidez.

Sinkronizaziorako erabiltzen diren agindu atomikoak "baliokideak" dira, eta prozesadore jakin batean denak edo batzuk bakarrik izango ditugu. Hala ere, horietako bat erabiliz besteen portaera "simula" daiteke. Esaterako, errutina bat egin daiteke LL/SC aginduak erabiliz F&I edo T&S aginduen portaera simulatzeko. Baina, ezin da ahaztu batzuk besteak baino egokiagoak izan daitezkeela, sortzen den trafikoaren arabera (idazketetan baliogabetzen diren datu-blokeak). Adibidez, T&S agindua erabiliz egindako lock errutina

4.5. LABURPENA ▪ 147 ▪

soila egokia da sekzio kritikoan sartzeko lehiarik ez badago, baina ez da batere eraginkorra lehia handia espero bada.

Datu-trafikoa arazo larria da SMP sistemetan, eta, beraz, hainbat estrategia garatu dira sinkronizazio-funtzioek sortzen duten trafikoa murrizteko: backoff, test-and-test&set, txartelak, sarraila-bektoreak... Izan ere, programatzailearen ardura da aplikazioari dagokion estrategiarik egokiena aukeratzea, dela bibliotekako (sistemako) funtzioak erabiliz, dela sinkronizazio-funtzio bereziak idatziz.

▪ 5 ▪

Memoriaren Kontsistentzia Konputagailu Paraleloetan

5.1. SARRERA

5.1.1. Prozesadore bakarreko sistemak

Zein ordenatan exekutatzen dira programa baten aginduak prozesadore batean? Erantzuna ez da erraza; gehiegi pentsatu gabe, honako erantzun hau eman daiteke: programan idatzitako ordenan, jakina! Haatik, badakigu hori ez dela egia. Exekuzio-eredua Von Neumann izan arren, hainbat hobekuntza erabiltzen dira, hala hardwarean nola softwarean, zeinek aginduen exekuzio-ordena aldatu egiten duten. Esaterako, hardwareak ez du beti errespetatzen aginduen jatorrizko ordena (scoreboard edo Tomasulo desordena/desordena exekuzio-ereduak; agindu-bufferren erabilera prozesadore supereskalarretan, eta abar). Ildo berean, baina softwarearen ikuspuntutik, badakigu

▪ 150 ▪ 5. kapitulua: MEMORIAREN KONTSISTENTZIA KONPUTAGAILU PARALELOETAN

konpiladoreek berrordenatu egiten dutela kodea, exekuzio eraginkorragoak lortzeko (list scheduling, loop unrolling, trace scheduling, software pipelining...).

Aginduen berrordenatze horretan, memoria-eragiketei dagokie alderdirik kezkagarriena. Konputagailu baten memoriak bildu beharko luke, zehatz-mehatz, exekutatzen ari den programaren "uneko egoera", hau da, programaren exekuzioa noraino heldu den eta lortutako emaitzak. Hala ere, jakin badakigu ez dela hori errealitatean gertatzen. Adibidez, cache memoria erabiltzen denez, memoria nagusia ez dago beti gaurkotua; LD eta ST aginduen arteko desordena onartzen da ("load aurreratu eta zirkuitulaburra egin" ereduan, esaterako); idazketa-bufferrak erabiltzen dira, CM→MN transferentziak egiten diren bitartean prozesadorea geldituta ez uzteko; konpiladoreak berak ken ditzake kodetik hainbat memoria-eragiketa eta, haien ordez, erregistroetako balioak erabili (esaterako, begiztak zabaltzen direnean eta errekurrentziak daudenean), eta abar. Izan ere, hobekuntza horietan guztietan datza prozesadoreen kalkulu-abiaduraren hazkundearen zioetako bat.

Beraz, ez da erraza programa baten aginduen exekuzio-ordena jakitea, aginduak berrordenatzen direlako eraginkortasun handiena lortu ahal izateko. Jakina, programa ordena hertsian exekutatuz lortuko liratekeen emaitzak berak lortu behar dira, beti. Esaterako, aldagai bat irakurtzen denean, beti lortu behar da azken idazketari dagokion emaitza.

Aipatu ditugun optimizazio guztiak erabiltzen badira ere, programen exekuzioaren kontrola "zehatza" da prozesadore bakarreko sistemetan, kontrol-unitatea bakarra baita. Zoritxarrez, ez da gauza bera gertatzen multiprozesadoreetan, kontrol-unitate asko, banatuta, baitaude.

5.1.2. Multiprozesadoreak

Prozesadore bakarreko sistemetan konponduta dagoena, arazo larri bihurtzen da multiprozesadoreetan, kontrola deszentralizatuta dagoelako, hainbat prozesadoretan. Beraz, zein ordenatan exekutatzen dira programen aginduak sistema paraleloetan, osorik hartuta? Edozein ordenatan exekutatuta, emaitza egokia da?

Prozesuen arteko komunikazioa memorian egiten bada (demagun hala dela), aurreko galderak beste honetan laburbil daitezke: zein ordenatan exekutatzen dira memoria-eragiketak sistema paraleloetan?

5.1. SARRERA ▪ 151 ▪

Aginduen exekuzio-ordenarekin lotzen den arazoari, eta, oro har, sistema paraleloa osatzen duten prozesadoreek memoria-edukiari buruz duten irudiaren arazoari, memoriaren kontsistentzia deritzo. Hirugarren kapituluan aztertu dugun koherentziaren arazoa ere gai berari dagokio, baina modu mugatuagoan. Gogoratu; koherentzia-protokolo baten erabilerak ziurtatzen ditu:

• cache lokal bateko aldagai baten gainean egiten diren aldaketak cache guztietan agertuko direla, noizbait.

• aldagai batean egiten diren aldaketak ordena berean agertuko direla beste prozesadoreetan.

Beraz, koherentzia-protokolo bat erabiliz, aldagai baten gainean egiten diren aldaketa guztiak hurrenkera berean ikusiko dute prozesadore guztiek. Hala ere, koherentzia-ereduak ez digu ezer esaten aldagai desberdinen gainean egiten diren idazketen ordenari buruz (zein ordenatan ikusiko diren sistemako prozesadoreetan). Arazoa, beraz, koherentziarena baino orokorragoa da.

5.1.3. Programen semantika eta aginduen exekuzio-ordena

Lehenik eta behin, ondo aztertu behar da programa paraleloen semantika, emaitzak ez baitira, askotan, intuitiboki espero ditugunak. Izan ere, algoritmo bat hainbat prozesadoreren artean banatzen denean, ondo kontrolatu behar da aldagai partekatuak nola erabiltzen diren. Aginduen exekuzio-ordena funtsezkoa da programa paraleloen semantika definitzeko. Esaterako, zein izango da bi prozesadoretan exekutatzen den programa honen emaitza P2n? Ba al dauka semantika garbia programak? (hasieran, A = B = 0)

P1 P2

A = 1; (wr1) B = 2; (wr2)

print B; (rd1) print A; (rd2)

Lau konbinazio posible ditugu emaitzetarako: BA = 00; 01; 21; eta 20. Aginduak denboran zehar tartekatzen diren ordenaren arabera, lau aukera horietatik lehenengo hirurak "logikoak" lirateke. Esaterako, BA = 01 inprimatuko du P2k, aginduak denboran zehar ordena honetan exekutatzen badira:

▪ 152 ▪ 5. kapitulua: MEMORIAREN KONTSISTENTZIA KONPUTAGAILU PARALELOETAN

P1 P2

A = 1; ... B = 2; ...

... print B; ... print A;

Aldiz, laugarren konbinazioak, hots, BA = 20, ezinezkoa ematen du: B = 2 inprimatzen bada, A = 1 inprimatu behar da, nahitaez. Baina, egon adi! konbinazio hori agertuko da, baldin eta P2k aginduak desordenatzea erabakitzen badu, bi aldagai independente irakurtzen baititu (ohiko exekuzio-eredua desordena/desordena da).

Izan ere, idatzita dagoen moduan, aurreko programa paraleloa anbiguoa izan daiteke. Aurreko kapituluan ikusi dugunez, programa paraleloen semantika, eskuarki, sinkronizazio-eragiketen bidez zehazten da. Adibide honetan ageri da kasu bat: P2k, A = 1 inprimatu beharko luke, beti.

P1 P2

A = 1; (wr1)

PREST = 1; (wr2)

while (PREST == 0) {}; (rd1) print A; (rd2)

Zoritxarrez, aldagai partekatuen erabilera sinkronizatuta ere, oraindik arazoak izan ditzakegu aginduen exekuzio-ordenarekin. Bi programetako datu-dependentziek ziurtatu beharko lukete emaitza zuzena; baina datu-dependentzia horiek programen (prozesadoreen) artean ageri dira, eta ez programa bakoitzaren barruan!

wr1 (A) rd1 (PREST) wr2 (PREST) rd2 (A)

Prozesadore bakoitzean aginduen ordena errespetatzen bada, hots, bi idazketen eta bi irakurketen arteko ordena errespetatzen bada (wr1 >> wr2; rd1 >> rd223), wr1 → rd2 dependentzia berez errespetatuko da, honako hau beteko baita: wr1 >> wr2 → rd1 >> rd2 ⇒ wr1 → rd2. Baina ordena lokala errespetatzen ez bada (hau da, konpiladoreak edo hardwareak kodea desordenatzen badu), baliteke A = 0 inprimatzea. 23 >> ikurrarekin ordena adierazten dugu. A >> B adierazpenak hau esan nahi du: A B baino lehen.

exekutatu da. → ikurrarekin, aldiz, datu-dependentzia bat adierazten dugu: A → B, A-k sortzen duena B-k erabili behar du.

denbora

5.1. SARRERA ▪ 153 ▪

Aginduen ordenaren arazoa beste adibide honetan ere ikusten da (hasieran F1 = F2 = 0):

P1 P2

F1 = 1; if (F2 == 0) then < kodea > ...

F2 = 1; if (F1 == 0) then < kodea > ...

Hauek dira agindu horien arteko dependentziak:

wr1 (F1) wr2 (F2)

rd1 (F2) rd1 (F1)

"Logika" sekuentzialaren arabera, ez da posible bi prozesadoreak then adarreko kodea exekutatzea, nahitaez errespetatu behar baitira wr1 >> rd1 eta wr2 >> rd2 ordenak; baina kodea desordenatzen bada prozesadore bakoitzean (eta ez dago arazorik hori egiteko, ez baitago inongo dependentziarik prozesadore bakoitzeko aginduen artean), litekeena da bi prozesadoreak kode zati hori exekutatzea.

Adibideetan aipatu ditugun ordena-aldaketak guztiz normalak dira prozesadore bakarreko sistemetan; are gehiago, beharrezkoak dira gutxieneko eraginkortasuna lortuko badugu.

5.1.4. Aginduen atomikotasuna

Memoria-aginduak atomikoak dira, baldin eta, hasten direnetik bukatu arte, beste memoria-eragiketari ekiten ez bazaio. Gainera, bukaera modu globalean ulertu behar da; hots, agindua bera eta haren ondorioak multiprozesadorean (esaterako, idazketa ez da bukatzen harik eta idatzi den datu-blokearen kopia guztiak baliogabetu diren arte).

Ikus dezagun adibide bat.

P1 P2

A = 1; (wr1) PREST = 1; (wr2)

while (PREST == 0) {}; (rd1) print A; (rd2)

▪ 154 ▪ 5. kapitulua: MEMORIAREN KONTSISTENTZIA KONPUTAGAILU PARALELOETAN

Aginduen arteko ordenari eutsita ere, badago oraindik beste arazo bat. Koherentzia-protokoloak P1en egiten diren bi idazketak (aldaketak) P2n ere ikusiko direla ziurtatzen du, baina ez du esaten zein ordenatan ikusiko diren, bi helbide desberdinekoak direlako24. PREST aldagaiaren balio berria A aldagaiarena baino lehen ageri bada P2n, A = 0 inprimatuko da. Hori gerta daiteke P1en idazketak atomikoak ez badira, hau da, programa exekutatzen jarraitzen bada (wr2) aurreko idazketa (haren ondorioak) oraindik bete gabe izanik. Hau da, beraz, ondorioa: programa paraleloen "zuzentasuna" ziurtatzeko, itxaron egin beharko genuke memoria-eragiketa bat "bukatu" arte hurrengoari ekin baino lehen.

Arazoa, hala ere, orokorragoa da. Adibide honetan ere islatzen da atomikotasunaren beharra (A = B = 0):

P1 P2 P3

A = 1;

while (A == 0) {}; B = 1;

while (B == 0) {}; C = A;

P1ek A idazten duenean, balio berria P2ra eta P3ra zabalduko da. A-ren balio berria P2n agertzen denean, B = 1 exekutatuko da, eta, ondorioz, B-ren balio berria ere P3ra zabalduko da. Bi aldaketa horietatik, zein ikusiko da lehenago P3n? Aurrena P2n egindako aldaketa (B berria) bada, litekeena da P3n C = 0 exekutatzea, eta ez C = 1.

Beraz, memoria-eragiketen atomikotasuna arazo globala da, prozesadore baten barruan ez ezik, sistema osoan mantendu behar baita.

5.1.5. Kontsistentzia-ereduak

Sistema paraleloetan exekutatzen diren programek prozesadore bakar batean exekutatzen direneko emaitza bera eman behar dute: sistema paraleloak kontsistentea izan behar du. Aurreko adibideetan ikusi dugunez, arazoa memoria-eragiketekin ageri da (batik bat, aldagai partekatuekin), aldaketen ordena eta atomikotasuna dela eta. 24 Prozesadore batetik bestera bidalitako “mezuak/kontrol-seinaleak” desordenan hel daitezke

helburura, komunikazio-sarearen eta -protokoloen arabera. Argia da aukera hori memoria banatutako sistemetan, baina bus batean oinarritzen diren SMP sistemetan ere gerta daiteke, bus motaren eta komunikazio-protokoloaren arabera.

5.2. KONTSISTENTZIA SEKUENTZIALA (SC, sequential consistency) ▪ 155 ▪

Sistema-softwarearen egileek zein aplikazioen programatzaileek programa paraleloen aginduen exekuzio-ordena eta atomikotasuna zehazten dituen eredu bat behar dute, kodean egin daitezkeen hobekuntzak jakiteko eta programen portaera modu egokian ulertu eta interpretatu ahal izateko. Memoriaren kontsistentzia-eredu batek memoria-espazio koherentea definitzen du, sistemako prozesu guztietarako, memoria-eragiketen arteko ordena-erlazioak adieraziz. Hurrengo ataletan, multiprozesadoreetan erabiltzen diren kontsistentzia-eredu nagusiak azalduko ditugu: batetik, kontsistentzia sekuentziala, eta, bestetik, kontsistentzia-eredu malguak.

5.2. KONTSISTENTZIA SEKUENTZIALA (SC, sequential

consistency)

Aipatu dugunez, kontsistentzia ez da arazoa prozesadore (kontrol-unitate) bakar bat erabiltzen denean: agindu-jario bakarra dago, eta ordena "kontrolpean" dago. Konpiladoreak hainbat aldaketa egin ditzake aginduen ordenan (irakurketak aurreratzea, esaterako), eta hardwarea dago prozesadorea blokeatzeko edo aginduak geldiarazteko, datu- eta kontrol-dependentziei aurre egiteko.

Prozesadore bakarreko "ordena hertsiko" eredua multiprozesadoreetara zabalduz, kontsistentzia sekuentziala (SC) izeneko eredua lortzen da. Multiprozesadore bat sekuentzialki kontsistentea da, baldin eta (a) aginduen ordena lokala mantentzen bada prozesadore bakoitzean, eta (b) aginduen ordena sistema osoan (globala) prozesadore bakoitzeko aginduen tartekatze jakin bati badagokio.

SC eredua da programatzaile batek eskuarki espero duena, intuitiboena. Bi baldintza ezartzen ditu eredu horrek:

1. Prozesadore bakoitzean, aginduen ordena lokala mantendu behar da. Ordena lokala mantentzeak LD eta ST aginduak ezin direla

desordenatu esan nahi du. Mantendu egin behar dira, beraz, lau ordena-erlazio hauek, edozein helbidetarako eta prozesadore bakoitzean: wr >> rd; wr >> wr; rd >> rd; eta rd >> wr.

Esaterako, hurrengo adibidean, lehenbiziko bi exekuzio-ordenak SC ereduarekin bat datoz; beste biak, ordea, ez, aginduen jatorrizko ordena lokala (memoria-eragiketak) errespetatzen ez baita.

▪ 156 ▪ 5. kapitulua: MEMORIAREN KONTSISTENTZIA KONPUTAGAILU PARALELOETAN

P1 P2 Batera, denboran zehar SC bai SC ez

a b

c d

a a a c b c d d c b c b d d b a

2. Ordena globala ere mantendu behar da, eta horrek esan nahi du ezin dela memoria-eragiketa bat exekutatu harik eta aurrekoa (edozein prozesadoretan), eta haren ondorioak, bukatuta izan arte. Hori ziurtatzeko, memoriako eragiketek atomikoak izan behar dute (write atomicity = idazketa guztiek, edozein posiziotan, ordena berean ageri behar dute, prozesadore guztietan).

Beraz, ez da onartzen honako exekuzio hau:

Bi baldintza horien beharra egiaztatu dugu, dagoeneko, aurreko ataletako adibideetan. Beraz, eta laburbilduz, memoriaren kontsistentziaren arazoa erabat desagertzen da SC ereduan, exekuzio-ordena jakin bat, lokala zein globala, eta atomikotasuna ezarri direlako. Memoria-eredua, beraz, ordena hertsiarena da, eta programen portaera espero dena izango da. Irudian, eredu horren memoria-eskema logikoa ageri da: memoria-eragiketak atomikoki zerbitzatzen dira, ordena hertsian.

5.2.1. Memoria-eragiketen ordena eta atomikotasuna

Prozesadore bakoitzean ordena lokala ezartzea erraza izan daiteke, baldin eta aurreko memoria-agindua noiz bukatu den badakigu; aldiz, zailagoa izan daiteke memoria-eragiketen atomikotasuna (ordena globala) ziurtatzea,

P P P P

MEM

ordena

atomikotasuna

denbora

a agindua

b agindua

5.2. KONTSISTENTZIA SEKUENTZIALA (SC, sequential consistency) ▪ 157 ▪

prozesadoreek cache pribatu bana erabiliko dutela kontuan harturik. Hauek izango lirateke SC eredua betetzeko eginkizunak:

1. Prozesadore bakoitzean, LD eta ST aginduen arteko ordena gorde behar da (erraz bete daiteke, prozesadore bakoitzeko aginduen ordena kontrol-unitate bakar baten mende dagoelako).

2. Ordenaz gain, bertako aginduen atomikotasuna ziurtatzeko, prozesadore bakoitzeko memoria-eragiketak noiz bukatzen diren jakin behar da, hurrengoei ekin ahal izateko. Irakurketa (LD) baten bukaera detektatzea erraza da: datuak eskuratzen direnean, hain zuzen ere. Idazketekin, aldiz, arazo gehiago dago. Izan ere, idazketa (ST) bat exekutatzen denean, prozesadoreak ezin du hurrengo memoria-eragiketa exekutatu idazketa zein haren ondorioak (kopien baliogabetzea edo eguneratzea) prozesadore guztietan bete diren arte (write completion).

Baliogabetze/eguneratze guztiak egin direla ziurtatzeko, koherentzia-protokoloak konplexuagoa behar du izan, erantzunak gehitu behar baitira: ACK seinaleak edo mezuak (acknowledgement, onartzea). Bloke baten kopia baliogabetu/eguneratu duten prozesadoreek ACK bana bidali behar dute; erantzun horiek guztiak bildu direnean, eragiketa bukatu egin da (arazoa: nola jakin zenbat kopia dagoen?).

3. Prozesadore guztiak kontuan hartuta, atomikotasuna (ordena globala) ziurtatzeko, bi baldintza bete behar dira: (a) Batetik, aldagai beraren gaineko idazketak hurrenkera berean ikusi

behar dira prozesadore guztietan. Adibidez,

P1 P2 P3 P4

A = 2; B = 1;

A = 3; C = 1;

while (B ≠ 1) {}; while (C ≠ 1) {}; reg1 = A;

while (B ≠ 1) {}; while (C ≠ 1) {}; reg2 = A;

A aldagaiaren eguneratzeak (2 eta 3) P3ra eta P4ra desordenatuta heltzen badira, kontsistentzia ez da beteko, balio desberdinak esleituko baitira reg1 eta reg2 erregistroetara, eta A-ren idazketa ez dela atomikoa izan emango du.

1. INV

2. ACK 2. ACK

1. INV

▪ 158 ▪ 5. kapitulua: MEMORIAREN KONTSISTENTZIA KONPUTAGAILU PARALELOETAN

Multiprozesadoreko konexio-sarea bus bat denean, koherentzia-protokoloak (zelatariak) eta busa egoki erabiltzeak ziurta dezakete idazketen ordena. Laster ikusiko dugunez, sare orokorragoak erabiltzen direnean, direktorioak erabili behar dira koherentzia zein ordena ziurtatzeko.

(b) Eta, bestetik, irakurketa (LD) bat exekutatu baino lehen, itxaron egin behar da aldagai horren azken balioa idatzi zuen agindua, eta haren ondorioak prozesadore guztietan, bukatuta izan arte (oro har, beste prozesadore batean).

Koherentzia-protokoloa baliogabetzekoa bada, ez da zaila aurreko baldintza betetzea: bertako kopia baliogabetuta dago, eta, beraz, beste kopia bat eskatu behar da; kopia hori eragiketa bukatuta dagoenean zerbitzatuko da. Kopiak eguneratzen badira, ordea, koherentzia mantentzeko prozesuak, idazketa dela eta, konplexuagoa izan behar du: aldagaia eguneratzeko seinalea sortu ondoren (1), itxaron egin behar da baieztapen guztiak heldu arte (2); azkenik, aldagaia erabil daitekeela adierazteko mezua bidali behar zaie kopia guztiei (3), eragiketa sistema osoan bukatutzat emateko. Konplexutasun hori dela eta, eguneratzeko koherentzia-protokoloak ez dira eskuarki erabiltzen.

5.2.2. Eragina hardwarean eta konpiladorean

Kontsistentzia sekuentziala ziurtatzen duten baldintzak —ordena eta atomikotasuna mantendu beharra, alegia— oso gogorrak dira. Memoria-eragiketa bat "bukatu" arte, prozesadoreak ezin du hurrengo memoria-eragiketa exekutatu; eta memoria-aginduak % 25 - % 35 dira! Gainera, cache memoriaren erabilera konplikatu egin da, eta prozesadore bakar baterako eskuarki erabiltzen diren hainbat hobekuntza ezin dira erabili.

Adibidez, memoria-eragiketen atomikotasuna eta ordena direla eta, ezin dira idazketa-bufferrak erabili; azken batean, idazketa-bufferrak erabiltzeak hurrengo LD aginduen aurreratzea dakar. Era berean, konpiladoreak ezin du kodea berrordenatu, horrekin memoria-eragiketen ordena aldatzen bada. Eta, zoritxarrez, ezin da memoriaren erabilera optimizatu erregistroak erabiliz

1. BC 1. BC

2. ACK 2. ACK

3. segi 3. segi

5.3. EREDU MALGUAK (relaxed) ▪ 159 ▪

(LD/ST aginduak aurrezteko). Esaterako, optimizazio hau gaizki dabil multiprozesadore batean:

P1 P2 P1 P2 A = 1; B = A;

(2 ST / 1 LD)

A = 0;

r1 = 1; A = r1; B = r1;

(2 ST)

A = 0;

Jatorrizko programan, B aldagaiak 1 edo 0 balioak izan ditzake; bigarrenean, aldiz, B = 0 balioa ez da inoiz lortuko, A irakurtzen ez baita (funtsean, LD aginduen aurreratzea). Beraz, ezin da optimizazio hori onartu SC kontsistentzia-ereduan.

SC ereduaren "albo-ondorio" horiek arintzeko edo, zenbait aukera daude. Esaterako, LD aginduak modu espekulatiboan exekuta daitezke, aurreko ST aginduak bukatu baino lehen. Azkenean dena ondo atera bada, aurrera jarraituko da, arazorik gabe; bestela, tartean blokea baliogabetu edo eguneratu bada, atzera jo beharko da (roll-back, jauzi-aginduen latentzia gainditzeko egiten den modu berean). Nolanahi ere, oraintxe ikusiko dugunez, SC eredua inposatzen dituenak baino murriztapen gutxiagorekin ere manten daiteke sistema paraleloen kontsistentzia.

5.3. EREDU MALGUAK (relaxed)

Kontsistentzia ziurtatzeko SC ereduaren baldintzek multzo nahikoa osatzen dute, baina ez beharrezkoa. Gainera, eraginkortasunaren ikuspuntutik, sistemaren gainean duten eragina handia da, hainbat eta hainbat hobekuntza debekatzen direlako, eta memoria-eragiketa guztien bukaera arte itxaron behar delako. Eraginkortasuna hobetzeko, beraz, eredu malguagoak garatu behar dira, eta, horretarako, agindu-ordenaren beharraren analisi finagoa egin behar da.

Aipatu dugunez, memoria-aginduen arteko ordena lau kasu hauetan laburbiltzen da:

rd >> rd25 rd >> wr 26 wr >> rd wr >> wr

Kontsistentzia-eredu sekuentzialak aurreko ordena guztiak betetzen direla ziurtatzen du. Kontsistentzia-eredu malguek, aldiz, onartzen dituzte 25 Kontuan hartu hutsegiteetan blokeatzen ez diren cacheak. 26 Kontuz hiru kasu hauekin: helbide berean badira, datu-dependentziaren bat izango da.

▪ 160 ▪ 5. kapitulua: MEMORIAREN KONTSISTENTZIA KONPUTAGAILU PARALELOETAN

horietako batzuk ez errespetatzea. Kontsistentzia-eredu malgu bat definitzeko, beraz, honako hau adierazi behar da:

• Memoriako aginduetan zein ordena errespetatzen den eta zein ez. • ST (idazketa) eragiketaren atomikotasuna betetzen den ala ez, LD

agindu baten exekuzioa baimendu ahal izateko, ST aginduaren eragina oraindik prozesadore guztietan gauzatu ez bada ere.

Nolanahi ere, kontsistentzia-eredu malgu bat erabiltzen denean, aukera izan behar da beti hobekuntza horiek bertan behera uzteko, ordena hertsia ezartzeko. Horretarako, eskuarki makina-mailako agindu bereziak erabiltzen dira (oro har, bibliotekako funtzioen bidez). Agindu berri horiek ordena-hesiak (fence) deitzen dira, eta kontrol-gune gisa erabiltzen dira. Ordena-hesi motako agindu batek hurrenkera jakin bat inposatzen du, ez baitu uzten hurrengo memoria-aginduei ekitea, aurreko guztiak bukatu arte.

Agindu berezi horiek desberdinak dira prozesadoreen arabera: MEMBAR, STBAR, SYNC... Oro har, hiru mota hauetan sailkatu ohi dira:

• Write-fence: aurreko idazketa guztiak bukatu direla eta hurrengoak ez direla hasi ziurtatzeko (beraz, wr >> wr ordena ezartzeko).

• Read-fence: gauza bera, baina irakurketekin (eskuarki, LD aginduen aurreratzea mugatzeko erabiltzen dira).

• Memory-fence: berdin, baina bi eragiketetarako, rd eta wr.

Definizioz, kontsistentzia sekuentziala erabiltzen denean, memoria-eragiketa guztiak fence motako agindu bihurtzen dira.

5.3.1. Total Store Ordering (TSO) / Processor Consis-tency (PC)

Idazketen latentzia "ezkutatzea" da lehenbiziko hobekuntzaren helburua, eta, horretarako, ST agindu bat bukatzeke dagoela, onartzen da hurrengo LD aginduak exekutatzea; hau da, LD aginduak aurreratu daitezke: ez da ziurtatzen wr >> rd ordena. TSO eta PC ereduen arteko desberdintasun bakarra hau da: Processor Consistency deiturikoan, ez da ziurtatzen memoria-eragiketak atomikoak direnik.

Hau litzateke eredu horri dagokion memoria-egitura (eskematikoki):

5.3. EREDU MALGUAK (relaxed) ▪ 161 ▪

TSO ereduan, ilara bat erabiltzen da ST (eta SWAP, T&S...) aginduetarako (idazketak), eta haien artean ordena mantentzen da (FIFO). LD aginduek aurreratu dezakete ilara hori eta memoria irakurri (edo zirkuitulabur bat erabili), dependentziarik ez badago, noski. Edonola ere, ST aginduek ezin diete LD aginduei aurrea hartu, eta, halaber, ezin dira bi LD agindu desordenatu. Izan ere, LD aginduek "blokeatu" egiten dituzte hurrengo memoria-eragiketak.

Adibide gisa, honela ulertu behar da bi programa hauen exekuzioa, erabilitako kontsistentzia-ereduaren arabera:

P1 P2

X = balio_berria; Y_kopia = Y

Y = balio_berria; X_kopia = X

SC → gutxienez batek, Y_kopiak edo X_kopiak, balio_berria izango du. TSO → litekeena da Y_kopia zein X_kopia ez hartzea balio_berria.

Definizioz, TSO/PC kontsistentzia-eredu malguan ez da kontsistentzia sekuentziala mantentzen; beraz, ez da ziurtatzen programen portaera egokia izango dela kasu guztietan. Hori dela eta, litekeena da programetako zenbait puntutan ordena hertsia (SC) ezarri behar izatea. Eta, horretarako, arestian aipatu ditugun agindu bereziak (fence motakoak) erabili behar dira. Agindu mota hori prozesadorearen agindu-multzoan ez badago, read-modify-write motako aginduak erabil daitezke (T&S esaterako) ST (LD) memoria-agindu arruntak erabili beharrean, ezen horiek irakurketa eta idazketa bana egiten baitute, eta, ondorioz, ezin dira desordenatu TSO/PC kontsistentzia-eredua erabiltzen denean; esaterako:

ST ... LD → SWAP ... LD desordenatu daitezke ezin dira desordenatu

ST bufferrak (FIFO)

LD ST

P P P P

MEM

ST ST ST

▪ 162 ▪ 5. kapitulua: MEMORIAREN KONTSISTENTZIA KONPUTAGAILU PARALELOETAN

TSO kontsistentzia-eredua egokia da idazketen latentzia gainditzeko, eta, gainera, eredu horretan ondo funtzionatzen dute beti adierazle baten bidezko ohiko sinkronizazioek: write A; write FLAG // read FLAG; read A.

Hori dela eta, hainbat makinatan erabili da: Sequent Balance, Encore Multimax, (IBM 370), SparcCenter2000, SGI Challenge eta Pentium Pro (PC) eta abarretan.

5.3.2. Partial Store Ordering (PSO)

Kontsistentzia-eredu malguagoa lortzen da, baldin eta idazketen arteko ordena ere ez bada errespetatzen (idazketa >> irakurketa ordenaz gain); hau da, ez dira ziurtatzen bi ordena-erlazio hauek: wr >> rd, wr. Memoria-egitura aurreko ereduarena da, baina ST aginduetarako ilarak ez dira FIFO moduan kudeatzen; beraz, idazketen ordena ez da ziurtatzen.

Adi egon: kontsistentzia-eredu hori erabiltzen denean, gerta daiteke sinkronizazio arruntenak ere (ekoizle/kontsumitzaile, adierazle baten bidez) gaizki funtzionatzea. Beraz, kontu handiz analizatu behar da eredu hori erabiltzea merezi duen, eta ebaluatu, beti bezala, irabaz daitekeena eta galtzen dena. Aurreko ereduan bezala, memoria-aginduen ordena hertsia (orain wr >> wr ordena ere) ezarri behar bada programa baten puntu jakin batean, haren esanahia ziurtatzeko, dagoeneko azaldu ditugun agindu bereziak (fence motako aginduak) erabili behar dira.

Kontsistentzia-eredu hori erabili da, esaterako, Sun Sparc PSO konputagailuan.

5.3.3. Eredu malguenak

Partekatzen diren aldagaietan baino ez da ageri ordenaren arazoa, ez besteetan. Are gehiago; bi adibide hauetan, esaterako, ez litzateke beharrezkoa izango memoria-atzipen guztien ordena hertsia ziurtatzea:

P1 P2 P1 / P2 / ... / Pn

X = X + 1; Y = B + 1; adi = 1; ...

... while (adi == 0) {}; A = X / 2; B = Y;

... lock(sar); nik = i; i = i + N; j = j - 1; unlock(sar); ...

5.3. EREDU MALGUAK (relaxed) ▪ 163 ▪

Izan ere, nahikoa da sinkronizazio-eragiketarekiko ordena ziurtatzea; hori eginda, berdin zaigu beste aginduak zein ordenatan betetzen diren (adibidez, sekzio kritikoan prozesadore bakar bat izango da).

Programazio sinkronizatua egiten dela esaten da, baldin eta aldagai partekatuen erabilera bi sinkronizazio-eragiketen bidez babesten bada (adibidez, aurreko adibideetan ageri den moduan). Dakigunez, aldagai partekatuetako atzipenak sinkronizatuta ez badaude, datu-lasterketak (data-races) ager daitezke: emaitzak ezin dira aurreikusi, eta aldatu egiten dira exekuziotik exekuziora. Hori dela eta, programa paralelo gehienek sinkronizazio motaren bat erabiltzen dute datu partekatuen erabilera "ordenatzeko" (beharrezkoa denean): lock eta unlock funtzioak, adierazleak eta abar.

Ondorioz, programa baten kontsistentzia (esanahi intuitiboa) mantentzeko, nahikoa izango litzateke sinkronizazio-eragiketen ordena ziurtatzea, bai eta beste memoria-eragiketena sinkronizazioekiko ere.

Hurrengo kontsistentzia-ereduak definitzeko, memoria-eragiketa arruntak (rd, wr) eta sinkronizaziokoak (s) bereiztea komeni zaigu. Beraz, rd eta wr eragiketen arteko ordenaz gain, ordena-erlazio hauek ere kontuan hartu beharko ditugu:

rd, wr >> s s >> rd, wr s >> s

Ordenazioa sinkronizazio-eragiketetara mugatu nahi bada, memoria-atzipenak egoki identifikatu beharko dira (hardwareaz zein softwareaz), bakoitzari dagozkion ordena-murriztapenak kontuan hartu ahal izateko.

5.3.3.1. Weak Ordering (WO)

Weak Ordering kontsistentzia-ereduan, memoria-aginduen arteko edozein ordena onartzen da, baldin eta aginduak sinkronizazio motakoak ez badira; azken horien ordena, aldiz, zorrotz mantendu behar da (eta, ondorioz, fence edo hesi-agindu gisa funtzionatuko dute). Laburbilduz: sinkronizazio-eragiketak exekutatu baino lehen, itxaron egin behar da aurreko memoria-eragiketa guztiak bukatuta izan arte; sinkronizazio ondoko memoria-atzipenek ere itxaron beharko dute sinkronizazioa bukatu arte.

Hori dela eta, hauek dira ereduak ziurtatzen dituen ordena-erlazioak: rd / wr >> s s >> rd / wr; s >> s

rd ...wr ...

sink

rd ...wr ...

sink

rd ...wr ...

▪ 164 ▪ 5. kapitulua: MEMORIAREN KONTSISTENTZIA KONPUTAGAILU PARALELOETAN

Aurreko bi ereduetan bezala, programaren esanahia zehazteko aginduen ordenari eutsi behar zaionean, bi aukera daude: hesi-aginduak (fence) sartzea ordena ezartzeko; edo, aukera hori ez badago, ordena mantendu behar den puntuan LD edo ST agindu arruntak sinkronizazio-eragiketa gisa identifikatzea (ordena ezarri, beraz).

5.3.3.2. Release Consistency (RC)

Kontsistentzia-eredurik malguena da. Aurrekoan bezala, sinkronizazio-eragiketek markatuko dituzte ordenazio-puntuak; haien artean, LD eta ST aginduen arteko desordena onartzen da. Gainera, bi multzotan banatzen dira sinkronizazio-eragiketak: eskuratzeak (acquire, sa) eta askatzeak (release, sr). sa eragiketak irakurketak (edo RMW eragiketak) dira, eta sr eragiketak idazketak (edo RMW eragiketak). Adibidez, lock funtzioa acquire motako sinkronizazio-eragiketa da, eta unlock, aldiz, release motakoa (gauza bera hesi bat irekitzeko eragiketa).

Sinkronizazio-eragiketen arteko ordenaz gain (s >> s), hauek dira eredu horretan bete beharreko baldintzak:

• eskuratze (acquire) motako sinkronizazio-eragiketaren ondorengo memoria-atzipenek ere itxaron behar dute sinkronizazioa bukatu arte; hau da, sa >> rd / wr ordena mantentzen da.

• askatze (release) motako sinkronizazio-eragiketa bat exekutatu baino lehen, prozesadoreak itxaron egin behar du aurreko memoria-eragiketa guztiak bukatu arte; beraz, rd / wr >> sr ordena mantentzen da.

Azken bi kontsistentzia-ereduak egokiak dira aginduen planifikazio dinamikoa (desordena/desordena) erabiltzen duten prozesadoreetan, LD aginduak desordenan bukatzea onartzen baita, bai eta idazketa bat aurreko irakurketa bat baino lehen betetzea ere. Alpha, IBM PowerPC, MIPS prozesadoreetan erabili da mota horretako kontsistentzia-ereduren bat (izan ere, hainbat kasutan ez da eredu jakin bat erabiltzen, eta erabiltzaileak erabaki behar du zer eredu nahi duen, fence motako eragiketen bidez).

rd ...wr ...

s_acq

rd ...wr ...

s_rel

rd ...wr ...

5.3. EREDU MALGUAK (relaxed) ▪ 165 ▪

Taula honetan, kontsistentzia-ereduen ezaugarri nagusiak laburbildu dira.

Eredua

Memoria-eragiketen ordena Ordena ezartzeko aginduak wr>>rd wr>>wr rd>>rd/wr sink. wr atom.

SC denak

TSO denak MEMBAR, RMW

PC denak MEMBAR, RMW

PSO denak STBAR, RMW

WO denak SYNC

RC sa >> w/r w/r >> sr s >> s

REL, ACQ, RMW

Irudi honetako adibidean, eredu bakoitzean inposatzen diren aginduen

arteko ordenak (geziak) ageri dira.

SC

wr,rd,s >> wr,rd,s TSO/PC

– wr >> rd PSO

– wr >> wr WO RC

– rd >> wr, rd

rd

wr

sink_a

wr

rd

sink_r

wr

wr

= A

B =

sink_acq

C =

= D

sink_rel

E =

F =

= A

B =

sink_acq

C =

= D

sink_rel

E =

F =

= A

B =

sink_acq

C =

= D

sink_rel

E =

F =

= A

B =

sink_acq

C =

= D

sink_rel

E =

F =

= A

B =

sink_acq

C =

= D

sink_rel

E =

F =

▪ 166 ▪ 5. kapitulua: MEMORIAREN KONTSISTENTZIA KONPUTAGAILU PARALELOETAN

5.4. LABURPENA ETA PERSPEKTIBAK

Programa paraleloek semantika argia eta ondo definitua izan dezaten, hardwareak zein programatzaileek multiprozesadoreko memoriaren "irudi" ondo definitua behar dute. Memoria partekatuko multiprozesadorearen memoria-irudi edo -interfaze horri kontsistentzia-eredua deritzo.

Bi motako kontsistentzia-ereduak daude: sekuentziala eta malguak. Aurrenak, SC ereduak, memoria-aginduen ordena lokala eta globala mantentzera behartzen du, bai eta agindu horien exekuzio atomikoa egitera ere. Bestalde, eredu malguek agindu batzuen arteko desordena onartzen dute; esaterako, LD aginduak aurreratu daitezke (TSO), edo LD/ST aginduak (PSO), edo edozein exekuzio-ordena onartzen da, baina sinkronizazio-aginduekiko ordena errespetatuz (WO). Kontsistentzia-eredu malguak erabiltzen direnean, zenbait kasutan debekatu egin behar da aginduak desordenatzea ordena hertsia berrezartzeko, eta horretarako fence motako agindu bereziak erabiltzen dira.

Eraginkortasuna kontuan harturik, eredu malguak SC eredua baino egokiagoak lirateke. Izan ere, SC eredua erabiltzen denean, ezin dira erabili prozesadore bakarreko sistemetan ohikoak diren hainbat hobekuntza, eta, ondorioz, eraginkortasuna txikiagoa dateke. Baina, beti bezala, eredu horien alde positiboak eta negatiboak aztertu behar dira, merezi duten ala ez jakiteko; hain zuzen ere, eredu malguak erabili ahal izateko, hardwarearen eta softwarearen laguntza behar da (agindu berriak; programatzaileek ondo identifikatu behar dituzte ordenazio-puntuak; eta abar.)

Mark Hill izan da gai hauek guztiak aztertu dituen ikertzaile nagusietako bat. Haren iritziz, multiprozesadoreek SC eredua erabili behar dute oinarrizko eredu gisa, eta, agian, eredu malguren bat eskaini behar dute aukera moduan. Zer dela eta?

Oraingo prozesadoreetan, ohikoa da aginduen exekuzio espekulatiboa egitea. Aginduak espekulatiboki exekutatzen dira, hots, seguru izan gabe exekutatu behar direnetz. Exekuzioa seguru bihurtzen denean, emaitzak idazten dira eta aginduak bukatutzat (commit) ematen dira; bestela, ez zirela exekutatu behar detektatzen bada, agindu horien eragina deuseztatu egiten da (batzuetan, roll-back prozedurak exekutatu behar dira), eta programaren exekuzio-puntu "seguru" batera itzultzen da.

Hori dela eta, SC eredua erabili arren, eredu malguen hobekuntzak ere erabil daitezke, aginduak espekulatiboki exekutatzen diren neurrian;

5.4. LABURPENA ETA PERSPEKTIBAK ▪ 167 ▪

desegokiak suertatzen badira, aukera izango da haien eragina desegiteko. Zertan bereizten dira, beraz, bi eredu motak? Bada, eredu malguak erabiliz, aginduak lehenago erretira daitezke prozesadoretik, ez baita desordena egokia den edo ez jakin arte itxaron behar.

Hobekuntzen balizko onurak neurtu behar dira beti, programa errealak zein proba-bankuak erabiliz. Egin diren zenbait esperimentutan, programen exekuzio-denbora % 10-20 txikiagoa da kontsistentzia-eredu malguak erabiltzen direnean, SC ereduarekin alderatuta. Merezi du hobekuntza horrek? Prest daude middleware (sistemako softwarea, behe-mailako aplikazioak...) programatzaileak eredu malguak erabiltzeko behar den konplexutasuna onartzeko? Esaterako: konpiladoreak egiten dituzten programatzaileei dagokie fence aginduak noiz sartu behar diren erabakitzea (behar direnak bakarrik, ez gehiago, eraginkortasuna ez galtzeko); softwarearen eramangarritasuna bermatzeko, hardware-plataforma desberdinak kontuan hartu behar dira; eta abar. Paraleloan programatzea zaila da berez, eta kontsistentzia-eredu malguak kontuan hartu behar badira, zailagoa.

Laburbilduz; SC eredua multiprozesadore guztietan erabiltzen da (estandar gisa): kontsistentziako arazoak hardwarean konpontzen dira eta gardenak dira programatzailearentzat. Bigarren aukera gisa, TSO eredua egokia izan daiteke optimizazio arruntak erabili ahal izateko (LD aurreratu), eta txikia da eragina programatzaileengan. Memoria-eragiketen ordena guztiak erlaxatzen dituzten ereduak, aldiz, zailagoak dira justifikatzen.