5. Rinnakkaisuus ja jako prosesseihin

Samankaltaiset tiedostot
5. Luento: Rinnakkaisuus ja reaaliaika. Tommi Mikkonen,

Käyttöjärjestelmät: poissulkeminen ja synkronointi

5. Luento: Rinnakkaisuus ja jako prosesseihin (+ lyhyesti reaaliajasta) Arto Salminen,

Oppimistavoitteet kurssilla Rinnakkaisohjelmointi

Concurrency - Rinnakkaisuus. Group: 9 Joni Laine Juho Vähätalo

OHJ-4301 Sulautettu Ohjelmointi

Ongelma(t): Miten tietokoneen käyttöjärjestelmä toimii sisäisesti, jotta resurssit saadaan tehokkaaseen käyttöön?

Palvelut. Sulautetut järjestelmät Luku 2 Sivu 1 (??) Sulautetut käyttöjärjestelmät

2 Konekieli, aliohjelmat, keskeytykset

4. Luento: Prosessit ja säikeets. Tommi Mikkonen,

Rinnakkaisuuden hyväksikäyttö peleissä. Paula Kemppi

6. Luento: Skedulointi eli Vuoronnus. Tommi Mikkonen,

14. Luento: Kohti hajautettuja sulautettuja järjestelmiä. Tommi Mikkonen,

Rinnakkaistietokoneet luento S

Sulautettujen järjestelmien skaala on niin laaja, että on erittäin vaikea antaa yleispätevää kuvausta siitä millainen on sulautettu järjestelmä.

Monitorit. Monitori Synkronointimenetelmiä Esimerkkejä. Andrews , Stallings 5.5

Monitorit. Tavoite. Monitori Synkronointimenetelmiä Esimerkkejä. Andrews , Stallings 5.5. Minimoi virhemahdollisuuksia

Järjestelmäarkkitehtuuri (TK081702) Hajautettu tietokanta. Hajautuksen hyötyjä

Agenda. Johdanto Ominaispiirteitä Kokonaisjärjestelmän määrittely Eri alojen edustajien roolit Sulautetut järjestelmät ja sulautettu ohjelmointi

TIES530 TIES530. Moniprosessorijärjestelmät. Moniprosessorijärjestelmät. Miksi moniprosessorijärjestelmä?

Tehtävä 2: Tietoliikenneprotokolla

Algoritmit. Ohjelman tekemisen hahmottamisessa käytetään

12. Javan toistorakenteet 12.1

Tietojenkäsittelyn perusteet 2. Lisää käyttöjärjestelmistä

Ongelma(t): Miten mikro-ohjelmoitavaa tietokonetta voisi ohjelmoida kirjoittamatta binääristä (mikro)koodia? Voisiko samalla algoritmin esitystavalla

Ohjelmoinnin perusteet Y Python

Ongelma(t): Jotta tietokone olisi mahdollisimman yleiskäyttöinen ja suorituskykyinen, niin miten tietokoneen resurssit tulisi tarjota ohjelmoijalle,

12. Javan toistorakenteet 12.1

Ohjelmoinnin peruskurssien laaja oppimäärä

Liite 1. Projektin tulokset (Semaforit Javassa) Jukka Hyvärinen Aleksanteri Aaltonen

9. Luento: Ohjelmistotyö. Tommi Mikkonen,

Arto Salminen,

Käyttöjärjestelmät: prosessit

812341A Olio-ohjelmointi, IX Olioiden välisistä yhteyksistä

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

1. Keskusyksikön rakenne

11/20: Konepelti auki

Harjoitustyön testaus. Juha Taina

Sisällys. 12. Javan toistorakenteet. Yleistä. Laskurimuuttujat

812315A Ohjelmiston rakentaminen. Asynkronisuus

Transaktiot - kertausta

Ohjelmoinnin peruskurssien laaja oppimäärä

Kiertokysely. Sulautetut järjestelmät Luku 2 Sivu 1 (??)

Algoritmit 1. Luento 3 Ti Timo Männikkö

OSA I: Yhteisten muuttujien käyttö Prosessit samassa koneessa. Sisältöä. Poissulkeminen. Halutut ominaisuudet 2-1. Rinnakkaiset, atomiset operaatiot

Sisällys. 16. Lohkot. Lohkot. Lohkot

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 16.3

Chapel. TIE Ryhmä 91. Joonas Eloranta Lari Valtonen

Jaetun muistin muuntaminen viestin välitykseksi. 15. lokakuuta 2007

Agenda. Läpäisyvaatimukset Henkilökunta Luennot ja aikataulu Kurssimateriaali Harjoitustyöt Demoharjoitus Tentti ja arvostelu Muuta?

Tutoriaaliläsnäoloista

Käyttöjärjestelmät. Teemu Saarelainen Tietotekniikka

Ohjelmiston testaus ja laatu. Ohjelmistotekniikka elinkaarimallit

Luku 8. Aluekyselyt. 8.1 Summataulukko

Luento 7: VIRTUAALIMUISTIN SIVUTUS JA SEGMENTOINTI

Kuva 8.7. u Muunnos prosessin sivunumerosta sivutilanumeroksi u Kussakin alkiossa: u Katenoimalla. u MMU:ssa; juuri äsken käytettyjä muunnoksia

Rinnakkaisuus. parallel tietokoneissa rinnakkaisia laskentayksiköitä concurrent asioita tapahtuu yhtaikaa. TTY Ohjelmistotekniikka

Sisällys. 16. Ohjelmoinnin tekniikkaa. Aritmetiikkaa toisin merkiten. Aritmetiikkaa toisin merkiten

ohjelman arkkitehtuurista.

16. Ohjelmoinnin tekniikkaa 16.1

Algoritmit 1. Luento 1 Ti Timo Männikkö

1 Määrittelyjä ja aputuloksia

OHJ-4301 Sulautettu Ohjelmointi

16. Ohjelmoinnin tekniikkaa 16.1

A11-02 Infrapunasuodinautomatiikka kameralle

Käyttöjärjestelmät II

IT K 1 45 K ä yt t öj ä rj estelmät

TIE Tietorakenteet ja algoritmit 1. TIE Tietorakenteet ja algoritmit

11. Javan toistorakenteet 11.1

7.4 Sormenjälkitekniikka

Ohjelmien automaattisen verifioinnin reunamailla

815338A Ohjelmointikielten periaatteet

Itsestabilointi: perusmääritelmiä ja klassisia tuloksia

Sisältöä. Tietokoneen rakenne. Ch 1 - Ch 8 [Sta06] Valikoituja paloja TITO-kurssista. Tietokonejärjestelmä

Intel Threading Building Blocks

JReleaser Yksikkötestaus ja JUnit. Mikko Mäkelä

Synco TM 700 säätimen peruskäyttöohjeet

Graafisen käyttöliittymän ohjelmointi Syksy 2013

Kilpailemaan valmentaminen - Huipputaidot Osa 3: Vireys- ja suoritustilan hallinta. Harjoite 15: Keskittyminen ja sen hallinta

OSA I: Yhteisten muuttujien käyttö. Prosessit samassa koneessa. Rio 2004 / Auvo Häkkinen 2-1

OSA I: Yhteisten muuttujien käyttö. Sisältöä. Prosessit samassa koneessa. Poissulkeminen ja synkronointi. Semaforit ja rinnakkaisuuden hallinta

Algoritmi on periaatteellisella tasolla seuraava:

Sisällys. 17. Ohjelmoinnin tekniikkaa. Aritmetiikkaa toisin merkiten. for-lause lyhemmin

Tietokoneen toiminta, K Tavoitteet (4)

Jakso 12 Yhteenveto. Keskeiset asiat Teemu Kerola, K2000

Ongelma(t): Miten tietokoneen komponentteja voi ohjata siten, että ne tekevät yhdessä jotakin järkevää? Voiko tietokonetta ohjata (ohjelmoida) siten,

811120P Diskreetit rakenteet

Sisällys. 15. Lohkot. Lohkot. Lohkot

Testaajan eettiset periaatteet

OSA I: Sisältöä. Atomisuus (atomic action) v Poissulkeminen ja synkronointi. Kriittinen (koodi)alue (critical section)

Liite 1: KualiKSB skenaariot ja PoC tulokset. 1. Palvelun kehittäjän näkökulma. KualiKSB. Sivu 1. Tilanne Vaatimus Ongelma jos vaatimus ei toteudu

dokumentin aihe Dokumentti: Testausraportti_I1.doc Päiväys: Projekti : AgileElephant

Käyttöjärjestelmät II

Tietokonejärjestelmä. Tietokoneen rakenne. Ch 1 - Ch 8 [Sta06] Valikoituja paloja. TITO-kurssista. John von Neumann ja EDVAC, 1949.

Toinen harjoitustyö. ASCII-grafiikkaa

Valitaan alkio x 1 A B ja merkitään A 1 = A { x 1 }. Perinnöllisyyden nojalla A 1 I.

Verkon värittämistä hajautetuilla algoritmeilla

Algoritmit 2. Luento 12 To Timo Männikkö

Maastotietokannan torrent-jakelun shapefile-tiedostojen purkaminen zip-arkistoista Windows-komentojonoilla

Määritelmä, alkuluku/yhdistetty luku: Esimerkki . c) Huomautus Määritelmä, alkutekijä: Esimerkki

Transkriptio:

Rinnakkaisuus ja jako prosesseihin 89 5. Rinnakkaisuus ja jako prosesseihin Tietokoneen oheislaitteet toimivat toisistaan riippumatta. Ne edustavat todellista rinnakkaisuutta, sillä niiden toimintojen ei tarvitse olla millään tavalla sidoksissa toisiinsa. Tämä rinnakkaisuus aiheuttaa vaatimuksia myös suorittimelle: sille voi tulla keskeytyspyyntöjä, jotka käsittelevät juuri sitä tietorakennetta, jota suoritin on juuri käsittelemässä. Teemme tässä yhteydessä nopean kertauksen rinnakkaisuuden hallintaan. 5.1 Johdanto Rinnakkaisuus näyttäytyy ohjelmoijille joko todellisena tai näennäisenä. Todellista rinnakkaisuutta on muun muassa monisuoritinjärjestelmissä ja hajautetuissa järjestelmissä. Todellista rinnakkaisuutta on myös yksisuoritinkoneissa, kun oheislaitteet toteuttavat itsenäisesti suorittimen antamia käskyjä. Näennäinen rinnakkaisuus esiintyy moniajon (eli monta prosesessia tai säiettä yhtä aikaa aktiivisena) ja keskeytysten kautta. Ohjelmoijan kannalta on hyvin vähän eroa siinä, onko kyseessä todellinen vai näennäinen rinnakkaisuus, sillä ratkaistavat ongelmat ovat samat, ainakin, jos käytössä on irrottava skedulointi (skedulointiin palataan luvussa 6). Rinnakkaisuus vaikuttaa joko suoraan tai epäsuorasti. Suoraa vaikutusta prosessien välillä on yhteisten tietorakenteiden ja sanomien välityksen kautta. Erityisen voimakasta suoraa vaikuttamista on toisen prosessin luonti tai tuhoaminen. Epäsuora vaikutus tulee kilpailemisesta yhteisistä resursseista, joita ovat muun muassa oheislaitteet, suoritin ja ytimen tietorakenteet. Ohjelmoinnin kannalta perusongelma on suoran vaikutuksen hallinta, mutta reaaliaikaympäristössä epäsuora kilpailu voi nousta tärkeään osaan.

90 Sulautettu ohjelmointi Toinen tärkeä tekijä sulautetun järjestelmän toiminnassa on sen toiminnan oikea ajoitus. Tärkeintä ole se, että kyselyyn, keskeytykseen tai muu sellainen vastataan mahdollisimman nopeasti, vaan että vastaukseen kuluvan ajan vaihteluväli voidaan laskea etukäteen 15. Jotta ajanlaskenta voidaan tehdä, pitää tietää, kuinka kauan suorittimelta menee vastauksen laskemiseen. Tämä ei tietenkään riitä, mikäli vastauksen laskeva prosessi kilpailee suoritinajasta muiden prosessien kanssa. Laskennan mahdollistamiseksi on tunnettava käytössä olevan skedulerin ominaisuudet. Asiaa sivutaan tässä yhteydessä, mutta tarkempaan käsittelyyn ei ryhdytä. 5.2 Perusongelmat Rinnakkaisuuden mukanaan tuomia ongelmia ovat poissulkeminen, synkronointi, lukkiutuminen ja nälkiintyminen. Lisäksi rinnakkaisen ohjelman testaus on hankalaa, sulautetuissa järjestelmissä erityisen hankalaa. Näitä perusongelmia käsitellään tarkemmin omalla kurssillaan, mutta tähän on koottu lyhyt yhteenveto asiasta. 5.2.1 Kriittinen alue Jos kaksi (tai useampia) ohjelmaa käsittelee yhteistä muuttujaa, sanotaan muuttujaa käsittelevää ohjelman osaa kriittiseksi alueeksi. Niin yksinkertaista ohjelman osaa ei käytännössä olekaan, etteikö kriittinen alue aiheuttaisi ongelmia. Esimerkiksi muuttujan kasvattaminen yhdellä a++; generoi nykyaikaisessa koneessa usein kolme konekäskyä, esimerkiksi seuraavasti: ld [a],%1 // Lue a:n arvo rekisteriin 1 (merkitty %1) add %1,1,%1 // Kasvata rekisterin 1 arvoa yhdellä st %1,[a]. // Talleta rekisterin 1 arvo muuttujaan a Mikäli suoritin keskeytetään kesken tämän kolmen käskyn sekvenssin, ja keskeytyspalvelu muuttaa a:n arvoa, palaaminen tähän ohjelmaan kirjoittaa keskeytyspalvelun tekemien muutosten päälle alkuperäisen a:n arvon kasvatettuna yhdellä. 15. Tarkoitus ei ole vähätellä nopeuden merkitystä, vaan korostaa sitä, että se yksinään ei ole riittävä ominaisuus.

Rinnakkaisuus ja jako prosesseihin 91 Tässä siis muuttuja a edusti yhteistä muistia ja lause a++ krittiistä aluetta. Sekä yhteinen muisti että kriittinen alue voivat tietenkin olla paljonkin suurempia ja yleensä ovatkin; tässä lähestyttiin minimiä. 5.2.2 Poissulkeminen Poissulkeminen tarkoittaa sitä, että yhteistä muistialuetta käyttävälle kriittiselle alueelle päästetään vain yksi ohjelma kerrallaan. Helpoimmillaan tämä tapahtuu yksisuoritinkoneissa siten, että ennen kriittistä aluetta kielletään keskeytykset ja kriittisen alueen jälkeen sallitaan ne. Sulautetuissa järjestelmissä tämä on usein käytännössäkin mahdollista, sillä sovelluksia ajetaan usein käyttöjärjestelmän tilassa, mikä sallii keskeytyskiellot. Keskeytyskielto estää mitään keskeyttämästä ohjelman suoritusta kesken kriittisen alueen. Näin voidaan olla varmoja, että päivitys tietorakenteeseen tapahtuu halutulla tavalla. Keskeytyskiellolla on myös ongelmansa: pitkä kielto voi aiheuttaa jonkin oheislaitteen virheellisen toiminnan tai viivästyttää sitä niin, että toiminta ei ole paras mahdollinen. Toisaalta, jos laite on kytketty sellaiseen keskeytyslinjaan, jolta tulevaa keskeytystä ei voi kieltää (NMI), ei millään kriittisellä alueella voida käsitellä laitteen tietoja turvallisesti. Tämän takia NMI:tä ei pidä kytkeä normaalin laitteen keskeytysrutiiniin, vaan sitä kannattaa käyttää ainoastaan poikkeuksellisen "hätätilanteen" signalointiin. Poissulkemista varten voi ytimestä löytyä niin sanotut semaforit, joiden avulla poissulkeminen saadaan tehtyä. Ehkä yleisempi ratkaisu on kuitenkin se, että järjestelmästä löytyvät kutsut reserve ja release (tai jotain vastaavaa), joilla ensimmäisellä varataan alue ja toisella vapautetaan se. Poissulkemisesta on enemmän rinnakkaisuus- ja käyttöjärjestelmäkirjoissa. 5.2.3 Synkronointi Synkronointi tarkoittaa sitä, että ohjelma odottaa joko toisen ohjelman pääsemistä tiettyyn vaiheeseen tai oheislaitteen työn valmistumista. Usein pienimmissä järjestelmissä ohjelmat harvoin odottavat toisiaan tällä tasolla, mutta sitäkin useammin keskeytyksiä. Jos järjestelmässä ei ole prosessikäsitettä, keskeytys toimii synkronointiprimitiivinä. Prosesseja käytettäessä synkronointia odottava prosessi (tai säie) pysäytetään, ja sen annetaan edetä vasta sitten, kun odotettava tapahtuma on tullut.

92 Sulautettu ohjelmointi Synkronointiinkin voidaan käyttää edellisessä kohdassa mainittua semaforia. Usein tarjolla on erityiset kutsut wait ja signal, joista ensimmäisellä voidaan odottaa tapahtumaa ja toisella ilmoittaa tapahtuman tapahtuneen. Myös synkronointia käsitellään enemmän rinnakkaisuus- ja käyttöjärjestelmäkirjoissa. 5.2.4 Poissulkemisen ja synkronoinnin vähentäminen Kuten yllä on esitetty, poissulkemiseen liittyy aina kriittisen alueen käsite. Alue on kriittinen, jos sen käyttämiä muuttujia voi käsitellä useampi prosessi yhtä aikaa mahdollisesti muuttaen niiden arvoja. Yhtäaikainen luku ei yleensä häiritse, mutta yhtäaikainen kirjoittaminen ja lukeminen voi johtaa ongelmiin ei tosin aina, mutta sopivalla tietorakenteella tämä voi tietyissä sovelluksissa olla mahdollinen. Kriittinen alue tulee aina ympäröidä kutsuilla, jotka varaavat ja vapauttavat kriittisen alueen. Tietyissä tilanteissa poissulkeminen ei kuitenkaan ole välttämätöntä, varsinkin, jos prosesseja on vain kaksi. Tällaisia erikoistapauksia ovat jotkin jonot, kuten rengaspuskurit, sillä jonon ensimmäistä alkiota osoittavaa muuttujaa käsittelee vain jonoa purkava prosessi, ja jonon viimeistä alkiota osoittavaa muuttujaa päivittää vain jonoon kirjoittava prosessi. Koska jonon viimeinen paikka ei koskaan ole ensimmäinen, lukitusta ei tarvita. Tällainen ratkaisu tosin luottaa siihen, että puskuri ei ikinä täyty. Yleisesti ottaen on syytä aina huolehtia siitä, että poissulkemisen toteuttavat kutsut ovat paikallaan. Vain jos ajoituksen kanssa tulee ongelmia, kannattaa yrittää poissulkemisen vähentämistä. Joka tapauksessa järjestelmä on parasta laittaa ensin toimimaan ja vasta sitten tutkia, voiko poissulkemista vähentää. Synkronointi tapahtuu esimerkiksi silloin, kun odotetaan toisen prosessin varaamaa resurssia. Synkronointiakin voidaan vähentää, mikäli ollaan aivan varma siitä, että sen poistaminen ei aiheuta ajoitusongelmia. Kuten poissulkemisen vähentämisessä, tämäkin tulisi tehdä vasta sitten, kun looginen toiminta on muuten kunnossa, mutta ohjelma käyttää liikaa aikaa. Erityisesti on huomioitava, että vaikka poissulkemista ja synkronointia voidaan erityistapauksissa vähentää, tämä voi aiheuttaa myöhemmin pahoja ongelmia, mikäli järjestelmää ylläpitävät henkilöt eivät ole tietoisia tällaisesta optimoinnista. Vähintäänkin operaatioiden

Rinnakkaisuus ja jako prosesseihin 93 kutsut tulisi aina jättää ohjelmaan kommentteina myöhempää ylläpitoa varten. 5.2.5 Lukkiutuminen ja nälkiintyminen Poissulkemisen ja synkronoinnin lisäksi rinnakkaisuuden aiheuttamia ongelmia ovat lukkiutuminen, jossa ohjelman suoritus estyy joiltain osin resurssien jatkuvan varaamisen vuoksi, ja nälkiintyminen, jossa periaatteessa suoritus olisi mahdollista, mutta muiden prosessien suoritus kollektiivisesti estää jonkin ohjelman osan suorittamisen. Lukkiutumiseen ja nälkiintymiseen liittyvät ongelmat heräävät oikeastaan vasta sitten, kun poissulkemisrutiineita ruvetaan käyttämään. Näistä nälkiintyminen on hankalampi hallita, koska lukkiutumisen estämiseen riittää yhden lukkiutumisen välttämättömän ehdon säännönmukainen rikkominen. Lukkiutumisen välttämättömät ja riittävät ehdot ovat: 1. Poissulkemisehto: prosessi varaa resurssin yksityiseen käyttöön. 2. Varaus-odotusehto: prosessi ei vapauta resursseja odotuksen ajaksi. 3. Irrottamattomuusehto: varatun resurssin vapauttaa vain prosessi itse. 4. Silmukkaodotusehto: prosessit odottavat toisten varaamia resursseja. Nälkiintymiselle välttämätön mutta ei riittävä ehto on poissulkeminen. Usein tätä ei vain huomata, sillä monissa tapauksissa poissulkeminen ei ole nähtävissä ohjelmakoodista, vaan se on alussa mainittua epäsuoraa vaikutusta. Näin nälkiintymiselle ei ole vastaavaa helppoa tapaa sen kiertämiseksi kuin lukkiutumiselle. Sitä voidaan estää paitsi ohjelman rakenteella myös sopivalla skedulerilla. Ohjelman rakenne on aina turvallisempi ratkaisu, koska silloin mahdollinen ympäristön ja samalla skedulerin vaihdos ei aiheuta myöhemmin yllätyksiä. 5.2.6 Testaamisesta Rinnakkaisuutta sisältävän ohjelman testaaminen on monimutkaisempaa kuin peräkkäisohjelman. Koska ohjelman säikeet etenevät omaa tahtiaan, muodostuu mahdollisista suorituksista lähes aina niin suuri joukko testattavia polkuja ettei niiden kaikkien testaaminen olisi mahdollista edes periaatteessa. Käytännössä näin voitaisiin menetellä harvoin jo senkin takia, että tietyn suoritusjärjestyksen pakottaminen on

94 Sulautettu ohjelmointi harvoin mahdollista tämä tarkoittaisi ohjelman suorituksen täydellistä sarjallistamista esimerkiksi synkronoinnin avulla. Koska suorituspolkuja on niin paljon, voidaan yleensä testata vain pieni osajoukko kaikista mahdollisista. Siksi ohjelmiin jää usein virheitä, jotka johtavat ongelmiin vain tietyissä tilanteissa, kun joku todennäköisyydeltään alhainen suorituspolku päätyy suoritukseen. Usein ongelmat raportoidaan vasta kun järjestelmä on käytössä, mutta vaikka ongelmaan törmättäisiin jo testausvaiheessakin sen toistaminen voisi olla mahdotonta. Varsinaisen testaamisen lisäksi myös löydettyjen virheiden korjaaminen on usein vaikeaa. Syynä tähän on, että rinnakkaiset suoritukset voivat ehtiä edetä kauas varsinaisesta virheestä ennen kuin ongelmat ovat niin pahoja, että ne huomataan. Siksi testaustarkoituksia varten kannattaa mahdollisuuksien mukaan lisätä apukoodia, joka auttaa virheiden jäljityksessä. Tämäkään ei kuitenkaan aina riitä, sillä joskus ongelmat poistuvat kun virheiden jäljittämistä varten lisätty apukoodi aktivoidaan. 5.3 Aktiivisen lukituksen toteutus Kuten edellä jo mainittiin, yksisuoritinympäristössä lukitus voidaan toteuttaa keskeytyskielloilla. Monisuoritinympäristössä tämä ei ole mahdollista (yhden suorittimen keskeytyskielto ei estä toista suoritinta tekemästä mitä huvittaa), jonka takia tässä kohdassa käydään läpi poissulkemisen toteuttamista yhteisen muistin koneilla, joissa keskeytyskieltoa ei voi käyttää. Mikäli suorittimilla on yhteistä muistia, voidaan aktiivinen odotus voidaan toteuttaa laitteiston tukemilla erikoiskäskyillä. Tällainen erikoiskäsky on esimerkiksi swap, joka vaihtaa rekisterin ja muistipaikan arvot keskenään ja varaa väylän koko toiminnon ajaksi, jotta toinen suoritin ei pääse väliin. Tämän käskyn avulla lukitus voidaan toteuttaa helposti esimerkiksi seuraavaan tapaan (muistipaikassa lukko on nolla, jos alue on vapaa, ja yksi, jos alue on varattu): lock: mov #1, %1 // Varausvakio 1 rekisteriin yksi. s1: swap %1,lukko // Vaihdetaan varattutieto lukkoon brpos s1 // Mikäli lukossa oli 1, // yritetään uudestaan. ret // Lukitus onnistui

Rinnakkaisuus ja jako prosesseihin 95 Lukon avaus onkin paljon helpompaa, sillä riittää, että kirjoitetaan nolla lukkomuuttujaan: unlock: mov #0, lukko ret Swap ei ole ainoa tällainen käsky. Toinen suhteellisen yleinen vastaavaan tarkoitukseen tehty käsky on btset (bit test and set) tai vastaava: testaa onko bitti nolla ja jos on, niin älä hyppää ja aseta bitti, muuten hyppää (tässäkin vapaa on siis nolla ja varattu ykkönen): lock: btset lukko, lock // Jos bitti asetettu, // testaa uudelleen. ret // Lukitus onnistui Vapautus tapahtuu vastaavasti unlock: bclr lukko // Nollaa bitti ret Mikäli lukitusta varten ei ole käytettävissä erityiskäskyjä, täytyy käyttää jotakin tähän tarkoitukseen suunniteltua algoritmia. Käyttökelpoisia algoritmeja ovat muun muassa Dekkerin, Petterssonin, Eisenberg & McGuiren ja Fischerin algoritmit. Näitä algoritmeja ei esitetä tässä; ne on esitetty monissa rinnakkaisuus- tai käyttöjärjestelmäkirjoissa. On syytä huomata, että näissä niin kuin kaikissa lukitusohjelmissa tarvitaan yhteistä muistia, jonka takia mahdollinen välimuisti (data cache) pitää olla kiellettynä, eikä kääntäjäkään saa optimoida sijoituskäskyjä liikaa. C:n ja C++:n määre volatile tarkoittaa sitä, että muuttujan arvo voi muuttua kyseessä olevan rutiinin ulkopuolella, joten sitä ei saa optimoida rekisteriin. Tämän takia kaikkien yhteisten muuttujien ja lukkomuuttujien tulee olla volatile-määreellä suojattuja. Muissa kielissä määre voi olla shared tai muu sellainen. 5.4 Jako prosesseihin Algoritmien rinnakkaistaminen on vaikeaa. Sama pätee myös suuremmille kokonaisuuksille. Rinnakkaistamiseen lähdetään joko ongelman hallitsemiseksi (kustannukset! 16 ) tai sitten tehokkuuden saavuttamiseksi. Silti jakaminen perustuu usein tekijän kokemukseen asioista, ja kriteereitä on vaikea formalisoida. Tehtävänä on siis jakaa yksi sovellusongelma monelle prosessille.

96 Sulautettu ohjelmointi Jakoperusteena voi olla järjestelmän toiminnallisuus, skedulointi, rakenne tai tehokkuuden saavuttaminen. Toiminnallisessa jaossa yhteen loogiseen asiaan (sovelluksen toiminnalliseen osaan) liittyvät asiat ovat yhdessä prosessissa. Skedulointiin perustuvassa jaossa asiat, jotka suoritetaan aina yhtä aikaa ovat samassa prosessissa. Rakenteeseen perustuvassa jaossa kutakin rakenneosaa (ohjattavaa oheislaitetta tai muuta sellaista) ohjaa oma prosessinsa. Tehokkuuden saavuttamiseksi tehdään jakoa silloin, kun käytettävissä on monisuoritinympäristön tarjoamaa todellista rinnakkaisuutta. Periaatteessa samoilla tavoilla jaetaan monisuoritinjärjestelmässä tai hajautetussa järjestelmässä tehtävät eri suorittimille. Vaikka prosesseihin jako voi tuottaa lisätehoa, tärkein syy jakamiseen on yleensä modulaarisuuteen pyrkiminen ja kustannusten hallinta. Toisaalta liiallinen prosesseihin jako synnyttää turhaa viestiliikennettä ja voi näin hidastaa kokonaisjärjestelmää kohtuuttomasti. 5.4.1 Toiminnallinen jako Toiminnallisen jaon perustana ovat prosessien tehtävät sovelluksen loogisen toiminnan kannalta. Toiminnot sijoitetaan kukin omaan prosessiinsa. Toiminnallisen jaon etuja: Toimintojen ohjelmointi helpohkoa, jos tarvittavat tiedot ovat lokaaleja. Modulaarinen: testaus ja virheen etsintä helpottuu. Koko prosessin toiminta helppo ymmärtää. Toiminnallisen jaon haittoja: Mikäli tarvittavat tiedot ovat globaaleja, syntyy paljon potentiaalisia poissulkemisongelmia. Jos tiedot pitää kerätä toisilta prosesseilta, syntyy paljon suhteellisen raskaita kommunikaatiokutsuja. 16. Ohjelmistoprojektin kustannukset nousevat lineaarista nopeammin projektin koon kasvaessa. Tämän takia projektin jakaminen osaprojekteihin on kannattavaa, vaikka siitä jouduttaisiin hieman maksamaankin. Eli kustannusfunktiolla f ilmaistuna: f(kaikki) > n*f(kaikki/n)+n*vakio.

Rinnakkaisuus ja jako prosesseihin 97 Jokainen prosessi rasittaa järjestelmää ainakin keskusmuistin kulutuksella (pino!) ja skedulerin hidastumisena; ongelmaksi tämä tulee, jos loogisia toimintoja on paljon. Järjestelmän staattinen rakenne voi hämärtyä. 5.4.2 Skedulointiin perustuva jako Skedulointiin perustuvassa jaossa yhteen prosessiin kootaan ne asiat, jotka tehdään aina yhtä aikaa. Tyypillisesti kyseessä ovat tällöin periodiset tehtävät eli tehtävät, jotka toistuvat säännöllisesti ja kestävät aina suurin piirtein yhtä kauan. Esimerkiksi mittaustaajuus voi olla sama kuin säätötaajuus, jolloin nämä prosessit voidaan yhdistää, vaikka ne toiminnallisesti ovatkin jossain määrin erillään. Käänteisesti ajatellen jakoperuste on velvoittava: eri aikaan tehtävät asiat sijoitetaan eri prosesseihin. Skedulointiin perustuvan jaon etuja: Vähentää skedulerin työtaakkaa ja pinoihin tarvittavaa tilaa, mistä seuraa edelleen, että reaaliaikaominaisuuksien laskenta helpottuu. Skedulointiin perustuvan jaon haittoja: Jonkin verran ristiriidassa modulaarisuuden kanssa, joskin haitta on pienennettävissä hyvällä ohjelmointityylillä. Voi syntyä suuria kokonaisuuksia, jolloin eri toimintojen rooli voi hämärtyä. Periaate voi liittää toisiinsa toimintoja, joilla ei ole mitään loogista yhteyttä toisiinsa paitsi sama periodi. 5.4.3 Rakenteeseen perustuva jako Rakenteeseen perustuvassa jaossa kutakin (fyysistä) toimilohkoa ohjaa oma prosessinsa. Rakenteeseen perustuvan jaon etuja Toimilohkot voivat olla myös loogisesti toiminnallisia kokonaisuuksia, jolloin jako lähenee toiminnallista jakoa.

98 Sulautettu ohjelmointi Toimilohkon vaihto heijastuu vain yhteen osaan ohjelmistoa. Rakenteeseen perustuvan jaon haittoja Toimilohko voi kattaa monta eri toiminnallista osaa, jolloin toiminnallinen rakenne hämärtyy. Yhdestä prosessista voi tulla hyvin suuri. Toimintojen sisällä voi olla erilaisia ajastustarpeita. 5.4.4 Rinnakkaistaminen Algoritmit rinnakkaistetaan, jotta laskenta voidaan jakaa monille suorittimille. Rinnakkaistamiseen perustuvan jaon etuja Laskenta nopeutuu, mikäli eri osien välillä ei ole (liikaa) riippuvuutta. Rinnakkaistamiseen perustuvan jaon haittoja Algoritmit äärimmäisen vaikeita suunnitella, testata tai edes ymmärtää. Hajautus ei aina onnistu. Onnistunutkaan hajautus ei aina ole tehokas, jos tiedonsiirtoa suorittimien välillä on runsaasti. Hyötyä vain silloin, jos suorittimia on monta. Yksisuoritinkoneessa vaikutus on päinvastainen kuin haluttu. 5.4.5 Yhteenveto Niin kuin yleensäkin reaalimaailmassa, tulee eri periaatteita käytännössä yhdistellä. Esimerkiksi skedulointi vaatii käytännössä sen, että eri aikavaatimuksilla varustetut toiminnat ovat eri prosesseissa, mutta ei pakota yhdistämään samaan aikaan ajettuja prosesseja. Näihin voidaan soveltaa muita periaatteita, esimerkiksi modulaarisuuden mukaista jakoa. Jos kyseessä on hajautettu järjestelmä, rakenteellinen jako on tyypillisesti ensimmäinen jakomalli. Päätetään siis siitä, mikä hajaute-

Rinnakkaisuus ja jako prosesseihin 99 tun järjestelmän osa tekee minkin toiminnon. Kunkin osan sisällä voidaan sitten tehdä yksityiskohtaisempia jakoja muilla menetelmillä. Prosessijako voi olla ilmiselvä jo heti suunnitteluvaiheesta lähtien; toisaalta monissa suunnittelumenetelmissä prosesseja käytetään hyvin eri tavalla kuin mikä on järkevää "luonnossa". Tämän takia prosessijako voi muuttua suunnitteluvaiheen jaosta paljonkin siirryttäessä toteutukseen. Rinnakkaistaminen ja jako monelle prosessille voi vaikuttaa vaikealta asialta. Kuitenkin sitä käytetään paljon ratkaisun yksinkertaistamiseksi. Vaikka se tuo mukanaan omia ongelmiaan, niistä tuleva haitta on usein pienempi kuin saavutettava hyöty. 5.5 Yhteenveto Rinnakkaisuuden mukanaan tuomia ongelmia ovat: 1. poissulkeminen 2. synkronointi 3. lukkiutuminen 4. nälkiintyminen. Lisäksi monet muut tehtävät, kuten esimerkiksi testaaminen, monimutkaistuvat. Yleensä kannattaa pyrkiä suunnittelemaan ajoitukseen liittyvät tehtävät ensin, sillä niihin liittyvien ongelmien löytäminen myöhemmin on vaikeaa. Useita erilaisia strategioita ohjelman jakamiseksi rinnakkaisiin prosesseihin: 1. toiminnallinen jako 2. skedulointiin perustuva jako 3. rakenteeseen perustuva jako 4. laskennan rinnakkaistaminen (erityisesti monisuoritinympäristössä).