Hyppää sisältöön

Welcome to our weekly research support coffee hour on Zoom! Click here for more information.

Warning!

Puhti scratch disk is becoming very full (80+ % ) resulting in performance degradation. Everybody is advised to only keep actively processed data on scratch, all other data should be deleted, transferred to host institute or stored in Lumi-O. No new quota will be granted. Click here for a tool for examining your disk usage.

GNU Parallel -työvuo monille pienille, riippumattomille ajoille

Tavoitteena on työnkulku, joka on

  1. helppo ymmärtää,
  2. sopii hyvin eräjono järjestelmään, ja
  3. ei kuormita rinnakkaista tiedostojärjestelmää.

Työvuotyökaluja on runsaasti. Riippumatta siitä, minkä työkalun valitsee, se ei todennäköisesti sellaisenaan sovi juuri kyseiseen työnkulkuun ja taustalla olevaan laskenta-alustaan. Useimmissa tapauksissa tarvitaan jonkin verran ohjelmointia. Aiheeseen läheisesti liittyvää keskustelua on Taulukkotyöt -luvussa osoitteessa https://docs.csc.fi.

GNU Parallelin vahvuudet

  • Ei vaadi tietokantaa tai pysyvää hallintaprosessia
  • Skaalautuu helposti suureen määrään tehtäviä/solmuja
  • Käyttää ajastimen resursseja tehokkaasti

GNU Parallelin haitat

  • Käyttäjän on järjesteltävä syöte- ja tulostiedostot huolellisesti
  • Skaalaaminen vaatii järjestelmän I/O-suorituskyvyn huomioimista
  • Bash-skriptauksen perustuntemus on suositeltavaa
  • Vain sarjallisia alitehtäviä
  • Ei tukea riippuvuuksille tai virheistä palautumiselle

Järjestelmän rajoitusten yleiskuva

Kunkin käyttäjän kuukaudessa lähettämien töiden enimmäismäärä tulisi pitää alle tuhannessa. Liian suuri määrä eräajoja tuottaa ylimääräistä lokidataa ja hidastaa työnajastinta. Taulukkotyöt ovat käytännössä vain lyhennysmerkintä, joten yksi 100 jäsenen taulukkotyö lasketaan eräjono järjestelmän näkökulmasta samaksi kuin 100 yksittäistä työtä.

Työn enimmäiskestoa rajoittavat jonon parametrit. Vähimmäiskestoa ei ole rajoitettu, mutta jos työ on liian lyhyt, se aiheuttaa vain suhteettoman suuren ajastuksen yleiskuorman eräjärjestelmässä.

Tip

Hyvä tavoite on kirjoittaa eräajot niin, että ne valmistuvat jossain kahden tunnin ja kahden päivän välillä.

Rinnakkaiset tiedostojärjestelmät toimivat huonosti, kun yksi asiakas (sovellusohjelma) yrittää tehdä liian paljon tiedosto-operaatioita. Tällaisia tapauksia voivat olla esimerkiksi Conda-paketinhallinnalla suoraan jaettuun tiedostojärjestelmään asennetut sovellukset. Yksi miniconda-ympäristö sisältää helposti yli 20000 tiedostoa, ja Anaconda-jakelu on vielä paljon pahempi. Monia näistä tiedostoista täytyy avata aina, kun Conda-sovellus käynnistetään. Kun ajetaan paljon suhteellisen lyhyitä töitä, vältä Condalla asennettujen sovellusten käyttöä. Jos sovelluksesi kuitenkin vaatii monimutkaisen ympäristön, käytä Singularity-kontteihin pakattuja sovelluksia, jotka näkyvät tiedostojärjestelmälle yhtenä tiedostona. Jos haluat kontittaa Conda-ympäristön helposti, katso Tykky-konttikääretyökalu

"Liikaa tiedostoja" -ongelmat ovat yleisiä myös työnkuluissa, jotka koostuvat tuhansista pienistä ajoista. Yleisohjeena pidä yhdessä hakemistossa olevien tiedostojen määrä selvästi alle tuhannen ja järjestä data useisiin hakemistoihin. Käytä myös komentoa csc-workspaces seurataksesi, että projektiesi tiedostojen kokonaismäärä pysyy selvästi rajojen alapuolella. Jos suurin osa tiedostoista on väliaikaisia tai niitä on yksinkertaisesti liikaa, nopeiden paikallisten SSD-levyjen käyttö I/O-solmuissa voi ratkaista ongelman. Voit pakata pieniä tiedostoja suuremmaksi arkistotiedostoksi komennolla tar. Tärkeintä on, että jos tulostiedostoja on sellaisia, joita et tarvitse, selvitä miten niiden kirjoittaminen voidaan estää jo alun perin.

Ota yhteyttä osoitteeseen servicedesk@csc.fi, jos työnkulkusi tarvitsee apua yllä annettuihin rajoihin sovittamisessa.

Esimerkkitapaus: 80000 riippumatonta ajoa

Yleisesti työnkulun suunnitteluun tarvitaan kolme syötettä:

  1. Kuinka monta ajoa on yhteensä?
  2. Kuinka kauan yksi ajo kestää?
  3. Kuinka monta tiedostoa syntyy?

Kaksi ensimmäistä määrittävät, miten ajot ryhmitellään eräajoiksi, ja viimeinen määrittää hakemistohierarkian.

Tarkastellaan esimerkkiä, jossa meillä on 80000 riippumatonta, rinnakkaistamatonta yhden ytimen ajoa, joista kukin kestää 0:sta 30 minuuttiin, keskiarvon ollessa 15 minuuttia. Pahimmassa tapauksessa kaikki eräajon ajot kestävät enimmäisajan eli 30 minuuttia. Voimme nähdä, että yksi 40 tunnin eräajo riittää yhdellä ytimellä vähintään 80 ajolle ja täydellä 40 ytimen laskentasolmulla 3200 ajolle. Näin ollen kaikkien 80000 ajon pitäisi mahtua 25 kappaleeseen 40 tunnin eräajoja, joista kukin varaa yhden kokonaisen laskentasolmun.

Oletetaan, että sovelluksemme on todellinen levytilasyöppö, ja yhden säilytettävän syötetiedoston ja yhden säilytettävän tulostiedoston lisäksi se luo nykyiseen hakemistoon myös 100 väliaikaista tiedostoa. Yhdessä hakemistossa voi olla enintään noin 400 syöte- ja tulostiedostoa, ja väliaikaisille tiedostoille voidaan käyttää I/O-solmujen nopeaa paikallista levyä. Näin 80000 ajolle saadaan 200 hakemistoa, joissa kussakin on 400 ajoa.

many
    dir-001
        input-001
        input-002
        ...
        input-400
    dir-002
    ...
    dir-200

Lisähuomioita tarvitaan, jos yksittäiset ajot ovat rinnakkaisia tai niiden välillä on riippuvuuksia, mutta se on jo toinen tarina.

Katsotaan esimerkkitapauksen työskriptiä:

#!/bin/bash
#SBATCH --partition=small
#SBATCH --account=<project>
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=40
#SBATCH --time=40:00:00
#SBATCH --mem=160G
#SBATCH --gres=nvme:3600
#SBATCH --array=0-24

module load parallel

cd /scratch/${SLURM_JOB_ACCOUNT}/many

(( from_dir_index = SLURM_ARRAY_TASK_ID * 8 + 1 ))
(( to_dir_index = SLURM_ARRAY_TASK_ID * 8 + 8 ))

job_dirs=$(printf "%dir-%03d " $(seq $from_dir_index $to_dir_index))

find $job_dirs -name 'input-*' | \
    parallel -j $SLURM_CPUS_PER_TASK bash wrapper.sh {}

Eräajo varaa kokonaisen solmun 40 tunniksi. Solmussa käynnistyy yksi tehtävä, jolla on käytössään kaikki solmun 40 CPU-ydintä. Koska varaamme kaikki ytimet, voimme samalla varata kaiken muistin ja koko paikallisen levyn, tässä ei tarvitse kitsastella. Viimeinen rivi, #SBATCH --array=0,24, kertoo eräjärjestelmälle, että tästä työstä suoritetaan 25 kopiota, joista jokainen tunnistetaan yksilöllisellä numerolla ympäristömuuttujassa SLURM_ARRAY_TASK_ID. Jonotilanteesta riippuen monet näistä töistä voivat ajautua rinnakkain.

Seuraavaksi lataamme moduulin, joka tarjoaa GNU parallelin. Käytämme tätä työkalua solmun sisällä "ajastamaan" kaikki työn 3200 ajoa niin, että kaikkina aikoina kaikki 40 ydintä ovat käytössä mutta eivät ylikuormitettuina.

Seuraavat rivit laskevat, mitkä hakemistot kuuluvat nykyiseen taulukkotyöhön, käyttäen SLURM_ARRAY_TASK_ID-ympäristömuuttujaa.

Skriptin pää-"silmukka" on toteutettu GNU parallel -komennolla parallel. Valinnalla -j $SLURM_CPUS_PER_TASK kerromme GNU parallelille, että sen tulee pitää käynnissä 40 komentoa (sovellusta) rinnakkain. Koska meidän täytyy kopioida tiedostoja paikalliselle SSD:lle ja sieltä pois jokaisessa ajossa, käärimme sovelluksemme pieneen komentotulkkiskriptiin wrapper.sh, joka ottaa syötetiedoston nimen argumenttina. Syötetiedostojen nimet syötetään GNU parallelille putken kautta, ja GNU parallel jatkaa komennon bash wrapper.sh <input file> suorittamista niin kauan kuin putkessa on argumentteja.

Kääreskriptin erottaminen eräajon skriptistä mahdollistaa niiden kehittämisen ja testaamisen erikseen. Yleisesti kannattaa käyttää pieniä testiaineistoja työnkulkua kehitettäessä eikä odottaa, että kaikki toimii täydellisesti ensimmäisellä yrittämällä. Voit tutkia ja testata pientä versiota esimerkkitapauksesta seuraavasti:

export SBATCH_ACCOUNT=<your project>
wget -c https://a3s.fi/docs-files/support/tutorials/many.tar.gz -O - | tar xz
cd many
bash create_inputs.sh
tree /scratch/${SBATCH_ACCOUNT}/many
sbatch job.sh

Note

Useiden erillisten töiden ajaminen suuremman varauksen sisällä voi johtaa käyttämättömiin resursseihin. Varmista, että tällaisessa työssä on paljon nopeasti suoritettavia ajoja, jotta viimeisenä käynnissä oleva työ ei pidä koko varausta turhaan voimassa pitkään. Alityön keston tulisi siis olla paljon lyhyempi kuin varauksen kesto, ja alitöiden määrän paljon suurempi kuin yhdessä tehtävässä pyydettyjen ytimien määrä.

Voit käyttää seff -työkalua selvittääksesi, kuinka kauan aiemmat työt ovat kestäneet.

Suomenkielinen tekoälykäännös

Sisällössä voi esiintyä virheellistä tietoa tekoälykäännöksestä johtuen.

Klikkaa tästä antaaksesi palautetta