Array jobs
Monissa tapauksissa laskennalliseen analyysitehtävään sisältyy useita samankaltaisia riippumattomia osatehtäviä. Käyttäjällä voi olla useita tietoaineistoja, joita analysoidaan samalla tavalla, tai sama simulaatiokoodi suoritetaan useilla eri parametreilla. Tällaisia tehtäviä kutsutaan usein häpeämättömän rinnakkaisiksi tehtäviksi tai tehtäväviljelyksi, koska ne voidaan periaatteessa jakaa niin monelle prosessorille kuin on tehtäviä suoritettavana.
Array jobs -lähestymistapa voi olla sopiva, jos:
- Kunkin riippumattoman tehtävän suoritusaika on tarpeeksi pitkä, jotta SLURM-eräjärjestelmän
ylijäämäkustannukset ovat merkityksettömiä.
- Yksittäisten ajoaikojen tulee olla pidempiä kuin noin 30 minuuttia.
- Riippumattomien tehtävien kokonaismäärä ei ole liiallinen.
- Yhdellä käyttäjällä voi olla enintään 400 tehtävää joko suorituksessa tai jonossa eräjärjestelmässä.
Muut vaihtoehdot
Kun suoritusaika on hyvin lyhyt tai yksittäisten tehtävien määrä on erittäin suuri,
on olemassa sopivampia vaihtoehtoja suuren läpimenon laskentaan. Suositeltu työkalu näihin
käyttötapauksiin on HyperQueue. Vaihtoehtoina ovat myös
Linux xargs
-työkalu
(katso tämä eräskripti esimerkkinä käytöstä)
ja GNU Parallel -shell-työkalu.
Määritä taulukkotyö
Slurmissa taulukkotyö määritetään käyttämällä vaihtoehtoa --array
tai -a
, esim.
käynnistää ei vain yhtä erätehtävää, vaan 100 erätehtävää, joissa alitehtäväkohtaisella ympäristömuuttujalla $SLURM_ARRAY_TASK_ID
on arvo 1:stä 100:aan. Tätä muuttujaa voidaan sitten käyttää varsinaisissa tehtävän käynnistämiskomennoissa siten, että kukin osatehtävä käsitellään. Kaikki alitehtävät käynnistetään eräjärjestelmässä kerralla, ja ne suoritetaan samalla käyttämällä niin monta prosessoria kuin on saatavilla.
Määrittelemällä työalueen lisäksi voit myös antaa luettelon työindekseistä, esim.
käynnistää kolme työtehtävää $SLURM_ARRAY_TASK_ID
arvoilla 4, 7 ja 22.
Voit myös sisällyttää askelkoon työalueen määrittelyyn. Taulukkotyön määritelmä
suorittaisi viisi työtehtävää $SLURM_ARRAY_TASK_ID
arvoilla: 1, 21, 41, 61 ja 81.
Joissakin tapauksissa voi olla järkevää rajoittaa samanaikaisesti suoritettavien prosessien määrää.
Tämä tehdään merkinnällä %max_number_of_jobs
. Esimerkiksi tapauksessa, jossa sinulla on 100 tehtävää,
mutta lisenssi vain viidelle samanaikaiselle prosessille, voit varmistaa, ettet käytä lisenssiä
liikaa käyttämällä määritelmää
Yksinkertainen taulukkotyön esimerkki
Ensimmäisenä taulukkotyön esimerkkinä oletetaan, että meillä on 50 tietoaineistoa (data_1.inp
, data_2.inp
... data_50.inp
), jotka haluaisimme analysoida käyttämällä ohjelmaa my_prog
, joka käyttää syntaksia
Kukin osatehtävä vaatii alle kaksi tuntia laskenta-aikaa ja alle 4 GB muistia. Voimme suorittaa kaikki 50 analyysitehtävää seuraavalla erätyöskriptillä:
#!/bin/bash -l
#SBATCH --job-name=array_job
#SBATCH --output=array_job_out_%A_%a.txt
#SBATCH --error=array_job_err_%A_%a.txt
#SBATCH --account=<project>
#SBATCH --partition=small
#SBATCH --time=02:00:00
#SBATCH --ntasks=1
#SBATCH --mem-per-cpu=4000
#SBATCH --array=1-50
# suorita analyysikomennon
my_prog data_${SLURM_ARRAY_TASK_ID}.inp data_${SLURM_ARRAY_TASK_ID}.out
Erätyöskriptissä rivi #SBATCH --array=1-50
määrittelee, että 50 alitehtävää lähetetään.
Muut #SBATCH
-rivit viittaavat yksittäisiin alitehtäviin. Tässä tapauksessa yksi
alitehtävä käyttää enintään yhtä prosessoria (--ntasks=1
), 4 GB muistia (--mem-per-cpu=4000
)
ja voi kestää enintään kaksi tuntia (--time=02:00:00
). Kuitenkin kaikkien 50 tehtävän
kokonaiskellonaika ei ole rajoitettu.
Tehtävän suorituskomentojen kohdalla skripti käyttää $SLURM_ARRAY_TASK_ID
muuttujaa
määritellessään syöte- ja tulostetiedostot niin, että ensimmäinen alitehtävä suorittaa komennon
toinen suorittaa komennon
ja niin edelleen.
Tehtävä voidaan nyt käynnistää komennolla
Tyypillisesti kaikki tehtävät eivät suoriteta samalla kertaa. Kuitenkin jonkin ajan kuluttua
voi olla käynnissä useita tehtäviä samanaikaisesti. Kun erätyö on valmis, hakemisto data_dir
sisältää 50 tulostetiedostoa.
Kun taulukkotyö on lähetetty, komento
paljastaa, että sinulla on yksi odottava työ ja mahdollisesti useita muita töitä käynnissä
eräjärjestelmässä. Kaikilla näillä töillä on jobid
, joka sisältää kaksi osaa: taulukkotyön
jobid
-numero ja alitehtävän numero. On suositeltavaa ohjata kunkin alitehtävän
tuloste erilliseen tiedostoon, sillä tiedostojärjestelmä voi kaatua, jos useita kymmeniä
prosesseja yrittää kirjoittaa samaan tiedostoon samanaikaisesti. Jos tulostetiedostot täytyy
liittää yhteen tiedostoon, se voidaan usein tehdä helposti taulukkotyön päätyttyä.
Esimerkiksi yllä olevassa tapauksessa voisimme kerätä tulokset yhteen tiedostoon komennolla
#SBATCH
-rivien kohdalla voit käyttää määrittelyjä %A
ja %a
, jotta voit antaa ainutlaatuisia
nimiä kunkin alitehtävän tulostiedostoille. Tiedostonimissä %A
korvataan taulukkotyön
tunnuksella ja %a
korvataan $SLURM_ARRAY_TASK_ID
-arvolla.
Tiedoston nimiluettelon käyttö taulukkotyössä
Yllä olevassa esimerkissä pystyimme käyttämään $SLURM_ARRAY_TASK_ID
:tä viittaamaan syötetiedostojen
järjestysnumeroihin. Jos tämän tyyppinen lähestymistapa ei ole mahdollinen, voidaan
ennen erätyön lähettämistä luoda tiedosto- tai komentoluettelo. Oletetaan, että meillä on
samantyyppinen tehtävä kuin yllä, mutta tiedostonimet eivät sisällä numeroita, vaan ovat muodossa
data_aa.inp
, data_ab.inp
, data_ac.inp
ja niin edelleen. Nyt meidän on ensin tehtävä
analysoitavien tiedostojen luettelo. Tässä tapauksessa voisimme kerätä tiedostonimet tiedoston
namelist
muotoon komennolla
Komento
lukee tietyn rivin nimilista-tiedostosta. Tässä tapauksessa varsinainen komentoskripti voisi olla
#!/bin/bash -l
#SBATCH --job-name=array_job
#SBATCH --output=array_job_out_%A_%a.txt
#SBATCH --error=array_job_err_%A_%a.txt
#SBATCH --account=<project>
#SBATCH --partition=small
#SBATCH --time=02:00:00
#SBATCH --ntasks=1
#SBATCH --mem-per-cpu=4000
#SBATCH --array=1-50
# aseta syötetiedosto, jota käsitellään
name=$(sed -n ${SLURM_ARRAY_TASK_ID}p namelist)
# suorita analyysi
my_prog ${name} ${name}.out
Tämä esimerkki on muuten samanlainen kuin ensimmäinen mutta se lukee analysoitavan tiedoston nimen
listatusta tiedostosta namelist
. Tämä arvo tallennetaan muuttujaan ${name}
, jota käytetään
tehtävän suorituskomennossa. Koska luettavan rivin numero määritetään $SLURM_ARRAY_TASK_ID
:n
mukaan, kussakin namelist
-tiedostossa lueteltu aineistotiedosto prosessoidaan erillisenä
alitehtävänä. Huomaa, että nyt käytämme myös ${name}
:a tulosteemäärittelyssä, tulostetiedoston
nimi on muodossa data_aa.inp.out
, data_ab.inp.out
, data_ac.inp.out
ja niin edelleen.
Array jobs -tehtävien käyttö työnkuluissa sbatch_commandlistin avulla
sbatch-hq
Tehokkaampi vaihtoehto sbatch_commandlistille
on CSC-apuohjelma sbatch-hq
,
joka on käytännössä HyperQueue:n kääre. sbatch-hq
antaa sinun lähettää joukko samankaltaisia riippumattomia ei-MPI-rinnakkaistehtäviä
komentolistalta, eli tiedostosta, jossa jokainen rivi vastaa yksittäistä suoritettavaa
alitehtävää. Lisätietoja HyperQueue-sivulta.
Puhtissa voit käyttää komentoa sbatch_commandlist
suorittaaksesi komentoluettelon
taulukkotyönä. Tämä komento ottaa syötteenä tekstitiedoston. Komentoluettelo
jaetaan useaan osaan, jotka suoritetaan erätyön riippumattomana alitehtävänä,
joka generoidaan automaattisesti sbatch_commandlist
-komennolla. Näin ollen yksi
taulukkotyön alitehtävä voi käsitellä useita komentoja komentoluettelosta.
Tämän komennon syntaksi on:
Vaihtoehtoja -t
ja -mem
voidaan käyttää alitehtävien ajan ja muistivarausten muuttamiseen
(oletus 12 h, 8 GB). Oletusarvoisesti laskutusprojekti asetetaan sen keskenhakemiston nimen
perusteella, jossa tätä komentoa suoritetaan, mutta tarvittaessa se voidaan määrittää
vaihtoehdolla -project
. Komentoluettelo jaetaan korkeintaan 200 alitehtävään. Jos yksittäiset
tehtävät ovat hyvin lyhyitä, voit käyttää vaihtoehtoa --max_jobs
vähentääksesi jakamista
niin, että kukin taulukkotyön tehtävä kestää vähintään noin puoli tuntia.
Kun taulukkotyö on lähetetty, sbatch_commandlist
alkaa valvoa tehtävän edistymistä.
Jos käytät sbatch_commandlist
-komentoa vuorovaikutteisesti kirjautumissolmussa, et
tavallisesti halua pitää valvontaa käynnissä tuntikausia. Näissä tapauksissa voit vain
sulkea valvontaprosessin painamalla Ctrl-c
. Varsinaista taulukkotyötä ei poisteta,
vaan se pysyy aktiivisena eräjärjestelmässä, ja voit hallita sitä tavanomaisilla Slurm-komennoilla.
Vuorovaikutteisen käytön lisäksi sbatch_commandlist
voidaan hyödyntää erätöissä ja
automaattisissa työnkuluissa, joissa vain tietyt työnkulun vaiheet voivat hyödyntää
taulukkotöitä rinnakkaislaskennan perusteella. Esimerkiksi, oletetaan että meillä on gzip
pakattu tar-arkistotiedosto my_data.tgz
, joka sisältää hakemistollisen tiedostoja.
Luoaksesi uuden pakatun arkiston, johon sisältyy myös md5-tarkistussummatiedosto kustakin
tiedostosta, meidän pitäisi:
- Pura ja avaa
my_data.tgz
- Suorita
md5sum
kullekin tiedostolle, ja lopuksi - Pakkaa ja tiivistä
my_data
-hakemisto uudelleen.
Työnkulun toinen vaihe voisi olla suoritettavissa for-silmukan avulla, mutta voisimme myös
käyttää silmukkaa vain md5sum
-komentojen luettelon luomiseksi, joka voidaan käsitellä
sbatch_commandlist
-komennolla.
#!/bin/bash -l
#SBATCH --job-name=workfow
#SBATCH --output=workflow_out_%j.txt
#SBATCH --error=workflow_err_%j.txt
#SBATCH --account=<project>
#SBATCH --time=12:00:00
#SBATCH --mem=4000
#SBATCH --ntasks=1
#SBATCH --partition=small
# avaa tgz-tiedosto
tar zxf my_data.tgz
cd my_data
# luo md5sum-komentoluettelo
for my_file in *
do
echo "md5sum $my_file > $my_file.md5" >> md5commands.txt
done
# suorita md5-komennot taulukkotyönä
sbatch_commandlist -commands md5commands.txt
# poista kommentiluettelo ja pakkaa hakemisto
rm -f md5commands.txt
cd ..
tar zcf my_data_with_md5.tgz my_data
rm -rf my_data
Huomaa, että yllä oleva erätyöskripti ei ole taulukkotyö, mutta se käynnistää toisen erätyön, joka on taulukkotyö.