Przejdź do treści

Zlecanie zadań do SLURM

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:

  1. 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
  2. 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
  3. 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.

  • sbatch zawsze 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

  • srun moż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.

  • salloc zawsze 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

  • srun jest poleceniem slurm'a.

  • mpirun jest poleceniem przychodzacym razem z wybraną implementacją MPI (openMPI, intel-mpi, ibm-mpi, cray-mpi, etc. Uruchamiając mpirun bez 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-node określa, ile procesów (kopii programu) srun/mpirun uruchomi na każdym węźle - typowo procesy MPI.
  • --cpus-per-task okreś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=4 daje 4 taski × 4 = 16 rdzeni zamiast 4, a srun uruchomi program 4 razy. Poprawnie: --nodes=1 --ntasks-per-node=1 --cpus-per-task=4.
  • Program jednowątkowy uruchomiony z --cpus-per-task=4 wykorzysta tylko 1 z 4 zarezerwowanych rdzeni.
  • Program OpenMP uruchomiony z --ntasks-per-node=4 wystartuje w 4 niezależnych kopiach.
  • Polecenie wywołane w skrypcie bez srun/mpirun wykona 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.

Ta strona używa plików cookies.
Polityka Prywatności    AKCEPTUJĘ