Podstawy SLURM

Z Komputery Dużej Mocy w ACK CYFRONET AGH
Wersja z dnia 09:50, 21 sty 2019 autorstwa Maciej (dyskusja | edycje)
(różn.) ← poprzednia wersja | przejdź do aktualnej wersji (różn.) | następna wersja → (różn.)
Skocz do:nawigacja, szukaj


Co to jest system kolejkowy SLURM

System kolejkowy SLURM jest wygodnym narzędziem uruchamiania zadań na zasobach obliczeniowych. Umożliwia on sprawne dobieranie zasobów obliczeniowych do potrzeb użytkownika zdefiniowanych poprzez komendy systemu kolejkowego. W zależności od potrzeb, system kolejkowy umożliwia uruchamianie zadań zrównoleglonych, rozproszonych, tablicowych czy zadań wykorzystujących dodatkowe zasoby sprzętowe (i.e. karty graficzne lub koprocesory przyspieszające obliczenia) lub dedykowane oprogramowanie, w tym zadania umożliwiające interaktywną pracę na zasobach obliczeniowych klastrów i superkomputerów. Dodatkowo system kolejkowy umożliwia tworzenie zależności między zleconymi zadaniami, może informować użytkownika o dacie i czasie rozpoczęcia, czy też zakończenia wykonywania danego zadania na wskazany adres e-mail.

Rodzaje zadań zlecanych w systemie kolejkowym:

  • Zadanie wsadowe (ang. batch job) - zostanie wykonane na zasobach obliczeniowych wedle poleceń umieszczonych w tzw. skrypcie obliczeniowym. Skrypt obliczeniowy może być napisany w dowolnym języku skryptowym dostępnym na klastrze obliczeniowym (np. Bash, tcsh, Python).
    • Zadanie tablicowe - grupa zadań wsadowych, które wykorzystują ten sam skrypt obliczeniowy jednakże są uruchamiane z jako tablica zadań, co umożliwia np. efektywne przeprowadzenie obliczeń dla różnych warunków początkowych i tego samego schematu obliczeń.
  • Zadanie interaktywne - umożliwia interaktywną pracę na zasobach obliczeniowych. Po uruchomieniu zadania użytkownik otrzymuje dostęp do konsoli na węźle obliczeniowym.

System kolejkowy SLURM, pozwala (w odróżnieniu od np. PBS) na wyspecyfikowanie wewnętrznej organizacji zasobów wykorzystywanych przez obliczenia. SLURM operuje na pojęciach:

  • Zadanie (job), które działa w ramach przydzielonej alokacji zasobów
  • Proces (task), który odpowiada jednej instancji procesu aplikacji. Procesy zawierają się w zadaniu, zadanie domyślnie posiada 1 proces. Proces jest ograniczony do wielkości jednego węzła. Wykonywanie obliczeń na wielu węzłach wymaga użycia wielu procesów.
  • Rdzeń (core), który odpowiada alokacji jednego rdzenia procesora. Każdy proces ma przypisaną liczbę rdzeni, domyślnie jest to 1.

Więcej informacji można znaleźć w dokumentacji SLURMa: https://slurm.schedmd.com/quickstart.html Wewnętrzna organizacja zasobów przekłada się np. na działanie aplikacji MPI, dlatego warto dokładnie specyfikować zasoby dla zadania.

Uruchamianie zadań wsadowych

Do uruchamiania zadań wsadowych (ang. batch job) służy komenda sbatch. W tym przypadku wszystkie komendy dla systemu kolejkowego podaje jako argumenty polecenia sbatch lub umieszcza się w pliku zawierającym skrypt obliczeniowy. W takim pliku linijki zawierające instrukcje sterujące dla systemu kolejkowego muszą zaczynać się ciągiem znaków #SBATCH. Należy je umieścić na początku pliku, przed innymi poleceniami, które mają być wykonane w ramach zadania na węźle obliczeniowym. Dzięki temu system kolejkowy jest w stanie odczytać opcje jemu właściwe właśnie z tych linijek i uruchomić pozostałe instrukcje, dotyczące już samego zadania obliczeniowego, z dalszej części pliku. Przykładowy skrypt obliczeniowy.


Uruchamianie zadań interaktywnych

Możliwe jest również uruchomienie zadań interaktywnych, czyli dających bezpośredni dostęp do konsoli na węźle obliczeniowym. Do tego celu służy polecenie srun. Dla zadania interaktywnego opcje systemu kolejkowego podaje się jako argumenty polecenia srun. Obowiązkowym parametrem dla polecenia srun jest opcja --pty ustalająca konsole, która zostanie uruchomiona jako powłoka na maszynie zdalnej (np. /bin/bash lub /bin/tcsh). W celu wybrania konsoli Bash, która jest domyślną konsolą na klastrach w ACK Cyfronet AGH, należy użyć opcji --pty /bin/bash.

W przypadku zadań wsadowych polecenie srun może być umieszczone w skrypcie obliczneniowym, odpowiada ono wtedy za uruchomienie komendy podanej jako argument polecenia srun w ramach zaalokowanych zasobów, jednak w przypadku, gdy zasoby nie zostały wcześniej zaalokowane, komenda ta uprzednio dokonuje ich rezerwacji tuż przed uruchomieniem obliczeń. Przykładowe zadanie interaktywne.


Opcje i parametry komend sbatch i srun

Najważniejsze opcje i parametry komend sbatch oraz srun zawiera poniższa tabela.

Opcja Parametry Opis Wartość domyślna
-N (--nodes=) <liczba węzłów> Parametr służy do specyfikacji liczby węzłów 1
-n (--ntasks=) <liczba procesów> Liczba żądanych procesów (rdzeni) dla całego zadania. Może być użyte łącznie lub wymiennie z --ntasks-per-node 1
--ntasks-per-node= <liczba procesów> Liczba żądanych procesów na każdym węźle. Może być użyte łącznie lub wymiennie z -n (--ntasks=) 1
--cpus-per-task= <liczba rdzeni> Liczba żądanych rdzeni do dyspozycji każdego procesu 1
--mem-per-cpu= <ilość pamięci> Ilość pamięci operacyjnej dla każdego zaalokowanego rdzenia obliczeniowego. Wartość należy podawać w bajtach, megabajtach lub gigabajtach stosując odpowiednie przedrostki, np. 1GB. 4000Mb
--mem= <ilość pamięci> Ilość pamięci operacyjnej dla całego zadania na węzeł obliczeniowy. Wartość należy podawać w bajtach, megabajtach lub gigabajtach stosując odpowiednie przedrostki, np. 1GB.
-t (--time=) <czas obliczeń> Maksymalny czas obliczeń. Czas należy podawać w formacie DD-GG:MM:SS gdzie DD, GG, MM, SS oznaczają odpowiednio żądaną liczbę dni, godzin, minut i sekund na zadanie. zależne od kolejki
-J (--job-name=) <nazwa zadania> Nazwa zadania w systemie kolejkowym nazwa pliku batchowego lub bash jeśli zadanie interaktywne
--mail-type NONE, BEGIN, END, FAIL, REQUEUE, ALL, TIME_LIMIT, TIME_LIMIT_90, TIME_LIMIT_80, TIME_LIMIT_50 System kolejkowy wyśle e-mail do użytkownika jeśli zadanie osiągnie jeden z zadanych stanów (funkcjonalność dostępna tylko na klastrze Prometheus). NONE
--mail-user <adres@e-mail.użytkownika> Adres e-mail użytkownika na który ma zostać wysłana wiadomość o stanie zadania (funkcjonalność dostępna tylko na klastrze Prometheus). informacja brana z Portalu PLGrid
-p (--partition=) <nazwa partycji> Specyfikuje nazwę partycji (odpowiednika kolejki w PBS) do której ma trafić zadanie plgrid
-A <nazwa grantu> Specyfikuje nazwę grantu z którego zasoby będą brane do obliczeń grant domyślny wybrany w Portalu PLGrid
-o (--output=) <nazwa pliku> Specyfikuje nazwę pliku do którego zostanie zapisane standardowe wyjście slurm-<JOBID>.out, gdzie JOBID to numer zadania, np. slurm-12345678.out
-e (--error=) <nazwa pliku> Specyfikuje nazwę pliku do którego zostanie zapisane standardowe wyjście błędu slurm-<JOBID>.out, gdzie JOBID to numer zadania, np. slurm-12345678.out

Usuwanie zadań

Do usuwania zadań służy komenda scancel. W celu sunięcia zadania z kolejki potrzebny jest również jego identyfikator numeryczny (JOBID), który można wyświetlić komendą squeue. Cała sekwencja może wyglądać następująco:

scancel 12345678910

Jeśli zadania nie da się usunąć należy skontaktować się z administratorem komputera.

Monitorowanie kolejek, partycji, węzłów, zadań i zasobów

  • Narzędzia systemu SLURM
    • squeue - lista aktualnie zakolejkowanych/uruchomionych zadań
    • scontrol show job [<ID_zadania>] - szczegóły zadania
    • sstat -a -j <ID_zadania>/<ID_zadania.batch> - zużycie zasobów w ramach kroków (step) działającego zadania
    • scancel <ID_zadania> - usunięcie zadania (działającego lub zakolejkowanego)
    • sacct - zużycie zasobów zakończonego już zadania/kroku
    • scontrol show partition [<nazwa_partycji>] - właściwości partycji
    • sinfo - lista węzłów
    • scontrol show node [<nazwa_węzła>] - właściwości węzła

Więcej informacji znajduje się w pomocy danego polecenia możliwej do wywołania za pomocą opcji --help.

Przydatne zmienne systemu kolejkowego

  • $SLURM_NTASKS Zmienna wskazuje na ilość procesów przydzielonych dla zadania. Najczęściej wykorzystywany do określania liczby rdzeni przydzielonej zadaniu np.:
mpiexec -np $SLURM_NTASKS moja_aplikacja

Podawanie parametrów -np i -n do komendy mpiexec jest najczęściej opcjonalne. W większości przypadków biblioteka MPI jest w stanie automatycznie dobrać odpowiednią liczbę procesów, dopasowaną do alokacji zadania.

  • $SLURM_SUBMIT_DIR Zmienna wskazuje na katalog, z którego uruchomiono obliczenia. Najczęściej wykorzystywana do wskazania plików dla zadania np.:
cd $SLURM_SUBMIT_DIR
  • $SLURM_JOB_ID Zmienna wskazuje na numer zadania w systemie kolejkowym.

Tabela pomagająca przenieść skrypty pomiędzy PBS a SLURM

Tabelę, która porównuje systemy kolejkowe SLURM oraz PBS/Torque pod względem opcji, komend oraz zmiennych systemowych można znaleźć tutaj

Przykłady

Zadanie interaktywne

Uruchomienie zadanie interaktywnego w kolejce "plgrid-testing" z możliwością pracy w trybie tekstowym wymagające jednego rdzenia na jednym węźle obliczeniowym przez 20 minut.

srun -p plgrid-testing -t 20:00 --pty /bin/bash

Uruchomienie zadanie interaktywnego w kolejce "plgrid" z możliwością pracy w trybie interaktywnym wymagające 12 rdzeni na jednym węźle obliczeniowym przez 3h.

srun -N 1 --cpus-per-task=12 -p plgrid -t 3:0:0 --pty /bin/bash

Zadanie jednordzeniowe

Uruchomienie z linii poleceń zadania w kolejce "plgrid" wymagające jednego rdzenia na jednym węźle obliczeniowym przez 2h:

sbatch -p plgrid -t 2:0:0 nazwa_skryptu_do_uruchomienia

W powyższym przykładzie nie podajemy parametrów -n itp. ze względu na ich wartości domyslne.

W przypadku skryptu należy użyć poniższych wpisów:

#SBATCH -p plgrid
#SBATCH -t 2:0:0

Zadanie wykorzystujące cały węzeł obliczeniowy

Należy ustalić, ile rdzeni znajduje się w jednym węźle obliczeniowym. Liczba rdzeni jest różna w zależności od typu węzła, informacje o dostępnych typach można znaleźć na tym wiki lub sprawdzić w systemie kolejkowym konkretny węzeł za pomocą komendy scontrol show node nazwa_wezla.

Uwaga! W przypadku SLURMa istotne jest, czy aplikacja jest wielowątkowa (np. OpenMP) czy wieloprocesowa (np. MPI). W przypadku korzystania z aplikacji wielowątkowej należy specyfikować jeden węzeł (-N 1), jeden proces (tak jest domyślnie) i wiele procesorów (--cpus-per-task) przypisanych do tego procesu. W przypadku aplikacji wieloprocesowych należy specyfikować cały węzeł (-N 1), wiele procesów (-n 12) i jeden rdzeń per proces (tak jest domyślnie).

Węzeł 12-rdzeniowy Zeusa

Uruchomienie z linii poleceń zadania w kolejce "plgrid" alokujące cały 12-rdzeniowy węzeł obliczeniowy z domyślnym maksymalnym czasem trwania kolejki:

sabtch -N 1 --cpus-per-task=12 -p plgrid nazwa_skryptu_do_uruchomienia

W przypadku skryptu należy użyć poniższych wpisów:

#SBATCH -p plgrid
#SBATCH -N 1
#SBATCH --cpus-per-task=12


Węzeł 64-rdzeniowy Zeusa

Uruchomienie z linii poleceń zadania w kolejce "plgrid" alokujące cały 64-rdzeniowy węzeł obliczeniowy z domyślnym maksymalnym czasem trwania kolejki:

sabtch -N 1 --cpus-per-task=64 -p plgrid nazwa_skryptu_do_uruchomienia

W przypadku skryptu należy użyć poniższych wpisów:

#SBATCH -p plgrid
#SBATCH -N 1
#SBATCH --cpus-per-task=64


Węzeł 24-rdzeniowy Prometheusa

Uruchomienie z linii poleceń zadania w kolejce "plgrid" alokujące cały 24-rdzeniowy węzeł obliczeniowy z domyślnym czasem trwania kolejki:

sabtch -N 1 --cpus-per-task=24 -p plgrid nazwa_skryptu_do_uruchomienia

W przypadku skryptu należy użyć poniższych wpisów:

#SBATCH -p plgrid
#SBATCH -N 1
#SBATCH --cpus-per-task=24


Zadanie korzystające z wielu węzłów obliczeniowych

Uruchomienie z linii poleceń zadania w kolejce "plgrid" alokujące X węzłów, na każdym alokujemy Y procesów, każdy proces zajmuje jeden rdzeń:

sbatch -N X --ntasks-per-node=Y -p plgrid nazwa_skryptu_do_uruchomienia

W przypadku skryptu należy użyć poniższych wpisów:

#SBATCH -p plgrid
#SBATCH -N X
#SBATCH --ntasks-per-node=Y

W powyższym przykładzie alokujemy X węzłów, po Y procesów, sumaryczna ilość procesów (np. dla MPI) będzie wynosić X*Y.

Zadania tablicowe

Zadania tablicowe to mechanizm pozwalający na zlecanie dużej ilości zadań wsadowych, które są do siebie podobne. Zadania tablicowe posiadają swój indeks, dostępny jako zmienną środowiskowa $SLURM_ARRAY_TASK_ID wewnątrz zadania, dzięki któremu można odpowiednio parametryzować uruchamianą aplikację. Sposób zlecania zadania jest analogiczny jak w przypadku zwykłych zadań wsadowych, a przykładowy skrypt zawierający parametr --array -a, definiujący zakres indeksów, wygląda następująco:

UWAGA! To jest przykładowy skrypt, którego NIE NALEŻY uruchamiać. Przed jego uruchomieniem należy przeglądnąć podane opcje i dostosować je do własnych potrzeb, zmieniając m.i. nazwę grantu, nazwę partycji, czas trwania zadania, itp.

#!/bin/bash -l
## Nazwa zlecenia
#SBATCH -J testjob
## Liczba alokowanych węzłów
#SBATCH -N 1
## Liczba zadań per węzeł (domyślnie jest to liczba alokowanych rdzeni na węźle)
#SBATCH --ntasks-per-node=1
## Ilość pamięci przypadającej na jeden rdzeń obliczeniowy (domyślnie 4GB na rdzeń)
#SBATCH --mem-per-cpu=1GB
## Maksymalny czas trwania zlecenia (format DD-HH:MM:SS)
#SBATCH --time=01:00:00 
## Nazwa grantu do rozliczenia zużycia zasobów
#SBATCH -A <grant_id>
## Specyfikacja partycji
#SBATCH -p plgrid-testing
## Plik ze standardowym wyjściem
#SBATCH --output="output-%A_%a.out"
## Plik ze standardowym wyjściem błędów
#SBATCH --error="error-%A_%a.err"
## Parametr wyznaczający indeksy zadania tablicowego
#SBATCH --array=0-100

## przejscie do katalogu z ktorego wywolany zostal sbatch
cd $SLURM_SUBMIT_DIR

myCalculations $SLURM_ARRAY_TASK_ID

Domyślnie (bez specyfikowania opcji -e oraz -o) SLURM zachowuje pliku wyjściowe zarówno stdout jak i stderr dla zadań tablicowych w plikach o formacie: slurm-${SLURM_ARRAY_JOB_ID}_${SLURM_ARRAY_TASK_ID}.out. W powyższym przykładzie rozdzielono pliki z stdout oraz stderr, tak że dla każdego zadania będą one przyjmowały postać  output-${SLURM_ARRAY_JOB_ID}_${SLURM_ARRAY_TASK_ID}.out oraz error-${SLURM_ARRAY_JOB_ID}_${SLURM_ARRAY_TASK_ID}.out.

Zadania wykorzystujące MPI

Opis dotyczy uruchamiania zadań MPI na klastrze wyposażonych w system kolejkowy SLURM integrujący się z bibliotekami MPI. W przypadku KDM w ACK Cyfronet AGH dostępne są różne wersje bibliotek MPI (najczęściej OpenMPI i IntelMPI) dla większości dostępnych kompilatorów. Podczas uruchamiania aplikacji proszę nie podawać explicite parametru -n lub -np system dobierze odpowiednie wartości na podstawie parametrów alokacji (umieszczonych w skrypcie startowym) i zostaną one zastosowane. W uzasadnionych przypadkach, gdzie aplikacja wymaga specyficznej konfiguracji (np. lokalne wątkowanie), można podać wspomniane parametry.

UWAGA! To jest przykładowy skrypt, którego NIE NALEŻY uruchamiać. Przed jego uruchomieniem należy przeglądnąć podane opcje i dostosować je do własnych potrzeb, zmieniając m.i. nazwę grantu, nazwę partycji, czas trwania zadania, itp.

#!/bin/bash -l
## Nazwa zlecenia
#SBATCH -J MPITest
## Liczba alokowanych węzłów
#SBATCH -N 2
## Liczba zadań per węzeł (domyślnie jest to liczba alokowanych rdzeni na węźle)
#SBATCH --ntasks-per-node=12
## Ilość pamięci przypadającej na jeden rdzeń obliczeniowy (domyślnie 4GB na rdzeń)
#SBATCH --mem-per-cpu=4GB
## Maksymalny czas trwania zlecenia (format HH:MM:SS)
#SBATCH --time=01:00:00 
## Nazwa grantu do rozliczenia zużycia zasobów
#SBATCH -A <grant_id>
## Specyfikacja partycji
#SBATCH -p plgrid-testing
## Plik ze standardowym wyjściem
#SBATCH --output="output.out"
## Plik ze standardowym wyjściem błędów
#SBATCH --error="error.err"

srun /bin/hostname

## Zaladowanie modulu IntelMPI w wersji domyslnej
module add plgrid/tools/impi

## przejscie do katalogu z ktorego wywolany zostal sbatch
cd $SLURM_SUBMIT_DIR

mpiexec ./calcDiff 100 50

Dobrą praktyką jest kompilowanie i uruchamianie aplikacji przy pomocy środowiska budowanego tym samym zestawem modułów. Zalecamy korzystanie z wrappera mpiexec. Wielkość alokacji, w tym przypadku 2 węzły po 12 rdzenie, przekłada się bezpośrednio na 24 procesy dostępne dla aplikacji korzystającej z MPI. Dopuszczalne jest uruchomienie serii aplikacji MPI w jednym skrypcie, ale najczęściej, ze względu na długi czas wykonania, nie jest to optymalny sposób prowadzenia obliczeń. Niedopuszczalne jest jednoczesne uruchomienie wielu aplikacji MPI w ramach jednej alokacji, taka praktyka prowadzi do kłopotów związanych z alokacją zasobów na wyłączność dla danej aplikacji.

Proste zrównoleglenie wielu niezależnych zadań

Dość częstym przypadkiem użycia klastra jest przetworzenie wielu paczek danych, gdzie każda paczka jest przetwarzana niezależnie. Dobrym przykładem takich zadań jest przetwarzanie wielu obrazów w ten sam sposób. SLURM umożliwia proste zrównoleglenie takiego przetwarzania poprzez użycie komendy srun. Przykładowy skrypt, który zrównolegli uruchomienie wielu instancji obliczeń, gdzie stopień równoległości jest ustalany na podstawie parametrów zadania, znajduje się poniżej:

UWAGA! To jest przykładowy skrypt, którego NIE NALEŻY uruchamiać. Przed jego uruchomieniem należy przeglądnąć podane opcje i dostosować je do własnych potrzeb, zmieniając m.i. nazwę grantu, nazwę partycji, czas trwania zadania, itp.

#!/bin/bash -l
## Nazwa zlecenia
#SBATCH -J testjob
## Liczba alokowanych węzłów
#SBATCH -N 2
## Liczba zadań per węzeł (domyślnie jest to liczba alokowanych rdzeni na węźle)
#SBATCH --ntasks-per-node=12
## Ilość pamięci przypadającej na jeden rdzeń obliczeniowy (domyślnie 4GB na rdzeń)
#SBATCH --mem-per-cpu=4GB
## Maksymalny czas trwania zlecenia (format HH:MM:SS)
#SBATCH --time=01:00:00 
## Nazwa grantu do rozliczenia zużycia zasobów
#SBATCH -A <grant_id>
## Specyfikacja partycji
#SBATCH -p plgrid-testing
## Plik ze standardowym wyjściem
#SBATCH --output="output.out"
## Plik ze standardowym wyjściem błędów
#SBATCH --error="error.err"

module load plgrid/tools/imagemagick

## przejscie do katalogu z ktorego wywolany zostal sbatch
cd $SLURM_SUBMIT_DIR

ls *.tif | xargs -t -d "\n" -P ${SLURM_NTASKS} -n 1 srun -n 1 -N 1 --mem=4gb mogrify -format png

Powyższy skrypt dla każdego pliku *tif w katalogu uruchomi aplikację mogrify, tak aby skonwertować obraz do pliku png. Pierwszą czynnością jest wylistowanie plików wejściowych, następnie wynik jest przekazywany do komendy xargs, która przez parametr -P zapewnia równoległe uruchomienie dalszego polecania srun. Do każdej instancji srun zostanie przekazany jeden parametr, maksymalna równoległość wyniesie ${SLURM_NTASKS}. Każdy srun uruchomi aplikację mogrify na jednym rdzeniu z przydzielonym 4GB pamięci.