7. marraskuu 2009, 19:33

Simultaanikääntelyä

Olen tässä nyt kaksi viikkoa käynyt kurssia Hajautetut ja samanaikaiset järjestelmät. Aiheena on siis ensisijaisesti järjestelmien hajautus mutta myös samanaikaista ajamista, sekä sen erikoistapausta rinnakkaislaskenta. Koska minulla on tupaydinsuoritin koneessani, ajattelin tehdä vanhan käännösskriptini uudestaan, kun ajatus siihen heräsi kurssin demonäytöksessä.

En aivan ole varma, onko yksinkertaista skriptiä alkuperäisessä muodossa järkevää esitellä, mutta koska en ole sitä blogissani käsitellyt, käydään sen konseptit läpi myös.

Peräkkäisratkaisu

Linux-käytön alkuvaiheissa oli vähän haastavaa saada flac-tiedostot mp3-soittimessa kuuluviksi mötiköiksi. Käytin silloin yksittäistiedostoihin ihan alkeellista putkitusta:

flac -cd flac | lame - mp3

Tässä siis käytetään flac-dekooderia purkamaan PCM-virraksi flaccia, ja putkitetaan tulos lamelle, joka on paras kokeilemani MP3-enkooderi. Tämä siis lukee syötevirrasta ja tulostaa tiedostoon. Tämä on alkeellisin versio, ja toimii sinänsä hyvin, mutta jättää esimerkiksi tagit pois ja on muutenkin vähän heikko albumien kääntelyssä. Peräkkäisratkaisussa mennään siis tähän suuntaan:

for arg in "$@"
do
  flac -cd $arg | lame - $arg.mp3
done

Ja tuohon enää heitetään tunnistetietojen kaivaminen (kukin tieto otetaan kierroksella ylös lähdetiedostosta ja käytetään lamen komentoriviparametreja niiden uudelleensijoittamiseen. Käytän tietojen kaivamiseen taginfo-ohjelmaa) niin homma on valmis. Valmis lopputulos, jota olen vuosia jo käytellyt, on ohessa.

Periaatteessa myös tämä peräkkäisratkaisu on samanaikainen, sillä sekä de- että enkoodaus tehdään yhtaikaisesti. Kuitenkin tämä ratkaisu varaa vain yhden ytimen: dekoodaus ei paljoa syö.

Samanaikainen ratkaisu

Samanaikainen ratkaisu syntyy joko vaikeasti tai helposti kikkailemalla. Olen ajatellut rinnakkaistamista jo pitkään, mutta vasta kun opettaja sivumainintana kertoi, kuinka hän oli toteuttanut vastaavan systeemin, päätin kopioida mallia edelleen omaan käyttöön. Tulos on myös siistimpi kuin ensimmäinen versio.

Ensin luodaan peräkkäisratkaisun tavoin silmukassa käännettävien tiedostojen listat, tagit ja muut. Mutta nyt nokkelana ei komenneta suoritettavia ohjelmia toimimaan heti, vaan muodostetaan merkkijonot, joissa esiintyvät ajettavat komennot!

buildlist=()      # taulukko
i=0               # kierrosmuuttuja
for arg in "$@"
do
  buildlist[$i]="flac -cd $arg | lame - $arg.mp3"
  let i=i+1
done

Pseudohko bash-koodi ei käänny sellaisenaan, mutta idea tullee selväksi. Manuaalista syntaksiväritystä hyväksikäyttäen korostan sitä seikkaa, että nyt tallennetaan täsmälleen sellaiset komentorivit ylös, jotka voisi kopypastettaa sitten bash-istuntoon.

Syntyvä taulukko sisältää siis tiedostot, kukin tiedosto rivillään. Jaetaan tämä sitten kahdeksi eri osataulukoksi. On muuten syytä muistaa lisätä rivinvaihtomerkit "\n" kunkin taulukon jäsenen perään tai eteen. Tai lisätä puolipilkut komentojen erottamiseksi toisistaan.

let splitpoint=`echo "${#buildlist[*]} / 2"|bc`
firsthalf=${buildlist[@]:0:$splitpoint}
secondhalf=${buildlist[@]:$splitpoint}

Taulukoiden indekseillä kikkaileminen tuohon tyyliin on vähän epäselvää. Siinä siis on eräänlainen operaattori, joka palauttaa buildlist-taulukon jäsenet nollasta splitpointtiin asti. Ja kolmas rivi sisältää vastaavan systeemin pisteestä loppuun asti. Oppaista lisätietoa.

Bash voi suorittaa skriptiä suoraan syötevirrasta, joten lopuksi nätisti laitamme suorittimen lämpenemään:

echo -e $firsthalf | bash &
echo -e $secondhalf | bash

Ja sehän toimii kivasti. Tämmöisessä simultaaniajelussa kannattaa suosiolla laittaa kaikki oheisohjelmat hiljaisiksi, jotta esimerkiksi jatkuvasti päivittyvä prosenttilukema ei mene sekaisin. Lisäsin itse kunkin käännöksen alkuun yhden echo-lauseen ilmaisemaan uuden kappaleen kääntämisen aloittamista. Tulos on, mitä pitääkin. Lopullinen koodi interaktiivisen laatukyselyn kanssa täältä.

Tageja: , ,

---
---

---

Aiheen vierestä