Računajmo na več vozliščih
Na prvih računalniških gručah so imela vozlišča eno ali največ nekaj procesorskih jeder, za hitrejše računanje mnogih problemov je bilo potrebno usklajeno delovanje več vozlišč. Vozlišča si ne delijo skupnega pomnilniškega prostora, vsako vozlišče vidi samo svoj del porazdeljenega pomnilnika. Računanje na več vozliščih poteka tako, da se na vsakem vozlišču zažene vsaj en proces, ki sodeluje v izvajanju posla. Procesi si preko omrežja izmenjujejo sporočila s potrebnimi podatki. Da so stroški komunikacije čim manjši, so računska vozlišča med seboj povezana z nizkolatenčnimi širokopasovnimi omrežji, priljubljeno je omrežje Infiniband. Na superračunalniških sistemih se za tovrstno izvajanje poslov najpogosteje uporablja standard MPI (angl. Message Passing Interface). Standard MPI vključuje množico funkcij za porazdeljeno računanje: podpira komunikacijo med dvema procesoma, izmenjevanje sporočil med skupinami procesov, skupinsko računanje in še marsikaj.
Obstaja več knjižnic, ki podpirajo standard, zelo priljubljena je knjižnica OpenMPI, saj podpira najnovejšo komunikacijsko opremo in protokole, poleg tega pa se lepo povezuje z razvrščevalnikom poslov Slurm. Knjižnice običajno podpirajo programska jezika C/C++ in Fortran, za večino programskih jezikov pa so pripravljene ovojnice (angl. wrapper). V nadaljevanju bomo uporabili paket mpi4py
z ovojnnico za programski jezik python.
Porazdeljeno računanje Mandelbrotove množica z MPI
Programu za izris Mandelbrotove množice dodajmo še podporo za porazdeljeno računanje po standardu MPI.
Koda programa mandelbrot-mpi.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
|
V osnovnem programu mandelbrot-seq.py
smo tokrat spremenili funkcijo mandelbrot
(zdaj mandelbrot_mpi
). V funkciji mandelbrot_mpi
najprej razdelimo delo med procese, tako da vsak proces poračuna svoj del slike. Na koncu osnovni proces (rang 0) dele slik s funkcijo gather
združi v eno. V funkciji main
smo dopisali, da samo osnovni proces shrani sliko in izpiše podatke o poteku računanja.
Vsebnik s podporo za OpenMPI
Podobno, kot pri grafičnih procesnih enotah, mora ogrodje Apptainer tudi pri delu s knjižnicami MPI poskrbeti, da vsebniku dovoli dostop do potrebne strojne opreme. Pri izbiranju knjižnic moramo paziti, da je knjižnica v vsebniku združljiva s knjižnico na gostitelju.
Na superračunalniški gruči Arnes je nameščena knjižnica OpenMPI
verzija 4.1.1
, zato isto verzijo knjižnice namestimo tudi v vsebnik. Knjižnico OpenMPI najdemo med namestitvenimi paketi, vendar tam ni prevedena z ustreznimi stikali in na gruči deluje bolj za silo. Za pravilno namestitev moramo knjižnico prenesti v vsebnik in jo v njem prevesti. Za nameščanje sledimo postopku, pri čemer vrstico s klicem programa ./configure
dopolnimo s stikali --with-slurm
in --with-pmix
. S prvim stikalom zahtevamo podporo za Slurm. Z drugim stikalom zahtevamo, da MPI za komunikacijo z ostalimi sistemi in strojno opremo uporablja programsko plast PMIx (angl. Process Management Interface eXascale).
Poleg jezika python
, namestitvenega paketa pip
in ostalih standardnih paketov, namestimo še paket mpi4py
z ovojnico za MPI.
Poskrbimo, da v vsebnik prenesemo program mandelbrot-mpi.py
in konfiguracijsko datoteko default.conf
.
Vsebnik mb-mpi.def
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
|
Tako zgrajen vsebnik lahko zaženemo na dva načina:
-
Če želimo program izvajati na enem samem vozlišču, lahko v vsebniku zaženemo razvrščevalnik
mpirun
, ki mu s stikalom--n
povemo, koliko procesov naj zažene. Privzeto se bo vsak proces izvajal na svojem procesorskem jedru.Na računalniku, kjer smo vsebnik zgradili, zaženemo štiri procese:
$ apptainer exec mb-mpi.sif mpirun --n 4 mandelbrot-mpi.py Process 3 of 4 runs on node hpc-login1.arnes.si Process 0 of 4 runs on node hpc-login1.arnes.si Process 1 of 4 runs on node hpc-login1.arnes.si Process 2 of 4 runs on node hpc-login1.arnes.si MPI: size: (3840, 2160) iterations: 256 time: 3.394 s
apptainer exec mb-mpi.sif mpirun --n 4 mandelbrot-mpi.py
Na računskem vozlišču gre podobno, vendar moramo ustrezno nastaviti razvrščevalnik Slurm. V razvrščevalniku Slurm za eno nalogo rezerviramo štiri procesorska jedra, nato pa v vsebniku zaženemo razvrščevalnik
mpirun
, ki poskrbi za ostalo. Razvrščevalniku s stikalom--n
določimo, koliko procesov naj zažene, pri tem pazimo, da navedemo enako številko kot pri stikalu--cpus-per-task
. Razvrščevalnikmpirun
bo privzeto zagnal toliko procesov, kot je navedeno s stikalom--ntasks
. Da sprostimo to omejitev in izkoristimo vsa rezervirana procesorska jedra, dodamo stikalo--oversubscribe
.$ srun --ntasks=1 --cpus-per-task=4 apptainer exec mb-mpi.sif \ mpirun --n 4 --oversubscribe mandelbrot-mpi.py Process 3 of 4 runs on node wn120.arnes.si Process 2 of 4 runs on node wn120.arnes.si Process 1 of 4 runs on node wn120.arnes.si Process 0 of 4 runs on node wn120.arnes.si MPI: size: (3840, 2160) iterations: 256 time: 4.294 s
srun --ntasks=1 --cpus-per-task=4 apptainer exec mb-mpi.sif mpirun --n 4 --oversubscribe mandelbrot-mpi.py
-
Pri zaganjanju na več vozliščih, najprej zaženemo
mpirun
, ta pa potem zažene vsebnik. Pripravimo skripto bash===
Skripta
mandelbrot-mpi.sh
Izvorna datoteka: mandelbrot-mpi.sh1 2 3 4 5 6 7 8 9 10 11
#!/bin/bash #SBATCH --job-name=mandelbrot-mpi #SBATCH --ntasks=4 #SBATCH --nodes=2 #SBATCH --output=mandelbrot-mpi.log #SBATCH --reservation=fri module load OpenMPI/4.1.1-GCC-10.3.0 mpirun --n $SLURM_NTASKS apptainer exec mb-mpi.sif mandelbrot-mpi.py
V skripti zahtevamo, da se štiri naloge izvedejo na dveh vozliščih. Med izvajanjem skripta najprej na računskih vozliščih namesti modul
OpenMPI
. Paziti moramo, da sta verziji knjižnic v modulu in vsebniku enaki. Zampi
, ki uporablja isto različino knjižnic MPI. Nato zažene še ukazmpirun
, ki na dodeljenih procesorskih jedrih preko programaapptainer
zažene vsebnikmb-mpi.sif
in v njem programmandelbrot-mpi.py
.Skripto zaženemo, počakamo, da se posel konča, in pogledamo izpis v datoteki
mandelbrot-mpi.log
.$ sbatch mandelbrot-mpi.sh Submitted batch job 1198176 $ cat mandelbrot-mpi.log Process 1 of 4 runs on node wn113.arnes.si Process 3 of 4 runs on node wn120.arnes.si Process 2 of 4 runs on node wn120.arnes.si Process 0 of 4 runs on node wn113.arnes.si MPI: size: (3840, 2160) iterations: 256 time: 3.668 s
sbatch mandelbrot-mpi.sh squeue --me cat mandelbrot-mpi.log
Preveri svoje znanje
Vaja
Za pripravo recepta in gradnjo vsebnika sledimo navodilom: Vaja 07.