Zlecanie zadań do SLURM
- EN: This page is not translated to English.
Slurm - definicja
Info
SLURM (dawniej Simple Linux Utiliy for Resource Management) to system kolejkowy działający na wielu komputerach z listy Top500. W ICM system ten obsługuje wszystkie komputery dużej mocy.
System kolejkowy to element systemu operacyjnego odpowiedzialny za zarządzanie zasobami komputera obliczeniowego i przydzielanie ich użytkownikom zgodnie z obowiązującymi zasadami. Pozwala na optymalne wykorzystanie mocy obliczeniowych i pamięci komputera.
Kolejne zadania użytkowników zostają umieszczone w tzw. kolejce. Gdy zadeklarowane przez użytkowników zapotrzebowanie przekracza dostępne zasoby obliczeniowe tj. czasu procesora, pamięci operacyjnej i dyskowej, zadania kolejno oczekują na dostęp. Praca z systemem kolejkowym przebiega następująco:
- Użytkownik pisze tzw. skrypt, w którym określa zasoby niezbędne do przeprowadzenia obliczeń, a także sposób wykonania zadania użytkownik umieszcza zadanie w kolejce
- System kolejkowy na bieżąco sprawdza dostępność zasobów; gdy jest taka możliwość, rezerwuje zasoby według specyfikacji użytkownika, po czym uruchamia zadanie
- Po zakończeniu obliczeń system kolejkowy zwalnia zarezerwowane zasoby i próbuje je zarezerwować dla następnych zadań czekających w kolejce
Oficjalna dokumentacja:
https://slurm.schedmd.com/documentation.html
Podstawowe komendy systemu kolejkowego
Za pomocą komend systemu SLURM możemy sterować przebiegiem obliczeń naszego zadania. Aby zaplanować zadanie, można użyć polecenia salloc, sbatch lub srun.
-
sbatchzawsze tworzy nowy przydział zasobów po jego wywołaniu, wykonuje skrypt zadania na jednym z przydzielonych węzłów (master node), a następnie zwalnia przydział po zakończeniu skryptu. Dodatkową cechą sbatch jest to, że przeanalizuje skrypt w czasie przesyłania zadania - zamiast podawać argumenty z wiersza poleceń, opcje sbatch mogą zostać zapisane za pomocą linii rozpoczynających się od #SBATCH. Jeżeli poda się argumenty do wiersza poleceń to zastępią one opcje #SBATCH w skrypcie, więc można wywoływać pojedynczy skrypt wsadowy dla różnych przydziałów wielkości zadania, określając opcje -N lub -n w wierszu polecenia podczas przesyłania skryptu zadania zsbatch -
srunmoże, ale nie musi, utworzyć alokację, w zależności od sposobu jej wywołania. Jeśli zostanie wywołany w wierszu poleceń węzła logowania, utworzy nowy przydział i wykona polecenie po srun. Jeśli zostanie wywołany w skrypcie wsadowym, po prostu uruchomi zadanie na bieżącym przydziale. Podobnie, srun może otrzymać argument --jobid, który każe mu uruchomić zadanie jako część danego 'job`a' i jego alokacji. -
salloczawsze tworzy nowy przydział zasobów, gdy jest wywoływany, ale nie musi uruchamiać żadnych zadań w przydzielonych węzłach. Typowym przykładem użycia salloc jest utworzenie przydziału w celu uruchomienia serii kolejnych poleceń srun poprzez interaktywną sesję bash lub skrypt uruchamiany z węzła logowania. Zwalnia przydział po zakończeniu sesji skryptu lub sesji bash.
Źródło: https://cvw.cac.cornell.edu/slurm/basics_allocation
srun/mpirun/mpiexec
-
srunjest poleceniem slurm'a. -
mpirunjest poleceniem przychodzacym razem z wybraną implementacją MPI (openMPI, intel-mpi, ibm-mpi, cray-mpi, etc. Uruchamiającmpirunbez slurma, należy podać parametry zadania (które węzły, ile procesów, itp). -
mpiexec- jest zdefiniowany w standardzie MPI.
Procesy i wątki - MPI a OpenMP
Program może korzystać z wielu rdzeni na dwa sposoby:
- Proces - samodzielnie uruchomiona kopia programu z własną pamięcią. Procesy nie widzą nawzajem swoich danych - jeśli muszą je wymieniać, przesyłają sobie komunikaty.
- Wątek - "podprogram" działający wewnątrz procesu. Wszystkie wątki jednego procesu współdzielą jego pamięć, więc mogą od razu korzystać z tych samych danych.
Z tego wynikają dwa najczęstsze modele programowania równoległego:
- MPI (Message Passing Interface) - program działa jako wiele procesów, które komunikują się, przesyłając komunikaty. Procesy mogą działać na różnych węzłach, więc MPI pozwala wykorzystać wiele węzłów naraz.
- OpenMP - program działa jako jeden proces z wieloma wątkami. Wątki współdzielą pamięć, więc wszystkie muszą działać na jednym węźle.
Oba modele można łączyć (tzw. hybryda MPI + OpenMP): kilka procesów MPI, z których każdy uruchamia kilka wątków.
Jak przełożyć to na parametry zadania, opisano w sekcji --ntasks-per-node a --cpus-per-task.
Skrypty systemu kolejkowego
Opis zadania i zapotrzebowanie na zasoby można specyfikować w specjalnym
skrypcie - pliku tekstowym dla systemu SLURM. Skrypt tworzy użytkownik.
Skrypt składa się z tzw. dyrektyw systemu SLURM, czyli linii zaczynające
się od słowa #SBATCH oraz instrukcji uruchamiających odpowiedni
program.
- Pierwsza linia skryptu musi zawierać ścieżkę do interpretera
(shell), który ma wykonać skrypt na przydzielonym węźle
obliczeniowym np.
#!/bin/bash -l. - Kolejne linie powinny zawierać specyfikację zasobów
Note
Task jest rozumiany jako pojedynczy proces uruchomiony przez aplikację użytkownika. Rezerwacja zasobów oraz wszystkie uruchamiane komendy systemowe i programy nazywane są w skrócie zadaniem.
Skryptowi warto nadać rozszerzenie .slurm (np. moje_zadanie.slurm), dzięki czemu łatwo odróżnić skrypty kolejkowe od innych plików.
Większość opcji ma swoje skróty.
W razie wątpliwości można zajrzeć do instrukcji korzystając z polecenia man sbatch lub man srun.
Kolumna Domyślnie opisuje, co się stanie, gdy parametr nie zostanie podany w sbatch/srun.
Najważniejsze parametry
| Skrót | Pełna nazwa | Znaczenie | Domyślnie |
|---|---|---|---|
| -N | --nodes= | Liczba węzłów obliczeniowych do rezerwacji dla zadania. | tyle, ile potrzeba do zmieszczenia tasków (zwykle 1) |
| --- | --ntasks-per-node= | Liczba procesów (tasków) uruchamianych na każdym węźle. Patrz --ntasks-per-node a --cpus-per-task. | nieustawione - decyduje -n |
| -n | --ntasks= | Łączna liczba procesów (tasków) do uruchomienia. | 1 (ale patrz uwaga o --cpus-per-task poniżej) |
| -c | --cpus-per-task= | Liczba rdzeni przydzielonych każdemu procesowi (np. dla wątków OpenMP). | 1 |
| -t | --time=gg:mm:ss |
Maksymalna długość działania zadania od momentu jego uruchomienia. Po tym czasie zadanie zostanie przerwane przez system kolejkowy. | 30 min (Topola) |
Dodatkowe parametry
| Skrót | Pełna nazwa | Znaczenie | Domyślnie |
|---|---|---|---|
| -A | --account= | Numer grantu obliczeniowego użytkownika, np. G99-99. Używane w celach sprawozdawczych. | domyślny grant użytkownika |
| -p | --partition= | Zadanie uruchamiane będzie w dostępnej dla użytkownika partycji (np. topola, okeanos). | domyślna partycja systemu |
| -q | --qos= | Quality of service, patrz QOS. | domyślny QOS grantu |
| -J | --job-name= | Nazwa zadania. Pod taką nazwą będzie widziane zadanie w systemie, np. przy wyświetlaniu listy zadań. | nazwa skryptu |
| -o | --output= | Plik, do którego trafi wyjście zadania. | slurm-<numer_zadania>.out |
| --- | --mem= | Rezerwacja pamięci per node (megabytes). | 2 GB × liczba zarezerwowanych rdzeni (Topola) |
| --- | --mem-per-cpu= | Rezerwacja pamięci per CPU (megabytes). | 2 GB (Topola) |
| --- | --gres=gpu:4 |
Użycie dodatkowych zasobów, np. GPU (klaster Rysy). | brak |
| -C | --constraint= | Możliwość zażądania sprzętu o konkretnych parametrach, np. typu procesora. | brak |
| -w | --nodelist= | Możliwość zażądania konkretnego węzła obliczeniowego. | dowolny wolny węzeł |
| --- | --mail-user= | Adres email użytkownika, np. --mail-user=user@somewhere.com. |
użytkownik zlecający zadanie |
| --- | --mail-type= | Kiedy wysłać powiadomienie email (BEGIN, END, FAIL, ALL). |
brak powiadomień |
Tip
Domyślne wartości (czas, pamięć) mogą się różnić między partycjami. Można je sprawdzić poleceniem
scontrol show partition <nazwa_partycji> (pola DefaultTime, MaxTime, DefMemPerCPU).
--ntasks-per-node a --cpus-per-task
--ntasks-per-nodeokreśla, ile procesów (kopii programu)srun/mpirunuruchomi na każdym węźle - typowo procesy MPI.--cpus-per-taskokreśla, ile rdzeni dostaje każdy proces - typowo na wątki OpenMP.
Przykład: oba poniższe zadania rezerwują 4 rdzenie na jednym węźle, ale uruchamiają program inaczej.
Różnicę pokazano na przykładzie polecenia hostname, które wyświetla nazwę węzła (hosta), na którym zostało uruchomione - liczba wypisanych linii odpowiada liczbie uruchomionych procesów.
#!/bin/bash -l
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=4
srun hostname
4 procesy po 1 rdzeniu - hostname wykona się 4 razy:
t1-1
t1-1
t1-1
t1-1
#!/bin/bash -l
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=4
srun hostname
1 proces z 4 rdzeniami - hostname wykona się raz, a program wielowątkowy (OpenMP) może użyć 4 wątków:
t1-1
Parametry można łączyć:
| Opcje | Procesy | Rdzenie / proces | Rdzenie razem | Zastosowanie |
|---|---|---|---|---|
-N 1 --ntasks-per-node=4 |
4 | 1 | 4 | MPI |
-N 1 --ntasks-per-node=1 --cpus-per-task=4 |
1 | 4 | 4 | OpenMP / wątki |
-N 1 --ntasks-per-node=4 --cpus-per-task=4 |
4 | 4 | 16 | hybryda MPI + OpenMP |
-N 2 --ntasks-per-node=4 |
8 | 1 | 8 | MPI na 2 węzłach |
Warning
- Podając
--cpus-per-task, zawsze zdefiniuj jawnie liczbę tasków przez--ntasks-per-node. Bez niej zadanie może dostać kilka tasków - np.--nodes=1 --partition=topola --cpus-per-task=4daje 4 taski × 4 = 16 rdzeni zamiast 4, asrunuruchomi program 4 razy. Poprawnie:--nodes=1 --ntasks-per-node=1 --cpus-per-task=4. - Program jednowątkowy uruchomiony z
--cpus-per-task=4wykorzysta tylko 1 z 4 zarezerwowanych rdzeni. - Program OpenMP uruchomiony z
--ntasks-per-node=4wystartuje w 4 niezależnych kopiach. - Polecenie wywołane w skrypcie bez
srun/mpirunwykona się tylko raz, niezależnie od--ntasks.
Przykładowe skrypty
Partycja Topola
Poniższy skrypt uruchamia obliczenia w programie Quantum Espresso:
#!/bin/bash -l
#SBATCH --job-name="name_of_my_job"
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=12
#SBATCH --mem=5000
#SBATCH --time=20:00:00
#SBATCH --account=GYY-XX
#SBATCH --partition=topola
#SBATCH --output="my_results.out"
module load apps/espresso/6.1.0
mpirun -n 12 pw.x < S.in
- w systemie kolejkowym zadnie będzie funkcjonowało pod nazwą "qe-1"
- na jednym węźle obliczeniowym z wykorzystaniem 12 rdzeni obliczeniowych
- dla zadania przydzielone zostanie 5GB pamięci operacyjnej
- zlecający deklaruje, że zadanie zakończy się w czasie krótszym niż 20 godzin (po tym czasie zadanie zostanie przerwane przez system kolejkowy)
- zadanie zostaje przypisane do grantu o numerze GYY-XX
- Plik sterujący S.dat powinien być umieszczony w katalogu z którego uruchamiane jest zadanie
- Polecenie "module load apps/espresso/6.1.0" ustawia środowisko (dostęp do programu, zmienne środowiskowe) niezbędne do uruchomienia programu.
- Polecenie "mpirun -n 12 pw.x < S.in" uruchamia właściwy program obliczeniowy w środowisku równoległym MPI.
Partycja Okeanos
#!/bin/tcsh
#SBATCH --job-name="name_of_my_job"
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=12
#SBATCH --account=GYY-XX
#SBATCH --partition=okeanos
#SBATCH --output="my_results.out"
module swap PrgEnv-cray PrgEnv-intel
module load espresso/6.1.0
srun -n 12 pw.x < S.in
Partycja Rysy
W celu uruchomienia aplikacji na GPU niezbędne jest podanie opcji --gres=gpu:liczba_gpu.
#!/bin/bash -l
#SBATCH --job-name="my_job_name"
#SBATCH --nodes=1
#SBATCH --gres=gpu:1
#SBATCH --cpus-per-task=1
#SBATCH --ntasks-per-node=1
#SBATCH --account=GYY-XX
#SBATCH --time=01:00:00
#SBATCH --qos=normal
srun hello_world_cuda
Przykładowy program hello_world_cuda znajduje się w sekcji Podstawy GPU.
Wstawianie zadania do kolejki
Polecenie sbatch służy do wstawiania zadań do systemu kolejkowego.
Wszystkie flagi, które można wyspecyfikować w tym poleceniu,
alternatywnie podaje się w pierwszym bloku komentarza skryptu
kolejkowego w liniach zaczynających się od #SBATCH .
Niektóre opcje tego polecenia są specyficzne dla danego komputera.
Info
Zlecanie zadań na system topola możliwe jest bezpośrednio z węzła dostępowego hpc.icm.edu.pl.
W przypadku pozostałych systemów możliwy/wymagany jest dodatkowy krok logowania wykonany z komputera
hpc.icm.edu.pl, np. ssh rysy, ssh okeanos.
Więcej o komputerach dostępnych w ICM tutaj.
Tryb wsadowy
Podczas uruchamiania obliczeń w trybie wsadowym (batch) użytkownik nie może komunikować się z wykonywanym programem. Dlatego niezbędne jest wcześniejsze przygotowanie informacji potrzebnych w toku wykonywania wszystkich zaplanowanych czynności, tak aby program mógł je wykorzystać w stosownym momencie. Zakres tych informacji, ich format oraz sposób przygotowania zależy od konkretnego programu. Podczas przygotowywania zadania wsadowego należy poprawnie przewidzieć ciąg pytań generowanych przez program w miarę jego wykonywania i przygotować odpowiedzi na wszystkie takie komunikaty. Rozbieżność między pytaniami generowanymi przez program, a odpowiedziami znajdującymi się w pliku wejściowym może spowodować niepoprawny przebieg zadania wsadowego.
Wstawienie do kolejki zadania opisanego skryptem MojeZadanie.batch
wykonujemy komendą:
sbatch MojeZadanie.batch
Umieści ona w systemie kolejkowym zadanie wsadowe (bez możliwości
interakcji z wykonywanym programem). Dodatkowe opcje wykonania zadania
możemy wprowadzać w skrypcie lub podać jako parametry polecenia
sbatch.
Tryb interaktywny
Aby uzyskać dostęp do zasobów w trybie interaktywnym z dostępem do powłoki (shell), należy wykonać komendę:
srun -p <partition_name> -A <grant_name> -N 1 -n 12 --time=1:00:00 --pty /bin/bash -l # cluster: topola, okeanos
srun -A <grant_name> -N 1 -n 12 --time=1:00:00 --gres=gpu:2 --pty /bin/bash -l # cluster: rysy
Alternatywnie, można najpierw zaalokować zasoby, a następnie uruchomić sesję interaktywną
salloc -p <partition_name> -A <grant_name> -N 1 -n 12 --time=1:00:00 # cluster: topola, okeanos
salloc -A <grant_name> -N 1 -n 12 --time=1:00:00 --gres=gpu:2 # cluster: rysy
# następnie
srun /bin/bash -l
Ma to tą zaletę, że jeżeli będziemy musieli ponownie uruchomić zadanie (np. bo nasz program się zawiesił) to nie będziemy musieli czekać aż SLURM przydziali nam zasoby.
Quality of Service (QOS)
Parametr ten określa na jak długo możliwa jest alokacja zasobów oraz priorytet w uruchomieniu zadania.
Aby przypisać zadanie do konkretnego qos'a należy ustalić zmienną:
--qos=NAZWA_QOSa
Szczegóły qos'ów dostępnych w ICM znajdują się tu.