Fortran ja aika
Kellonajan, päiväyksen ja CPU-ajan selville saaminen Fortran-standardien mukaan

Alun perin Fortran-kielessä ei ollut välineitä kellonajan, päivämäärän tai keskusyksikköajan (CPU-ajan) selville saamiseen. Niinpä tarkoitukseen käytettiin erilaisia järjestelmäkohtaisia rutiineita, mikä tietenkin vähensi ohjelmien siirrettävyyttä. Tyypillisesti ongelmat ilmenivät - ja vanhoja ohjelmia siirrettäessä ilmenevät edelleen - siten, että latausvaiheessa saadaan virheilmoituksia puuttuvista aliohjelmista, esim. getdat. Useinkaan siinä vaiheessa ei ole käytettävissä sen ympäristön dokumentaatiota, jossa ohjelma on alkujaan tehty, joten se, mitä kyseisillä aliohjelmakutsuilla olisi tarkoitus tehdä, jää pääteltäväksi, ehkä arvattavaksikin. Yleensä päättely onnistuu katsomalla, miten aliohjelmakutsuilla saatua dataa käytetään, esim. millaisessa yhteydessä se tulostetaan.

Kellonaika ja päiväys

Tavallisin syy siihen, että halutaan ohjelman käyttöön päivämäärä ja kellonaika, on varmaankin se, että halutaan tulosteisiin tieto siitä, koska ne ovat syntyneet. (Paperitulostuksessa saattaa kirjoitin tai sitä ohjaava ohjelmisto liittää tulosteisiin tiedon tulostushetkestä mukaan automaattisesti. Mutta tulostushetki voi olla eri kuin tulostuvan datan tuottamisen hetki, etenkin, jos tulostus on ohjattu tiedostoon ja tulostetaan siitä myöhemmin.)

Kellonajan ja päiväyksen saa Fortran-90:ssä selville aliohjelmakutsulla

      call date_and_time(date,time,zone,values)

Tässä käytetyille muuttujille (joiden nimet toki ovat vapaasti valittavissa) sopivat määrittelyt olisivat

      character*8 date
      character*10 time
      character*5 zone
      integer values(8)
Aliohjelma date_and_time antaa päivän ja kellonajan kahdella eri tavalla:
  1. taulukossa values komponentteihin jaettuna:
    1. vuosi
    2. kuukausi,
    3. päivä
    4. paikallisen ajan ja UTC-ajan ero minuutteina
    5. tunnit
    6. minuutit
    7. sekunnit
    8. millisekunnit
  2. muuttujissa date, time ja zone merkkijonoina ilman muita välimerkkejä kuin desimaalipiste kellonajassa.

Jos tiedot tarvitaan tulostusta varten, kutsu kannattaa suorittaa juuri ennen tulostuksen aloittamista.

Käytännössä tiedot tulevat jotain kautta tietokoneen sisäisestä kellosta (tai vastaavasta) ja päivämääräkirjanpidosta.

Vaikka ohjelmassa vain tulostettaisiin päiväys ja aika, kannattanee käyttää numeeristavalues-taulukkoa eikä merkkijonomuuttujia date, time ja zone. On nimittäin helpompi formatoida lukujen tulostus kuin muokata valmista merkkijonoesitystä. Esimerkiksi ISO 8601 -standardin mukaisen esitysmuodon tyyliin 2000-11-18T13:49 saisi aikaan näin:

      print 100, values(1), values(2), values(3), values(5), values(6)
 100  format(1X,I4,'-',I2.2,'-',I2.2,'T',I2.2,':',I2.2)

Hiukan lisätietoja aiheesta: Bo Einarsson ja Juri Shokin: Fortran 90 for the Fortran 77 Programmer, kohta Time routines. Se mainitsee myös aliohjelman system_clock, joka mittaa "systeemin aikaa", mutta tämä ilmeisesti pitää tulkita ns. seinäkelloajaksi, ei keskusyksikköajaksi, jota seuraavassa käsitellään. Jos kuitenkin halutaan saada selville esimerkiksi johonkin operaatioon kuluva kokonaisaika ns. seinäkelloaikana, niin se käy Fortran-90:ssä seuraavaan tapaan:

        integer count, count2, rate
        real elapsedtime
        call system_clock(count,rate)
tässä välissä lasketaan ankarasti
        call system_clock(count2)
        elapsedtime = (count2 - count) / real(rate)

Tämän jälkeen muuttuja elapsedtime sisältää ajan sekunteina. Tämä on kuitenkin eri asia kuin seuraavassa tarkasteltava keskusyksikköaika.

Keskusyksikköaika (CPU-aika)

Keskusyksikköaika eli CPU-aika halutaan usein saada selville, jotta tiedettäisiin, mikä osa ohjelman suoritusta on laskennallisesti raskainta. Tätä taas saatetaan käyttää hyväksi harkittaessa ohjelman tehostamista ("optimointia"). Tosin tällaisiin tarkoituksiin on olemassa erityistä profilointiohjelmia. Toisaalta keskusyksikköaika ehkä halutaan selvittää ohjelman suorituksen aikana esimerkiksi siksi, että iterointi voitaisiin lopettaa, kun keskusyksikköajan kulutus on käynyt liian suureksi.

Keskusyksikköajan mittaamista varten ei ole välineitä Fortran-90:ssä, mutta Fortran-95:ssä se onnistuu aliohjelmakutsulla

      call cpu_time(time)

missä time on real-tyyppinen muuttuja, joka saa arvokseen kuluneen keskusyksikköajan sekunteina. Yleensä vain näin saatujen arvojen erotuksia on mielekästä käyttää. Esimerkiksi aliohjelman laskeskele määrätyn kutsun suoritukseen kuluva keskusyksikköaika saadaan selville seuraavasti:

      real alku, loppu
      call cpu_time(alku)
      call laskeskele
      call cpu_time(loppu)
      print 100, loppu - alku
100   format(' CPU-aikaa kului', F7.3, ' sekuntia.')

Hiukan lisätietoja on edellä mainitun Fortran 90 for the Fortran 77 Programmer -aineiston kohdassa Status of Fortran 95, alakohdassa Description of the new features.

Hyvin tehdyssä koodissa tarkistettaisiin ensimmäisen cpu_time-kutsun jälkeen, onko tulos negatiivinen. Standardin mukaan nimittäin järjestelmän tulisi palauttaa jokin negatiivinen arvo, jos se jostain syystä ei voi palauttaa asianmukaista tietoa keskusyksikköajasta.

Mittauksen tarkkuus on konekohtainen ja voi olla yllättävän huono, esim. noin 17 millisekuntia. Jos cpu_time-funktiota käytetään algoritmien tai koodien tehokkuuden vertailuun, kannattaa tarvittaessa menetellä siten, että tutkittava koodi on silmukassa, joka toistaa sen esimerkiksi sata kertaa, ja koko silmukan suoritukseen kuluva aika jaetaan toistokertojen määrällä. (Tosin tällöin mukaan tulee silmukkakontrolliin kuluvaa aikaa, mutta se on yleensä melko merkityksetön.)


Viimeisimmän päivityksen ajankohta: 2000-02-08

Jukka Korpela.