Chapel TIE-20306 Ryhmä 91 Joonas Eloranta Lari Valtonen
Johdanto Chapel on Amerikkalaisen Cray Inc. yrityksen kehittämä avoimen lähdekoodin ohjelmointikieli. Chapel on rinnakkainen ohjelmointikieli, joka on tarkoitettu etenkin suurten kokoluokan järjestelmien ja supertietokoneiden käyttöön. Chapel on skaalautuva kieli, joten sitä voidaan käyttää myös muissa järjestelmissä, joissa on useampi ydin, sekä mahdollisuus rinnakkaisuuteen(esimerkiksi kaikki nykyaikaiset tietokoneet), eikä vain suurissa supertietokoneissa, joita varten se on aluksi suunniteltu. Monisäikeistä suoritusmallia Chapel tukee käyttäen korkean tason abstraktioita erilaisista rinnakkaisen ohjelmoinnin toteutustavoista kuten tiedon rinnakkaisuus, jossa sama operaatio voidaan tehdä useammalle elementille samaan aikaan. Tehtävien rinnakkaisuus, jossa ydin voi suorittaa esimerkiksi plus- ja kertolaskuoperaatiot samanaikaisesti. Rinnakkaisuus, jossa useita funktioita voidaan suorittaa samanaikaisesti, sekä sisäkkäinen sisäkkäinen rinnakkaisuus joka tarkoittaa sitä, että ohjelman tehtävien sisällä voidaan luoda uusia tehtäviä. Chapel on suunniteltu niin sanotun Multiresolution philosophyn mukaisesti. Tämä tarkoittaa sitä, että ohjelmoija voi aluksi kirjoittaa koodia hyvin korkealla abstraktiotasolla, mutta tarpeen mukaan heillä on pääsy myös syvemmälle lähemmäs rautaa, jos tarve vaatii. Tämä mahdollistaa suorituskyvyn matalan tason optimoinnin tarpeen niin vaatiessa, mutta jos tarvetta ei ole, voidaan pysyä korkeammalla tasolla, jolloin koodin kirjoittaminen on nopeampaa. [1] Syntaksi ja tietotyypit Chapelin suunnitteluperiaate oli luoda kieli, joka mahdollistaa suuren skaalautuvuuden ja tehokkuuden, mutta kieli tulisi olla myös helppoa oppia, sekä kirjoittaa. Kielen syntaksi muistuttaakin melko paljon C-kieltä, eikä sen perusperiaatteiden ymmärtäminen ole vaikeaa, jos on käyttänyt ennen esimerkiksi C:tä C++:aa, Pythonia tai Javaa. Näiden kielien tapaan Chapel tukee esimerkiksi olioita ja luokkia. Chapel käyttää syntaksissaan aaltosulkeita erottamaan koodilohkot toisistaan. Rivit myös päättyvät puolipilkkuun. Kieli on myös staattisesti tyypitetty, tyyppiturvallinen kieli, jossa jokaisen muuttujan tyyppi tunnetaan käännösaikana. Muuttujat alustetaan avainsanalla var, jonka jälkeen määritellään muuttujan nimi ja lopuksi sen tyyppi tai muuttujan arvo. Tyypin voi myös jättää mainitsematta, jolloin se päätellään alustusarvon tyypistä. Muuttujia voi myös castata tyypistä toiseen. Tämä tapahtuu yksinkertaisesti luomalla uusi muuttuja, jolle castattava muuttuja annetaan parametrina. Esimerkiksi merkkijonon castaus tyypistä string tyyppiin int onnistuu seuraavasti: var mystring = 1234 ; var myint = mystring: int;
Chapelin käyttämiä perustietotyyppejä ovat seuraavat: Tyyppi Kuvaus Oletusarvo bool Totuusarvo false int Etumerkillinen kokonaisluku 0 uint Etumerkitön kokonaisluku 0 real Reaalinen liukuluku 0.0 imag Imaginääriluku 0.0i complex Kompleksinen liukuluku 0.0+0.0i string Merkkijono Chapellen perus tietotyypit ja niiden oletusarvot Kuten taulukosta nähdään, Chapel määrittelee tietotyypeilleen myös oletusarvon, jota käytetään, jos muuta arvoa ei ole annettu. Complexia lukuun ottamatta kaikki muuttujat ovat 64-bittisiä. Ohjelmoija voi kuitenkin halutessaan muuttaa sitä, kuinka suuria muuttujat ovat. Kokonaisluvuille ja booleanille pienin arvo on 8 bittiä, kun taas reaali- ja imaginääriluvuille se on 32 bittiä. Kompleksiluvut voivat olla vähintään 64 bittisiä ja niiden oletusarvo on 128 bittiä. Merkkijonoille näitä arvoja ei ole määritelty. [2] Tietovarastona Chapel käyttää taulukoita. Taulukot eroavat C-kielen taulukoista siten, että niihin voidaan lisätä alkioita myöhemmin, samaan tapaan kuin C++:n vektoreihin. Taulukot voivat olla myös kaksiulotteisia. Hieman outoja Chapelin taulukoista tekee se, että ohjelmoija voi halutessaan alustaa niihin vain tietyt indeksit. Esimerkiksi rivi var C: [2,4,6] int; Luo taulukon, joka pitää sisällään vain indeksit 2, 4 ja 6. Eli indeksejä 1, 3 ja 5 ei ole käytössä lainkaan ja jos näitä yritetään koodissa indeksoida, palauttaa ohjelma virheen. Alla on kuvattu tavat, jolla Chapelissa luodaan yksiulotteinen ja kaksiulotteinen taulukko: //Yksiulotteinen taulukko var A: [1..5] int; //Kaksiulotteinen taulukko var B: [1..5, 1..5] int; Taulukoille annetaan siis väli, tai halutut indeksit, joille taulukko luodaan. Jos taulukko luodaan käyttäen väliä, tulee taulukosta niin sanotusti tiheä (dense). Jos taas taulukolle listataan halutut indeksit, tulee siitä harva(sparse). Tiheisiin taulukoihin uusien elementtien lisääminen onnistuu
käyttäen push_back() operaattoria, mutta harvoihin sen käyttö ei onnistu, vaan kääntäjä palauttaa virheen. Chapelista löytyvät myös C-kielestäkin tutut for ja while silmukat, ehtolauseet, sekä C:n switch lausekkeen tapaan toimiva select-lauseke. Myös iteraattoreiden luonti on mahdollista. Iteraattori on kuin funktio, mutta se säilyttää oman tilansa ja se voi palauttaa useamman arvon. Iteraattoreita käytetään Chapelissa etenkin silmukoiden kanssa, jolloin silmukkamuuttujan arvoon voidaan jokaisella kierroksella palauttaa iteraattorin arvo. Alla on kuvattu koodi, jolla saadaan tulostettua näkyviin 10 ensimmäistä fibonacchin lukua iter fibonacci(n: int) { var (current, next) = (0, 1); for 1..n { yield current; (current, next) = (next, current + next); } } for indexvar in fibonacci(10) { write(indexvar, ", "); } Iteraattorille annettava parametri määrittää tässä tapauksessa sen, kuinka monta arvoa se palauttaa. Iteraattorin sisällä oleva yield avainsana palauttaa muuttujan arvon, ja se otetaan talteen indexvar silmukkamuuttujaan. Kun iteraattori on suorittanut itsensä 10 kertaa, lopettaa se toimintansa ja myös silmukan suoritus loppuu. Tehtävien rinnakkaisuus Tehtävä on Chapelissa laskennan yksikkö, joka suoritetaan rinnakkain muiden tehtävien kanssa. Nämä muodostavat perustan Chapelin kaikille rinnakkaisuudelle. Ohjelma, suoritus alkaa yhtenä tehtävänä ja uusia tehtäviä voi lisätä rinnakkaisajon aikaansaamiseksi. Ohjelma ei kuitenkaan automaattisesti lisää näitä, vaan se on ohjelmoijan itse määritettävä. Tehtävän suorituksen pituutta ei ole erikseen määritelty. Tehtävät voivat olla sisäkkäisiä, eli tehtävät luovat uusia tehtäviä. Tehtävät voivat jakaa tietoa keskenään perinteisten leksikaalisten lohkojen keinoin. Chapel ei takaa ohjelmien oikeellisuutta, mikäli tehtäviä yritetään ajaa sarjassa niiden päättymiseen asti. Tarkemmin sanottuna, on mahdollista että tehtävät ajetaan synkronoituna. Ne voivat myös estää tai odottaa muiden tehtävien suoritusta. Tehtävät voivat myös lukkiutua ja aiheuttaa kilpajuoksutilanteita.[3]
Yksinkertaisin tapa luoda tehtävä on lauseen tai lohkon aloittaminen begin -avainsanalla. Esimerkiksi: begin writeln("hei"); writeln("moi"); Koska näitä ei ole synkronoitu, suorituksen järjestys on määrittelemätön ja tulostus voi tapahtua kummassa järjestyksessä tahansa. Muuttujia voi synkronoida lisäämällä muuttujan tyypin eteen avainsanan sync, jolloin muuttuja sisältää tilan, joka voi olla tyhjä tai täysi. Muuttujaa ei voi lukea ennen kuin se on täysi ja siihen ei voi kirjoittaa ennen kuin se on tyhjä.[4] Muistinhallinta Chapel tukee dynaamista muistinhallintaa siten, että luokkaolioille voi varata muistia avainsanalla new ja vapauttaa avainsanalla delete. Chapel suunniteltiin alunperin ilman delete -avainsanaa. Aikomuksena oli toteuttaa roskienkeruu hajautetulle muistille (distributed-memory garbage collection), mutta tämä osoittautui tutkimusongelmaksi. Odotetaan, että tulevaisuudessa kieli tulee tukemaan vaihtoehtoisesti käytettävää hajautetun muistin roskienkeruuta sekä aluekohtaista muistinhallintaa (region-based memory management).[4]
Lähteet [1] https://chapel-lang.org/overview.html [2] https://chapel-lang.org/docs/latest/users-guide/base/basictypes.html [3] https://chapel-lang.org/docs/1.13/users-guide/taskpar/taskparallelismoverview.html [4] https://chapel-lang.org/docs/latest/_downloads/chapellanguagespec.pdf