A Fortran programozási nyelv

A Fortran 2008 újdonságai



A BLOCK utasítás

A Fortran 2008-ba bekerült BLOCK utasítással más nyelvekhez hasonlóan dinamikusan hozhatunk létre új hatókört. Ennek az a fő előnye, hogy ezt megelőzően változók deklarációjára csupán a program vagy a függvények és eljárások elején volt lehetőség, míg a létrehozott új blokkban szabadon deklarálhatunk új változókat. Jól szemlélteti a szerkezet használatát az alábbi példa

... IF (swapxy) THEN BLOCK REAL(KIND(x)) tmp tmp = x x = y y = tmp END BLOCK END IF ...

Látható hogy az új blokkban deklarálunk egy új változót a csere elvégzésére, azonban ennek a hatásköre a blokk végén (és még az IF előtt) véget is ér. Továbbá a blokkban deklarált lokális változók elfedik az azonos nevű blokkon kívüli változókat. Például:

I = 42 BLOCK INTEGER :: I I = 7 END BLOCK ! F még mindig 42

Almodulok

Az almodulok segítségével tovább bonthatóak a nagy méretű modulok. Korábban a Fortran 2003-ban ez csupán úgy volt lehetséges, hogy a nagy méretű modult felbontottuk több önálló kisebb modulra, azonban ez felveti annak a veszélyét hogy név ütközések lesznek, valamint felfedjük a belső struktúrát. Továbbá lehetőség van az almodulokat külön újrafordítani, anélkül hogy az őket használó programegységeket újrafordítanánk, elkerülve ezáltal az újrafordítási idő jelentős növekedését a kaszkádolt fordítás miatt. A megvalósítás úgy történik, hogy megadjuk egy modul interface részét, és egy almodulban a megvalósítást:

module points type :: point real :: x, y end type point interface module function point_dist(a, b) result(distance) type(point), intent(in) :: a, b real :: distance end function point_dist end interface end module points submodule (points) points_a contains module procedure point_dist distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2) end procedure point_dist end submodule points_a

Itt a a points modulban megadtunk egy új típust és az interface részében egy modul function-t. A points_a submodule-ban megadtuk a függvényünk megvalósítását, anélkül hogy a függvény teljes fejlécét megismételtük volna.

Coarray változók

A coarray-ek olyan speciális fortran változók, amelyek kifejezetten a párhuzamosság támogatására szolgálnak. Egész pontosan olyan párhuzamos programok írhatók segítségével melyek a PGAS (Partitioned Global Address Space), azaz osztott memóriájú SIMD (Single Instruction Multiple Data) párhuzamos sémát követnek. Minden processnek (image-nek) vannak saját privát változói. Azok a változók, amelyknek van egy ú.n. társdimenziójuk megcímezhetők más image-ekből is. A coarray-ek minden image-en látszódnak és van társdimenziójuk. A következőképpen lehet megadni például:

DOUBLE PRECISION, CODIMENSION[1:4,5,*] :: variable1,variable2 INTEGER :: A[*]

Az utolsó index "*" kell hogy legyen (kivéve ha a változó allokálható - ebben az esetben a hagyományos ":" használatos). Ennek hatására az "A" változó megosztott lesz a különböző image-ek között, amire az alábbi módon hivatkozhatunk:

A[4] = 5 A = 7

ami beírja az "5"-öt a skalár "A" coarray-be a (távoli) [4]-es társindexnek megfelelő image-en, valamint a "7"-et a helyi image-en. Egyszerre csak egy image címezhető meg, így nem lehetséges az üzenetszórás, sem az összes image-ről való begyűjtés. Az aktuális image index lekérdezhető a this_image() függvénnyel, az image-ek száma pedig a num_images() függvénnyel. A coarray-eken mellett elemi szinkronizációs lépések is használhatók. Ezek az alábbiak:

SYNC ALL() SYNC IMAGES() SYNC MEMORY

Ezek mellett megtalálható még a kritikus szakasz is, ami biztosítja hogy az utasítások egy időben csak egy image-en fognak futni:

CRITICAL COUNTER[1] = COUNTER[1] + 1 END CRITICAL

A DO CONCURRENT utasítás

A párhuzamosság további támogatását jelenti a nyelve bekerült DO CONCURRENT utasítás. Az így megadott ciklusokban a ciklusmag egyes iterációinak végrehajtási sorrendje tetszőleges, és párhuzamosan is történhet. Így csupán az biztosított, hogy az iteráció le fog futni minden egyes indexre a megadott tartományból, de a sorrend nem meghatározott. A ciklus végrehajtása akkor ér véget, ha minden iteráció lefutott. Példa:

INTEGER :: A(N), IND(N) DO CONCURRENT (I = 1:N) A(IND(I)) = I END DO

A fenti példában amennyiben nincsenek ismétlődő elemek az IND indexelésre használt tömbben, a úgy a processzor számára könnyen párhuzamosítható, optimalizált kódot kapunk.

A CONTIGUOUS attribútum

Sok esetben a fordító optimálisabb kódot tud generálni ha tudja, hogy egy tömb folytonos memóriaterületet foglal el. Ez az eset áll fenn például az explicit alakú tömbök esetén is, valamint más speciális esetekben. Sok felesleges művelet elkerülhető, ha a fordító előre tudja azt hogy az adött tömb a memória egy folytonos szakaszán elérhető. Erre szolgál a CONTIGUOUS attribútum, amely megadható pointer illetve assumed-shape tömbök esetében.

real, pointer, contiguous :: ptr(:) integer, contiguous, dimension(:,:) : ary

Ennek ellenére az hogy egy tömb folytonosan tárolódik a memóriában az processzorfüggő.

Adattípus bővítések

Az alábbi lista a Fortran 2008 adattípus kiegészítéseit sorolja fel. A lista nem teljes, csupán a legfontosabb változásokat emeli ki

Maximális rang

A tömbök maximális rangja 15-re emelkedett. Coarray-ek esetén ez a 15-ös határ a sima rang és a társ rang összegére vonatkozik.

Hosszú egészek

A processzornak képesnek kell lennie kezelni legalább egy olyan egész típust ahol 18 decimális jegy áll rendelkezésre. Például

integer,parameter :: long = selected_int_kind(18) integer(long) :: la, ll

A megvalósítás nyilván 64-bites egészekkel történik, és az új architektúrákkal kompatibilis programok írásának előfeltétele.

Allokálható komponensek

Rekurzív adatszerkezetek hozhatók létre dinamikus helyfoglalású komponensekre alapozva. Például:

type entry real :: value integer :: index type(entry), allocatable :: next end type entry

A fenti típusdeklaráció a más nyelvekből jól megszokott láncolt listákhoz hasonlít.