A Habanero Java programozási nyelv

Típusok, típuskonstrukciók

Beépített típusok

A Habanero Java nyelvben elérhető minden Javabeli alaptípus. Ezeken felül definiálták a komplex számok típusát, valamint az adatok és számítások elosztásának kezeléséhez a pontok, tartományok, helyek és elosztások típusait.

Komplex számok

A nyelv primitív típusként tartalmazza a komplex számokat. 32- és 64-bites valósakból építkező változata is van, és egy párral lehet megadni:

complex32 cf = (1.0f, 2.0f); complex64 cd = (1.0, 2.0);

A következő műveletek tartoznak a típushoz: real(), imag(), +, -, *, /, ==, !=, toString().

Az aritmetikai műveletek komplex, valamint komplex és valós értékek között is értelmezettek.
Mivel a típus nem-referencia, ezért a toString() metódust nem lehet közvetlenül meghívni, de pl. ki lehet íratni a képernyőre a változó értékét.

Region

A region típusú objektumok egy többdimenziós egész-tartományt reprezentálnak. Azaz a tartomány minden dimenziója egy-egy egészekből álló intervallum. Sajnos jelenleg csak legfeljebb 5 dimenziós tartmányokat lehet létrehozni.

region R = [1:10, 1:5]; //2 dimenziós tartomány, {1..10}×{1..5} R.size(); //a tartomány elemszáma R.rank(); //a tartomány dimenzióinak száma

A region.factory mezőn keresztül elérhető gyártó objektum segítségével elvileg lehetne akár háromszög mátrixhoz tartozó tartományt is gyártani, de ezen metódusok még nem működnek tökéletesen. Azonban az emptyRegion(int) metódus hasznos lehet, amennyiben üres tartományra van szükségünk. A paraméterben a tartomány dimenzióját kell megadni.

Tartományok között értelmezettek a halmazműveletek (union, intersection, difference), tartalmazás vizsgálat másik tartományra, pontra, vagy intek tömbjére is, sőt még Iterator-t is kérhetünk hozzá az iterator() metódus segítségével.

A Tartományban lévő pontok elérhetők nem csak a többdimenziós koordinátáik segítségével, hanem egy sorszámmal is. Adott ponthoz tartozó sorszám lekérdezésére szolgál az ordinal(point), és adott sorszámú elem koordinátájának lekérdezésére a coord(int) metódus.

Lekérdezhetjük egy adott regionről, hogy téglalap alakú-e a rect(), vagy konvex-e az isConvex() metódusok segítségével. Emellett lehetőségünk van lekérdezni a tartomány konvex burkát a convexHull() metódussal.

Point

A point objektumok egy n-dimenziós egész n-est reprezentálnak. Ezek a tartományok pontjai. A region típushoz hasonlóan ezekből is legfeljebb 5 dimenziós példányt lehet definiálni.

point P = [2, 3]; //2 dimenziós pont, ami eleme a korábban definiált R-nek R.contains(P); // tartalmazás-vizsgálat

A pont dimenziója kiolvasható a rank mezőből. A point típus metódusai között találhatók aritmetikai műveleteket megvalósítók(add(point), sub(point), mul(point), div(point)), valamint összehasonlítást elvégző műveletek is (ge(point), gt(point), le(point), lt(point)). Természetesen lehetőség van egyes koordináta-értékeinek lekérdezésére is, melyet a get(int) metódussal tehetünk meg. Az összes koordináta-értéket tartalmazó tömböt a val() metódussal kaphatjuk meg.

Place

A végrehajtási helyek némileg a párhuzamossághoz kapcsolódnak, mégis itt kerülnek részletezésre, mivel a nyelvben beépített típusként jelennek meg, illetve a következőként ismertetett primitív típus, a dist, is ezekkel lesz kapcsolatos.

A Hierarchical Place Trees című cikkben arról olvashatunk, hogy hierarchikus memóriaszerkezet esetén az adatlokalitás kritikus szempont a skálázhatóság elérése érdekében. A kérdés főleg problémás, ha a lokalitás implicit és a programozó számára átlátszó. A hely-fogalom bevezetésével támogatható az adat- és a számítás-elosztás az egyes végrehajtó-egységek között. Minden adat egy adott helyen található, és az egyes szálak is egy adott helyen hajtódnak végre. Amennyiben a helyeket a memóriahierarchiának megfelelően szervezzük, hatékonyabb végrehajtást tudunk garantálni.

A Habanero Java jelenleg ennek a hierarchikus elképzelésnek egy lapos változatát valósítja meg a place osztály példányain keresztül. Magukat a place objektumokat a futtató környezet készíti el a következő paraméterének megfelelően:

-places <p>:<t> set number of places and threads per places

A helyek egy ciklikus láncolt listában vannak, lehet lépni az előzőre (prev()) és a következőre (next()). (Persze maga a szál nem kerül át egy másik helyre, csak tudunk hivatkozni más helyekre is.) Az aktuális hely a here kulcsszóval lekérdezhető. A helyek 0-tól place.MAX_PLACES-ig vannak indexelve. Az első hely a place.FIRST_PLACE, az utolsó a place.LAST_PLACE mezőben található. Adott helyről megkérdezhető, hogy az első-e (isFirst()) vagy az utolsó-e (isLast()). A ciklikus lista adott pozícióján lévő hely is megkapható a place.places(int) metódustól.

Az objektumoktól lekérdezhető a helyük a getLocation() metódussal.

Jelenleg a helyek csak a tevékenységek logikai összekapcsolására használhatók, nem kötődnek a hardverhez. Minden egyes helyhez tartozik bizonyos számú Thread melyek végrehajtják a helyhez tartozó tevékenységeket. A Threadeket a JVM ütemezi, azonban a Habanero Java fejlesztőinek tervei között szerepel, hogy egy későbbi kiadásban a szálakat a magokhoz kössék, így az egyes helyek a hardver fizikai egységeihez kapcsolódnának.

Distribution

A dist osztály objektumai leképezések egy tartomány (region) és helyek között, ami alapvetően elosztott tömbök készítéséhez lenne jó. Sajnos az elosztott tömböket a nyelv egyelőre nem támogatja.

Definiáltak különböző dist objektumok közötti, illetve dist és region közötti halmazműveletek. Tartalmazás-vizsgálatot pointra is. Lekérdezhető egy dist objektum értelmezési tartománya (region) és értékkészlete(places()). Adott pozícióhoz tartozó hely lekérdezése csak a koordináták explicit megadásával lehetséges, point objektummal nem. Erre szolgál a get() metódus, mely a tartomány dimenziójának megfelelő számú int paramétert vár.

Létrehozni a dist.factory mezőn keresztül elérhető hj.array.DistributionFactory típusú gyártó objektum segítségével lehet.
Adott tartományhoz létrehozható elosztások típusai:

konstans
constant(region, place)
lokális
local(region)
Ez lényegében: constant(region, here)
blokkos
block(region)
ciklikus
cyclic(region)
véletlenszerű
random(region)

Helyek egy halmazához pedig létrehozható egy bijekció a unique([Set]) metódussal. (A szögletes zárójelek a paraméter opcionális voltát jelzik.) Természetesen a paraméterként átadott halmazba place típusú értékeket kell elhelyezni, ami sajnos a Habanero Java sablonok terén fennálló hiányosságai miatt nem jelenik meg szintaktikusan. Amennyiben paraméter nélkül hívjuk meg, úgy az összes hely bekerül az értékkészletbe.

Típuskonstrukciók

A Habanero Java nyelvben elérhető minden Javabeli típuskonstrukciós eszköz, azonban ezeken felül bevezették a többdimenziós tömbök fogalmát.

Többdimenziós tömbök (nézetek)

A nyelv készítői úgy gondolták, hogy a többdimenziós tömbökre szükségük van, azonban igazándiból nem is csináltak többdimenziós tömböket a Habanero Javában. Csupán az arrayView-nak nevezett konstrukciót vezették be, amely a hagyományos egydimenziós tömbök többdimenziós interpretálásáért felel. A nézetek jelölésére a [.]-t használják.

final region R = [1:10, 1:5]; //mint fentebb int[] base = new int[R.size()]; //megfelelő elemszámú egydimenziós tömb int[.] view = new arrayView(base, 0, R); //a base egydimenzió tömb többdimenziós nézete //paraméterezés: base-array, offset, region

Ilyen formán egy tömbre több nézet is ráhúzható, tehát pl. egy 16 elemszámú tömb nézhető egy 2×8-as, egy 8×2-es, de akár egy 2×2×4-es többdimenziós tartományon keresztül is.
Természetesen amennyiben ismerjük az eredeti tömböt, az a hagyományos módon is elérhető marad.

for(int i = 0; i < base.length; ++i) { base[i] = i; } for(point[i, j] : X.region) { System.out.print(X[i, j] + " "); }
Kimenet:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 \ 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

Ahogy a fenti példán is látható, egy for ciklusban a point objektumot a koordináta-változói segítségével adhatjuk meg. Jogos igény lehet koordináták nélkül, pusztán egy nevet adni a point-nak, erre még később visszatérünk.

A nézeteket a felszín alatt sima Javabeli osztályokkal valósították meg, és a fordító nem tud arról, hogy hány dimenziós tartományokat kezelnek, így a következő problémás helyzetekhez juthatunk:

for(point[i] : X.region) { System.out.println(X[i] + " "); }
Kimenet:
0 1 2 3 4 5 6 7 8 9

Elég nagy gond, hogy véletlenül csak a tömb egy részét járjuk be, de legalább a program nem állt meg. A ténylegesnél több koordináta-változó megadása azonban a program abortálásához vezet. Persze a futási idejű hibát az előbbi esetnél jobbnak is tekinthetjük, hiszen legalább észleljük, hogy valami nincs rendben.

for(point[i, j, k] : X.region) { System.out.println(X[i, j, k]); }
Kimenet:
Exception in thread "pool-0-thread-0: sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)" java.lang.AssertionError at hj.array.MultiDimRegion.rank(MultiDimRegion.java:167) at Array1.main(Array1.hj) at Array1$Main.runHjTask(Jasmin) at hj.runtime.wsh.InvocationStrategy$AsyncInFinishStrategy.invokeHjTask(InvocationStrategy.java:82) at hj.runtime.wsh.Activity.run(Activity.java:201) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:619)

Ahogy már fentebb is jeleztem, felmerül az igény koordináták nélkül, pusztán egy point típusú változót deklarálni a ciklushoz, ami nyilván a legkényelmesebb, és ráadásul biztonságos megoldás is lenne.

for(point P : X.region) { System.out.println(X[P]); }

A fenti kód szintaktikailag, és elméletileg szemantikailag is teljesen helyes, ám a fordító mégsem képes belőle bájtkódot generálni arra hivatozva, hogy nem találja a P értékét. A nyelv fejlesztői tisztában vannak ezzel a problémával, de még nem tudták megoldani.

A fenti példákból látszik, hogy hiába lenne sok esetben kényelmes a többdimenziós tömbök használata, a megvalósítás jelenlegi hiányosságaival eléggé veszélyes, és kényelmetlen a használatuk.