Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Međutim, za razliku od virtualnih strojeva koji sadrže cijele operacijske sustave i sve ovisnosti koje im trebaju za izvršavanje zadanih operacija (te su zbog toga zahtjevne za resurse), kontejeri kontejneri s hostom dijele kernel, te u sebi sadržavaju samo aplikacije, njihove ovisnosti i potrebne knjižnice (eng. library).

...

Tipični workflow za izgradnju kontejnera je sljedeći:

  1. pronalaženje uputa za instalaciju tražene aplikacijeaplikacije 
  2. istraživanje odgovarajućeg operativnog sustava
  3. kreiranje osnovnog kontejnera i njegova interaktivna nadogradnja
  4. prebacivanje kontejnera u image ili izvršni oblik
  5. dopremanje i izvršavanje na klasteru

...

  1. interaktivnom izgradnjom korištenjem verzije sandbox
  2. izgradnjom slike korištenjem definicijske datoteke .def

Nadogradnja kontejnera (lokalno) - shell --writable

Note
titleIzrada kontejnera

Upute koje koriste sudo pri izgradnji nisu moguće na Supeku i Padobranu jer korisnici nemaju takve ovlasti.

Pri izgradnji ili nadogradnji na Supeku i Padobranu koristite opciju fakeroot (npr. za interaktivnu nadogradnju):

Code Block
[korisnik@x3000c0s27b0n0 ~]$ apptainer shell --writable --fakeroot ...

U prvom slučaju, pri izgradnji kontejnera moramo navesti opciju opciju  build --sandbox koja će generirati kontejner u obliku direktorija ubuntu_20.04:

...

  • graditi u direktoriju /scratch/apptainer koji nije dio Lustre dijeljenog datotečnog sustava
  • prebaciti kreirani image nazad u vaš korisnički direktorij, jer u protivnom neće biti vidljiv izvan pristupnog čvora login-gpu.hpc.srce.hr
  • nakon izgradnje obrisati sve kreirane datotekepri sandbox izgradnji koristiti opciju fakeroot (
Note
titleIzrada kontejnera

Naredbe koje koriste sudo pri izgradnji nisu moguće na Supeku i Padobranu jer korisnici nemaju

...

takve ovlasti

...

.

Pri izgradnji ili nadogradnji na Supeku koristite opciju fakeroot (npr. za interaktivnu nadogradnju):

# login na pristupni poslužitelj gpu [korisnik@kompjuter
Code Block
languagebash
[korisnik@x3000c0s27b0n0 ~]$
ssh korisnik@login-gpu.hpc.srce.hr Last login: Wed May 24 09:23:06 2023 from x.x.x.x # pomicanje u /scratch i kreiranje direktorija za izgradnju [korisnik@x3000c0s27b0n0 ~]$ cd /scratch/apptainer [korisnik@x3000c0s27b0n0 apptainer]$ mkdir ${USER} [korisnik@x3000c0s27b0n0 apptainer]$ cd ${USER} # izgradnja sandbox verzije [korisnik@x3000c0s27b0n0 korisnik]$ apptainer build ubuntu_20.04_sandbox docker://ubuntu:20.04 [korisnik@x3000c0s27b0n0 korisnik]$ apptainer shell --writable --fakeroot ubuntu_20.04_sandbox Apptainer> ... Apptainer> ... dodatne komande za izgradnju kontejnera ... Apptainer> ... Apptainer> exit # mijenjanje sanboxa u image, prebacivanje u korisnički i [korisnik@x3000c0s27b0n0 korisnik]$ apptainer build ubuntu_20.04.sif ubuntu_20.04_sandbox [korisnik@x3000c0s27b0n0 korisnik]$ mv ubuntu_20.04.sif ~ [korisnik@x3000c0s27b0n0 korisnik]$ cd ~ # brisanje direktorija za izgradnju [korisnik@x3000c0s27b0n0 ~]$ rm -rf /scratch/apptainer/${USER}

Korištenje kontejnera

Kada jednom imamo gotov kontejner, postoji nekoliko naredbi za interagiranje s njim:

  • shell - pokretanje korisničke ljuske
  • exec - pokretanje naredbe
  • run - pokretanje zadane naredbe

Naredbom shell pokreće se ljuska unutar kontejnera, te se interagira s kontejnerom kao da je pokrenuta ljuska na malom virtualnom stroju.

 apptainer shell --writable --fakeroot ...
Tip
titleAPPTAINER_TMPDIR - Staza za privremene datoteke

Pri izgradnji ili nadogradnji, apptainer kreira privremene datoteke koje se spajaju u konačni kontejner i koristi stazu /tmp kao zadani direktorij.

/tmp direktorij na pristupnom poslužitelju je dijelom datotečnog prostora vezanog uz operativni sustav pristupnog poslužitelja i ima ograničen prostor od 178 gigabajta.

U trenutcima jače korisničke aktivnosti, a pogotovo višestruke izgradnje kontejnera koji mogu imati i do desetak gigabajta, zbog zadanog ponašanja s privremenim datotekama može doći do preopterećenja diskovnog prostora i smanjene funkcionalnosti operativnog sustava za sve korisnike.

U svrhu izbjegavanja ovog tipa preopterećenja, preporučeno je postaviti varijablu okoliša APPTAINER_TMPDIR prije izgradnje koja mijenja zadani direktorij i postaviti ga (primjerice) na direktorij unutar /scratch prostora (opisano u primjeru ispod)


Primjer sandbox izgradnje s dodatnim knjižnicama korištenjem Ubuntu v20.04 operativnog sustava:

Code Block
languagebash
# login na pristupni poslužitelj gpu
[korisnik@kompjuter ~]$ ssh korisnik@login-gpu.hpc.srce.hr
Last login: Wed May 24 09:23:06 2023 from x.x.x.x

# pomicanje u /scratch i kreiranje direktorija za izgradnju
[korisnik@x3000c0s27b0n0 ~]$ cd /scratch/apptainer
[korisnik@x3000c0s27b0n0 apptainer]$ mkdir ${USER}
[korisnik@x3000c0s27b0n0 apptainer]$ cd ${USER}

# postavljanje varijable okoliša za privremene datoteke
[korisnik@x3000c0s27b0n0 korisnik]$ export APPTAINER_TMPDIR=/scratch/apptainer/${USER}

# izgradnja sandbox verzije
[korisnik@x3000c0s27b0n0 korisnik]$ apptainer build --sandbox ubuntu_20.04_sandbox docker://ubuntu:20.04
[korisnik@x3000c0s27b0n0 korisnik]$ apptainer shell --writable --fakeroot ubuntu_20.04_sandbox
Apptainer> ...
Apptainer> ... dodatne komande za izgradnju kontejnera ...
Apptainer> ...
Apptainer> exit

# mijenjanje sanboxa u image, prebacivanje u korisnički i 
[korisnik@x3000c0s27b0n0 korisnik]$ apptainer build ubuntu_20.04.sif ubuntu_20.04_sandbox
[korisnik@x3000c0s27b0n0 korisnik]$ mv ubuntu_20.04.sif ~
[korisnik@x3000c0s27b0n0 korisnik]$ cd ~

# brisanje direktorija za izgradnju
[korisnik@x3000c0s27b0n0 ~]$ rm -rf /scratch/apptainer/${USER}

Korištenje kontejnera

Kada jednom imamo gotov kontejner, postoji nekoliko naredbi za interagiranje s njim:

  • shell - pokretanje korisničke ljuske
  • exec - pokretanje naredbe
  • run - pokretanje zadane naredbe

Naredbom shell pokreće se ljuska unutar kontejnera, te se interagira s kontejnerom kao da je pokrenuta ljuska na malom virtualnom stroju.

Code Block
languagebash
# otvaranje ljuske
[korisnik@kompjuter:~] $ singularity shell apptainer.sif
...

# izvršavanje komande unutar kontejnera
Apptainer> date | cowsay
 _______________________________
< Thu May 25 10:59:05 CEST 2023 >
 -------------------------------
Code Block
languagebash
# otvaranje ljuske
[korisnik@kompjuter:~] $ singularity shell apptainer.sif
...

# izvršavanje komande unutar kontejnera
Apptainer> date | cowsay
 _______________________________
< Thu May 25 10:59:05 CEST 2023 >
 -------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
        \   ^__^
     ||    \  ||

# izlaženje iz ljuske u kontejneru
Apptainer> exit

# izvršavanje iste komande izvan kontejnera
[korisnik@kompjuter:~] $ date | cowsay
bash: cowsay: command not found

Naredbom exec izvršava se naredba unutar kontejnera:

Code Block
languagebash
# izvršavanje naredbe cowsay unutar kontejnera
[korisnik@kompjuter:~] $ date | apptainer exec apptainer.sif cowsay
...
 < čet, 25.05.2023. 11:05:46 CEST  >
 --(oo)\_______
            (__)\       )\/\
                ||----w |
        \   ^__^
     ||    \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Naredbom run pokreće se kontejner pozivanjem runscripte definirane u Apptainer receptu.

 ||

# izlaženje iz ljuske u kontejneru
Apptainer> exit

# izvršavanje iste komande izvan kontejnera
[korisnik@kompjuter:~] $ date | cowsay
bash: cowsay: command not found

Naredbom exec izvršava se naredba unutar kontejnera:

Code Block
languagebash
# izvršavanje naredbe cowsay unutar kontejnera
[korisnik@kompjuter:~] $ date | apptainer exec apptainer.sif cowsay
Code Block
languagebash
# izvršavanje komandom run
[korisnik@kompjuter:~] $ apptainer run apptainer.sif
...
 < čet, 25.05.2023. 11:05:46 CEST  >
 --
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Naredbom run pokreće se kontejner pozivanjem runscripte definirane u Apptainer receptu.

Code Block
languagebash
# izvršavanje komandom run

# direktno izvršavanje
[korisnik@kompjuter:~] $ apptainer ./run apptainer.sif
...
 < čet, 25.05.2023. 11:0605:0546 CEST  >
 --
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Podnošenje kontejnera na Supeku

U slučaju da se koristi Apptainer kontejner na Supeku, podnošenje poslova je jednako kao i u slučaju aplikacija koje su instalirane direktno na klasteru.

Na primjer, ako želimo pokrenuti kontejner apptainer.sif nakon što ga dopremimo na Supek, minimalna skripta PBS apptainer-test.sh bit će:

Code Block
languagebash
#!/bin/bash
#PBS -N apptainer-test
apptainer run apptainer.sif

Koju možemo podnijeti na sljedeći način i provjeriti njen izlaz nakon malo vremena:



# direktno izvršavanje
[korisnik@kompjuter:~] $ ./apptainer.sif
...
 < čet, 25.05.2023. 11:06:05 CEST  >
 --
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Podnošenje kontejnera na Supeku

U slučaju da se koristi Apptainer kontejner na Supeku, podnošenje poslova je jednako kao i u slučaju aplikacija koje su instalirane direktno na klasteru.

Na primjer, ako želimo pokrenuti kontejner apptainer.sif nakon što ga dopremimo na Supek, minimalna skripta PBS apptainer-test.sh bit će:

Code Block
languagebash
#!/bin/bash
#PBS -N apptainer-test
apptainer run apptainer.sif

Koju možemo podnijeti na sljedeći način i provjeriti njen izlaz nakon malo vremena:

Code Block
languagebash
# podnošenje skripte apptainer-test.sh
[korisnik@x3000c0s25b0n0:~] $ qsub apptainer-test.sh

# nakon par sekundi provjerimo sadržaj direktorija
[korisnik@x3000c0s25b0n0:~] $ ls -l apptainer-test*
-rw------- 1 mkvakic hpc  75 May 25 11:31 apptainer-test.e10537
-rw------- 1 mkvakic hpc 229 May 25 11:31 apptainer-test.o10537
-rw-r--r-- 1 mkvakic hpc  63 May 25 11:31 apptainer-test.sh

# ispišemo sadržaj standardnog izlaza
[korisnik@x3000c0s25b0n0:~] $ cat apptainer-test.o10537
 _________________________________
< Thu May 25 09:31:17 Europe 2023 >
 ---------------------------------
        \   ^__^
Code Block
languagebash
# podnošenje skripte apptainer-test.sh
[korisnik@x3000c0s25b0n0:~] $ qsub apptainer-test.sh

# nakon par sekundi provjerimo sadržaj direktorija
[korisnik@x3000c0s25b0n0:~] $ ls -l apptainer-test*
-rw------- 1 mkvakic hpc  75 May 25 11:31 apptainer-test.e10537
-rw------- 1 mkvakic hpc 229 May 25 11:31 apptainer-test.o10537
-rw-r--r-- 1 mkvakic hpc  63 May 25 11:31 apptainer-test.sh

# ispišemo sadržaj standardnog izlaza
[korisnik@x3000c0s25b0n0:~] $ cat apptainer-test.o10537
 _________________________________
< Thu May 25 09:31:17 Europe 2023 >
 ---------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
              \  ||     ||

MPI aplikacije u kontejneru

Apptainer podržava paralelizaciju i širenje na više čvorova korištenjem MPI standarda na dva načina:

  1. hybrid model - izvršavanje korištenjem MPI implementacije u kontejneru
  2. bind model - izvršavanje korištenjem MPI implementacije izvan kontejnera
(oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

MPI aplikacije u kontejneru

Apptainer podržava paralelizaciju i širenje na više čvorova korištenjem MPI standarda na dva načina:

  1. hybrid model - izvršavanje korištenjem MPI implementacije u kontejneru
  2. bind model - izvršavanje korištenjem MPI implementacije izvan kontejnera

Na Supeku se preporučuje koristiti bind model zbog knjižnica koje osiguravaju integraciju sa sustavom za upravljanje PBS i mrežom Slingshot. Pri tom aplikacija koja koristi MPI mora biti ABI kompatibilna (kompajlirana sa MPICH verzija => v3.1 nadalje) . Način na koji se to inače postiže je dopremanjem knjižnice libmpi.so.12 putem varijable okoliša LD_LIBRARY_PATH prije poziva aplikacije:

Code Block
languagebash
# postavljanje LD_LIBRARY_PATH
[korisnik@kompjuter] $ export LD_LIBRARY_PATH=/putanja/do/libmpi.so.12:$LD_LIBRARY_PATH

# izvršavanje aplikacijom mpiexec
[korisnik@kompjuter] $ mpiexec -np 10 ./moja_ABI_kompatibilna_MPI_aplikacija

U slučaju kontejnera, varijable okoliša se uglavnom nasljeđuju od računala s kojeg se pokreće, no u ovom slučaju potrebno je dodatno namjestiti okolinu što se može učiniti na dva načina:

  • korištenjem --env ili --env-file opcije pri pokretanju kontejnera
  • namještanjem APPTAINERENV_* varijable okoliša prije pozivanja kontejnera

Na Supeku je potrebno je koristiti bind model, zbog knjižnica koje osiguravaju integraciju sa sustavom za upravljanje PBS i mrežom Slingshot. Moduli koji osiguravaju spajanje definicijom varijabli okoliša CRAY_LD_LIBRARY_PATH i LD_LIBRARY_PATH su:

  • cray-pals - integracija Craya sa sustavom PBS Professional
  • cray-mpich-abi - dostavljanje ABI kompatibilnih knjižnica
  • cray-pmi - knjižnica za spajanje s Crayevim sučeljem za pokretanje paralelnih programa
  • libfabric - mrežni API za spajanje na Slinghot

Dodatno, pri pozivu se moraju spojiti odgovarajući direktoriji u kontejner:

  • /opt - putanja za knjižnice Cray
  • /run - putanja za PBS
  • /usr/lib64 - putanja za sistemske knjižnice

ili kompajlirana sa openMPI 5.x.x verzijom. Isto tako, potrebno je koristiti RHEL-8.6 kompatibilne linux distribucije.

Warning
titleOsnovni operativni sustav kontejnera

Zbog bind model spajanja, potrebno je koristiti operativne sustave koji su slični operativnom sustavu Supeka Red Hat Enterprise Linux 8.6.

Neki od mogućih su:

Kako bi korisnicima olakšali izgradnju kontejnera i pokretanje aplikacija sa bind modelom, pripremili smo početne slike kontejnera povrh kojih je moguće instalirati i kompajlirati aplikacije. Pripremljene slike sadrže MPICH i openMPI kompatibilne verzije sa MPI implementacijama dostupnim na Supeku. Osim slika, pripremljeni su i odgovarajući moduli koji će spojiti potrebne knjižnice i direktorije na Supeku sa kontejnerom.

U tablici su prikazane putanje slika za izgranju kontejnera i odgovarajući moduli ovisno o MPI implementaciji:

MPI kontejnerOS kontejnerMPI modelMPI SupekPolazni kontejnerBind modul
mpich-4.1.1Rocky-8Bindcray-mpich-8.1.26

/apps/utils/apptainer-images/rockylinux-8-mpich-4.1.1.sif

utils/apptainer-bind/cray-mpich

openMPI-5.0.1Rocky-8Bind

Openmpi- 5.0.1-gnu-8.5.0

/apps/utils/apptainer-images/rockylinux-8-openmpi-5.0.1.sif

utils/apptainer-bind/openmpi-5.0.1

openMPI-4.1.2Ubuntu-22.04Hybrid

OpenMPI 4.x.x

/apps/utils/apptainer-images/ubuntu-22.04-openmpi-4.1.2.sif

X


Primjer izgradnje kontejnera koristeći MPICH(v4.1.1) :

Code Block
languagebash
titleDefinicijska datoteka (recept)
Bootstrap: localimage
From: /apps/utils/apptainer-images/rockylinux-8-mpich-4.1.1.sif

%files

  #kopiranje datoteka
  mpi.latency.c         /testmpi/

%post

  # prevedi aplikaciju u izvršnu datoteku
  mpicc     /testmpi/mpi.latency.c             -o /testmpi/mpi.latency
Code Block
languagebash
titlerun_cray-mpich.sh
#PBS -q cpu
#PBS -l select=2:ncpus=1
#PBS -l place=scatter

cd $PBS_O_WORKDIR

module load utils/apptainer-bind/cray-mpich

mpiexec --no-transfer apptainer exec mpich.sif /testmpi/mpi.latency
Code Block
languagec#
titlempi.latency.c
collapsetrue
.mpitutorial.com
// This code is provided freely with the tutorials on mpitutorial.com. Feel
// free to modify it for your own use. Any distribution of the code must
// either provide a link to www.mpitutorial.com or keep this header intact.
//
// An intro MPI hello world program that uses MPI_Init, MPI_Comm_size,
// MPI_Comm_rank, MPI_Finalize, and MPI_Get_processor_name.
//
#include <mpi.h>
#include <stdio.h>

int main(int argc, char** argv) {
  // Initialize the MPI environment. The two arguments to MPI Init are not
  // currently used by MPI implementations, but are there in case future
  // implementations might need the arguments.
  MPI_Init(NULL, NULL);
  
  // Get the number of processes
  int world_size;
  MPI_Comm_size(MPI_COMM_WORLD, &world_size);
  
  // Get the rank of the process
  int world_rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);

  // Get the name of the processor
  char processor_name[MPI_MAX_PROCESSOR_NAME];
  int name_len;
  MPI_Get_processor_name(processor_name, &name_len);

  // Print off a hello world message
  printf("Hello world from processor %s, rank %d out of %d processors\n",
         processor_name, world_rank, world_size);

  // Finalize the MPI environment. No more MPI calls can be made after this
  MPI_Finalize();
}

Grafički procesori i CUDA

Apptainer pruža podršku za izvršavanje na grafičikim procesorima ako su aplikacije i kontejneri namijenjeni za njihovo korištenje.

Ova mogućnost jednostavno se ostvaruje korištenjem opcije --nv pri izvršavanju kontejnera komandama exec ili run.

Ispod se nalazi primjer izgradnje kontejnera PyTorch v1.13.1 za duboko učenje i njegovo testiranje na pristupnom poslužitelju s grafičkim čvorovimaPri podnošenju posla na Crayu, to se može učiniti na sljedeći način (primjerice, u skripti PBS mpi-test.sh) :

Code Block
languagebash
#!/bin/bash

#PBS -N mpi-test
#PBS -l select=2:ncpus=1
#PBS -l place=scatter

# dopremanje modula
module load PrgEnv-gnu
module load cray-mpich-abi
module load cray-pals
module load cray-pmi
module load libfabric

# namještanje okolišne varijable LD_LIBRARY_PATH u kontejneru:
#
#     1) CRAY_LD_LIBRARY_PATH        - Cray knjižnice iz /opt
#     2) LD_LIBRARY_PATH             - sistemske knjižnice iz /usr/lib64
#     3) \$LD_LIBRARY_PATH           - očuvanje varijable ako već postoji u kontejneru
#     4) /opt/cray/pe/pals/1.2.3/lib - putanja za PALS servis
#
APPTAINERENV_LD_LIBRARY_PATH="${CRAY_LD_LIBRARY_PATH}:${LD_LIBRARY_PATH}:\$LD_LIBRARY_PATH:/opt/cray/pe/pals/1.2.3/lib"

# izvršavanje kontejnera mpi-test.sif s aplikacijom mpiexec modula cray-pals
mpiexec --no-transfer \
  apptainer exec \
    --bind /opt \
    --bind /run \
    --bind /usr/lib64 \
    mpi4py-install.sif \
      /myapp/mpi-test

Gdje je su recept za izgradnju kontejnera mpi-test.sif i aplikacija mpi-test.c:

Code Block
languagebash
titlempi-test.sif
collapsetrue
Bootstrap: docker
From: rockylinux:8

%files
  mpi-test.c /myapp/

%environment
  export LD_LIBRARY_PATH=/usr/lib64/mpich/lib:$LD_LIBRARY_PATH
  export PATH=/usr/lib64/mpich/bin:$PATH

%post

  # osvježi i instaliraj knjižnice za kompilaciju
  dnf update -y
  dnf install mpich-devel -y

  # namjesti okolinu za razvoj MPICHom
  export LD_LIBRARY_PATH=/usr/lib64/mpich/lib:$LD_LIBRARY_PATH
  export PATH=/usr/lib64/mpich/bin:$PATH
  
  # prevedi aplikaciju u izvršnu datoteku
  mpicc -o /myapp/mpi-test /myapp/mpi-test.c
Code Block
languagec#
titlempi-test.c
collapsetrue
// Author: Wes Kendall
// Copyright 2011 www.mpitutorial.com
// This code is provided freely with the tutorials on mpitutorial.com. Feel
// free to modify it for your own use. Any distribution of the code must
// either provide a link to www.mpitutorial.com or keep this header intact.
//
// An intro MPI hello world program that uses MPI_Init, MPI_Comm_size,
// MPI_Comm_rank, MPI_Finalize, and MPI_Get_processor_name.
//
#include <mpi.h>
#include <stdio.h>

int main(int argc, char** argv) {
  // Initialize the MPI environment. The two arguments to MPI Init are not
  // currently used by MPI implementations, but are there in case future
  // implementations might need the arguments.
  MPI_Init(NULL, NULL);
  
  // Get the number of processes
  int world_size;
  MPI_Comm_size(MPI_COMM_WORLD, &world_size);
  
  // Get the rank of the process
  int world_rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);

  // Get the name of the processor
  char processor_name[MPI_MAX_PROCESSOR_NAME];
  int name_len;
  MPI_Get_processor_name(processor_name, &name_len);

  // Print off a hello world message
  printf("Hello world from processor %s, rank %d out of %d processors\n",
         processor_name, world_rank, world_size);

  // Finalize the MPI environment. No more MPI calls can be made after this
  MPI_Finalize();
}
Warning
titleOsnovni operativni sustav kontejnera

Zbog bind model spajanja, potrebno je koristiti operativne sustave koji su slični operativnom sustavu Supeka Red Hat Enterprise Linux 8.6.

Neki od mogućih su:

Grafički procesori i CUDA

Apptainer pruža podršku za izvršavanje na grafičikim procesorima ako su aplikacije i kontejneri namijenjeni za njihovo korištenje.

Ova mogućnost jednostavno se ostvaruje korištenjem opcije --nv pri izvršavanju kontejnera komandama exec ili run.

Ispod se nalazi primjer izgradnje kontejnera PyTorch v1.13.1 za duboko učenje i njegovo testiranje na pristupnom poslužitelju s grafičkim čvorovima:

 spajanje na pristupni poslužitelj
[korisnik@kompjuter:~] $ ssh mkvakic@login-gpu.hpc.srce.hr

# izgradnja pytorch kontejnera
[korisnik@x3000c0s27b0n0:~] $ apptainer build pytorch_1.13.1.sif docker://pytorch/pytorch:1.13.1-cuda11.6-cudnn8-runtime

# print raznih informacija korištenjem --nv
[korisnik@x3000c0s27b0n0:~] $ apptainer run --nv ./pytorch_1.13.1.sif python -c "import torch; print('Is cuda available?:', torch.cuda.is_available())"
Is cuda available?: True
[korisnik@x3000c0s27b0n0:~] $ apptainer run --nv ./pytorch_1.13.1.sif python -c "import torch; print('Device count:', torch.cuda.device_count())"
Device count: 1
[korisnik@x3000c0s27b0n0:~] $ apptainer run --nv ./pytorch_1.13.1.sif python -c "import torch; print('Current device:', torch.cuda.current_device())"
Current device: 0
[korisnik@x3000c0s27b0n0:~] $ apptainer run --nv ./pytorch_1.13.1.sif python -c "import torch; print('Device name:', torch.cuda.get_device_name(0))"
Device name: NVIDIA A100-PCIE-40GB


Nadogradnja sandbox kontejnera sa korištenjem  --nv opcije moguća je nakon modifikacije sandbox direktorija izvan kontejnera. 

Code Block
titleKorištenje "sandbox" kontejnera sa --nv opcijom
# izgradnja test.sandbox sandbox slike kontejnera
[korisnik@x3000c0s27b0n0:~] $ apptainer build --sandbox --fix-perms test.sandbox test.def

# modifikacija slike kontejnera
[korisnik@x3000c0s27b0n0:~] $ touch test.sanbox/usr/bin/nvidia-smi
[korisnik@x3000c0s27b0n0:~] $ touch test.sanbox/usr/bin/nvidia-debugdump
[korisnik@x3000c0s27b0n0:~] $ touch test.sanbox/usr/bin/nvidia-persistenced
[korisnik@x3000c0s27b0n0:~] $ touch test.sanbox/usr/bin/nvidia-cuda-mps-control
[korisnik@x3000c0s27b0n0:~] $ touch test.sanbox/usr/bin/nvidia-cuda-mps-server
[korisnik@x3000c0s27b0n0:~] $ mkdir -p test.sandbox/var/run/nvidia-persistenced/
[korisnik@x3000c0s27b0n0:~] $ touch test.sanbox/var/run/nvidia-persistenced/socket

# pokretanje "sandbox" kontainera sa --nv opcijom
[korisnik@x3000c0s27b0n0:~] $ apptainer shell --nv --writable --fakeroot test.sandbox


NVIDIA NGC kontejneri

Tip
NVIDIA driveri na pristupnom poslužitelju su nadograđeni i usklađeni sa radnim poslužiteljima u siječnju 2024. godine!
Izgradnja valjanog kontejnera sa NGC repozitorija moguća je na pristupnom poslužitelju bez --bind opcije ili dodatnih naredbi i konfiguracije.

Nvidia NGC je repozitorij namijenjen korištenju kontejnera optimiziranih za izvršavanje na NVIDIA grafičkim procesorima i sadrži sijaset recepata za popularne aplikacije (poput strojnog učenja) pogodnih za izgradnju i modifikaciju za specifične korisničke potrebe.

Pri nadogradnji (interaktivnoj ili putem definicijskih datoteka), jedna od skripti unutar kontejnera postavlja korisničku okolinu (/etc/shinit_v2) i osigurava tzv. "forward" kompatibilnost na način da učitava datoteku /proc/driver/nvidia/version s domaćina, stvarajući sloj datoteka (/usr/local/cuda-11.8/compat/lib) koje usklađuju verziju CUDE s driverima na pristupnom poslužitelju (525.60.13):

Code Block
languagebash
# izgradi proizvoljan kontejner ngc korištenjem repozitorija NGC čija verzija CUDE (npr. v11.8) ovisi o driveru 520.61.05
[korisnik@x3000c0s27b0n0 ~] apptainer build ngc-kontejner.sif ngc-kontejner.def
...

# ispiši sadržaj /usr/local/cuda-11.8/compat/lib unutar kontejnera
[korisnik@x3000c0s27b0n0 ~] apptainer exec ngc-kontejner.sif ls -l /usr/local/cuda-11.8/compat/lib.real/lib
13:4: not a valid test operator: (
13:4: not a valid test operator: 525.60.13
total 145702
lrwxrwxrwx 1 korisnik korisnik       12 Sep 29  2022 libcuda.so -> libcuda.so.1
lrwxrwxrwx 1 korisnik korisnik       20 Sep 29  2022 libcuda.so.1 -> libcuda.so.520.61.05
-rw-r--r-- 1 korisnik korisnik 26284256 Sep 29  2022 libcuda.so.520.61.05
lrwxrwxrwx 1 korisnik korisnik       28 Sep 29  2022 libcudadebugger.so.1 -> libcudadebugger.so.520.61.05
-rw-r--r-- 1 korisnik korisnik 10934360 Sep 29  2022 libcudadebugger.so.520.61.05
lrwxrwxrwx 1 korisnik korisnik       19 Sep 29  2022 libnvidia-nvvm.so -> libnvidia-nvvm.so.4
lrwxrwxrwx 1 korisnik korisnik       27 Sep 29  2022 libnvidia-nvvm.so.4 -> libnvidia-nvvm.so.520.61.05
-rw-r--r-- 1 korisnik korisnik 92017376 Sep 29  2022 libnvidia-nvvm.so.520.61.05
lrwxrwxrwx 1 korisnik korisnik       37 Sep 29  2022 libnvidia-ptxjitcompiler.so.1 -> libnvidia-ptxjitcompiler.so.520.61.05
-rw-r--r-- 1 korisnik korisnik 19963864 Sep 29  2022 libnvidia-ptxjitcompiler.so.520.61.05


Pri izvršavanju aplikacija unutar ovog kontejnera, usklađenost kontejnera testira se izvršnom datotekom /usr/local/bin/cudaCheck:

Code Block
languagebash
# testiraj usklađenost na pristupnom poslužitelju GPU
[korisnik@x3000c0s27b0n0 ~] apptainer exec --nv ngc-kontejner.sif /usr/local/bin/cudaCheck
INFO:    underlay of /etc/localtime required more than 50 (95) bind mounts
INFO:    underlay of /usr/bin/nvidia-smi required more than 50 (474) bind mounts
13:4: not a valid test operator: (
13:4: not a valid test operator: 525.60.13
CUDA Driver OK

# spoji se interaktivnom sjednicom na jedan od radnih GPU čvorova
[korisnik@x3000c0s27b0n0 ~] qsub -l ngpus=1 -I
qsub: waiting for job 107908.x3000c0s25b0n0.hsn.hpc.srce.hr to start
qsub: job 107908.x3000c0s25b0n0.hsn.hpc.srce.hr ready

# testiraj usklađenost na radnom čvoru
[korisnik@x8000c2s4b0n1 ~] apptainer exec --nv ngc-kontejner.sif /usr/local/bin/cudaCheck
INFO:    underlay of /etc/localtime required more than 50 (95) bind mounts
INFO:    underlay of /usr/bin/nvidia-smi required more than 50 (474) bind mounts
13:4: not a valid test operator: (
13:4: not a valid test operator: 525.60.13
CUDA Driver OK
Code Block
languagebash
# spajanje na pristupni poslužitelj
[korisnik@kompjuter:~] $ ssh mkvakic@login-gpu.hpc.srce.hr

# izgradnja pytorch kontejnera
[korisnik@x3000c0s27b0n0:~] $ apptainer build pytorch_1.13.1.sif docker://pytorch/pytorch:1.13.1-cuda11.6-cudnn8-runtime

# print raznih informacija korištenjem --nv
[korisnik@x3000c0s27b0n0:~] $ apptainer run --nv ./pytorch_1.13.1.sif python -c "import torch; print('Is cuda available?:', torch.cuda.is_available())"
Is cuda available?: True
[korisnik@x3000c0s27b0n0:~] $ apptainer run --nv ./pytorch_1.13.1.sif python -c "import torch; print('Device count:', torch.cuda.device_count())"
Device count: 1
[korisnik@x3000c0s27b0n0:~] $ apptainer run --nv ./pytorch_1.13.1.sif python -c "import torch; print('Current device:', torch.cuda.current_device())"
Current device: 0
[korisnik@x3000c0s27b0n0:~] $ apptainer run --nv ./pytorch_1.13.1.sif python -c "import torch; print('Device name:', torch.cuda.get_device_name(0))"
Device name: NVIDIA A100-PCIE-40GB