Kontenery Docker

Dla węzłów z GPU istnieje możliwość użycia kontenerów Apptainer oraz pośrednio kontenerów Docker do obliczeń. Zalecane jest zapoznanie się z dokumentacją projektu dotyczącej tej metody.

Zagrożenie

Aby zapewnić kompatybilność z uruchamianiem wielu równoległych kopii obrazy Apptainer tworzone są w trybie tylko do odczytu. Podczas ich uruchamiania domyślnie montowany jest katalog bieżący oraz domowy użytkownika.

Należy zwrócić uwagę na możliwość modyfikacji środowiska użytkownika przez kontenery.

Obecnie przygotowanie kontenerów wymaga utworzenia rezerwacji interaktywnej GPU:

salloc --no-shell --partition=gpu --gpus=1 --cpus-per-task=4 --mem=24G

Po uzyskaniu rezerwacji należy zalogować się do węzła przez SSH i przejść do katalogu roboczego w celu utworzenia katalogu dla kontenera:

cd /work/$USER
mkdir docker-test
cd docker-test

Obsługa kontenerów Docker

Import z Dockerhub

  1. Zbudowanie kontenera Apptainer na podstawie obrazu Docker TensorFlow:
apptainer build tf-gpu.sif \
    docker://tensorflow/tensorflow:latest-gpu
  1. Zbudowanie kontenera Apptainer na podstawie obrazu Docker PyTorch:
apptainer build pt-gpu.sif \
    docker://pytorch/pytorch:latest

Praca interaktywna

Aby uruchomić utworzony kontener w trybie interaktywnym z dostępem do GPU należy:

  1. TensorFlow
apptainer run --nv tf-gpu.sif
  1. PyTorch
apptainer run --nv pt-gpu.sif

Uzyskany znak zachęty Apptainer> oznacza pracę wewnątrz kontenera.

Weryfikacja TensorFlow

python
from tensorflow.python.client import device_lib

local_device_protos = device_lib.list_local_devices()

[x.physical_device_desc for x in local_device_protos if x.device_type == 'GPU']

Jeśli wszystko się udało, to wynik powinien wyglądać podobnie do:

['device: 0, name: NVIDIA GeForce RTX 4090, pci bus id: 0000:00:10.0, compute capability: 8.9']

Weryfikacja PyTorch

python
import torch

print([(i, torch.cuda.get_device_properties(i)) for i in range(torch.cuda.device_count())])

Jeśli wszystko się udało, to wynik powinien wyglądać podobnie do:

[(0, _CudaDeviceProperties(name='NVIDIA GeForce RTX 4090', major=8, minor=9, total_memory=24210MB, multi_processor_count=128))]

Montowanie zasobów

Domyślnie zamontowany w kontenerze jest katalog domowy /home/<login> oraz katalog bieżący. Aby zamontować inny katalog, na przykład /work/<login> należy rozbudować polecenie:

apptainer run --bind /work/$USER/:/work/$USER --nv tf-gpu.sif

Kolejkowanie zadań

Podobnie jak w przypadku zadań CPU możliwe jest kolejkowanie zadań korzystających z kontenerów.

Warto przygotować skrypty i dane jako osobny katalog i zamontować go w kontenerze:

mkdir to_container
nano to_container/test_gpu.py
test_gpu.py
from tensorflow.python.client import device_lib

local_device_protos = device_lib.list_local_devices()

print([x.physical_device_desc for x in local_device_protos if x.device_type == 'GPU'])

Skrypt uruchamiający:

wykonaj.sh
#!/usr/bin/env bash

# Przykład wykonania skryptu Pythona w kontenerze

#SBATCH --job-name=apptainer-tf-gpu   # nazwa zadania
#SBATCH --partition=gpu                 # partycja (CPU/GPU)
#SBATCH --gres=gpu:1                    # jeden GPU
#SBATCH --exclusive                     # pozostałe zasoby na wyłączność
#SBATCH --time=10:00                    # limit czasu wykonania zadania - 10min
#SBATCH --output=sing-tf-gpu-%j.out     # schemat pliku wynikowego %j - numer zadania
#SBATCH --mail-type=ALL                 # konfiguracja powiadomienia e-mail
#SBATCH --mail-user=WPISZ_SWOJ_PELEN_EMAIL  # adres dla powiadomień e-mail

# przejście do katalogu roboczego
cd /work/$USER/docker-test || exit -1

srun apptainer exec --nv --bind ./to_container/:/mnt tf-gpu.sif python /mnt/test_gpu.py

Budowanie na podstawie Dockerfile

Apptainer niezbyt dobrze radzi sobie z budowaniem kontenerów, gdyż zwykle potrzebuje do tego uprawnień administracyjnych. Istnieją metody obejścia tego problemu za pomocą parametrów --fakeroot i --sandbox lecz też mają swoje problemy. Dodatkowo Apptainer nie obsługuje bezpośredniego importu Dockerfile - należy je przetłumaczyć na natywny język opisu kontenerów.

Aby zbudować kontener na podstawie Dockerfile należy użyć innego narzędzia - charliecloud dostępnego w systemie modułów środowiskowych.

Zagrożenie

Budowanie kontenerów jest złożonym procesem wymagającym dużych zasobów, więc należy tę operację przeprowadzać wyłącznie na węzłach obliczeniowych.

Przed rozpoczęciem budowania kontenera należy usunąć z Dockerfile dyrektywy CMD oraz ENTRYPOINT, gdyż nie są one jeszcze obsługiwane.

Ostrzeżenie

System skonfigurowany jest aby umieszczać obrazy oraz tymczasowe pliki w katalogu tymczasowym /tmp węzłów obliczeniowych. Aby zachować zbudowany obraz należy go po weryfikacji wyeksportować do formatu SquashFS.

Po załadowaniu modułu przez module load charliecloud należy przejść do katalogu zawierającego Dockerfile oraz ewentualnie inne pliki źródłowe konieczne do budowy kontenera.

Aby zbudować kontener o nazwie hello należy wydać polecenie:

ch-image build -t hello -f Dockerfile .

Po zakończeniu budowania można uruchomić powłokę Bash w kontenerze za pomocą:

ch-run hello bash

Po sprawdzeniu czy kontener działa poprawnie należy wyjść z powłoki przez exit, a następnie skonwertować obraz kontenera do formatu SquashFS:

ch-convert hello hello.sqfs

Wynikowy plik może być później uruchamiany bezpośrednio przez Apptainer.