Differenze tra le versioni di "AIE:Guida Utenti"

Da ISTI S2I2S Wiki.
Jump to navigation Jump to search
 
(4 versioni intermedie di 2 utenti non mostrate)
Riga 62: Riga 62:
  
 
==Accesso e Utilizzo Cluster di calcolo==
 
==Accesso e Utilizzo Cluster di calcolo==
Una volta ottenuto l'utente
+
Una volta ottenuto l'utente si accede al cluster tramite ssh tramite il comando:
  
 
'''TODO''' Si accede al frontend<syntaxhighlight lang="bash">
 
'''TODO''' Si accede al frontend<syntaxhighlight lang="bash">
 
ssh <username>@edge-mst1.isti.cnr.it
 
ssh <username>@edge-mst1.isti.cnr.it
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
Verrà richiesta la password (il cursore del terminale non si muove quando si inserisce la password).
 +
 +
'''N.B.:''' Se si tratta del primo accesso è caldamente consigliato il cambio della password. Per farlo utilizzare il comando: <code>passwd</code>, verrà chiesto di inserire la password vecchia e, successivamente, la password nuova (due volte).
  
 
E' obbligatorio l'utilizzo di slurm per lanciare jobs sul cluster.
 
E' obbligatorio l'utilizzo di slurm per lanciare jobs sul cluster.
La documentazione ufficiale e' disponibile ai seguenti link:<br/>
+
La documentazione ufficiale e' disponibile ai seguenti link:<br />
https://slurm.schedmd.com/documentation.html<br/>
+
https://slurm.schedmd.com/documentation.html<br />
https://slurm.schedmd.com/tutorials.html<br/>
+
https://slurm.schedmd.com/tutorials.html
 +
 
 +
A questo punto è possibile vedere le risorse disponibili sul cluster tramite il comando <code>sinfo</code> che ritornerà la lista delle partizioni, i rispettivi limiti di tempo e i relativi nodi associati. L'output del comando è il seguente:<syntaxhighlight lang="bash">
 +
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
 +
debug        up  infinite      4  idle gn[01-04]
 +
short        up    1:30:00      1  idle gn01
 +
long*        up 3-00:00:00      4  idle gn[01-04]
 +
</syntaxhighlight>
 +
 
 +
Come è possibile vedere, a disposizione dell'utente sono presenti due partizioni:
 +
 
 +
* short: utilizzabile per job "brevi", un job lanciato su questa partizione verrà, infatti, chiuso dopo 1:30 ore dall'inizio del run;
 +
* long: utilizzabile per job più lunghi, ha un tempo limite di 3 giorni.
 +
 
 +
'''N.B.:''' Per le attività di calcolo, '''sempre''' utilizzare una di queste partizioni, <u>'''mai''' svolgere operazioni di calcolo sul nodo di frontend.</u>
  
 +
=== Run di un job ===
 +
Il run di job può avvenire secondo due modalità:
  
 +
* modalità interattiva;
 +
* modalità batch.
  
'''TODO''' Si richiede risorse con SLURM<syntaxhighlight lang="bash">
+
==== Modalità interattiva ====
srun/sbatch ...
+
Si può aprire una sessione interattiva di Bash con il seguente comando:<syntaxhighlight lang="slurm">
 +
srun -n1 -p short --pty /bin/bash
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Riga 82: Riga 105:
 
Per un tutorial e alcuni esempi di utilizzo si può vedere la wiki: https://gitlab.com/w895/centro_calcolo_isti/-/wikis/home
 
Per un tutorial e alcuni esempi di utilizzo si può vedere la wiki: https://gitlab.com/w895/centro_calcolo_isti/-/wikis/home
  
== Accesso e Utilizzo NVIDIA DGX A100==
+
==Accesso e Utilizzo NVIDIA DGX A100==
Si accede alla DGX via ssh con certificato preinstallato (nessuna password viene richiesta):<syntaxhighlight lang="bash">
+
 
 +
 
 +
 
 +
Si accede alla DGX via ssh con certificato preinstallato (nessuna password viene richiesta):
 +
 
 +
<syntaxhighlight lang="bash">
 
ssh <username>@edge-nd1.isti.cnr.it
 
ssh <username>@edge-nd1.isti.cnr.it
</syntaxhighlight>'''È fortemente consigliato''' l'utilizzo di [https://www.docker.com/ Docker]  ([https://training.play-with-docker.com/ops-stage1/ qui]un tutorial) per creare l'ambiente con il software necessario e lanciare processi.
+
</syntaxhighlight>
 +
 
 +
'''È fortemente consigliato''' l'utilizzo di [https://www.docker.com/ Docker]  ([https://training.play-with-docker.com/ops-stage1/ qui]un tutorial) per creare l'ambiente con il software necessario e lanciare processi. Vedi la sezione [[AIE:Guida Utenti#Esempio di workflow|Esempio di workflow]] per una guida di esempio all'utilizzo consigliato.
 +
 
  
 
'''Si richiede:'''
 
'''Si richiede:'''
  
# di taggare le proprie immagini docker con nomi nel formato <code><username>/<nome_immagine></code> (es: <code>fabiocarrara/my-project:latest</code>). '''<u>Le immagini che non seguono questo standard possono essere cancellate periodicamente per recuperare spazio.</u>'''
+
#di taggare le proprie immagini docker con nomi nel formato <code><username>/<nome_immagine></code> (es: <code>fabiocarrara/my-project:latest</code>). '''<u>Le immagini che non seguono questo standard possono essere cancellate periodicamente per recuperare spazio.</u>'''
# di '''<u>NON</u>''' lanciare e tenere attivi job e/o servizi interattivi (es. jupyter notebooks, server http/flask, etc.). '''<u>I processi che non seguono questo standard possono essere killati in qualsiasi momento.</u>'''
+
#di '''<u>NON</u>''' lanciare e tenere attivi job e/o servizi interattivi (es. jupyter notebooks, server http/flask, etc.). '''<u>I processi che non seguono questo standard possono essere killati in qualsiasi momento.</u>'''
# di aggiungere ad ogni invocazione di <code>docker run</code> le opzioni <code>--user</code> e <code>--cpus</code> come segue:<syntaxhighlight lang="bash">
+
#di aggiungere ad ogni invocazione di <code>docker run</code> le opzioni <code>--user</code> e <code>--cpus</code> come segue:<syntaxhighlight lang="bash">
 
docker run \
 
docker run \
 
     ...
 
     ...
Riga 99: Riga 130:
 
</syntaxhighlight>L'opzione <code>--user</code> è necessaria per evitare che i processi girino come utente <code>root</code>. '''<u>I processi che non seguono questo standard e girano come <code>root</code> possono essere killati in qualsiasi momento.</u>'''  L'opzione <code>--cpus</code> è fortemente consigliata per evitare di occupare erroneamente l'interezza delle CPU. Una euristica per specificare <code><X></code> è scegliere un valore compreso tra <code>8*nGPUs</code> e <code>24*nGPUs</code> dove <code>nGPUs</code> indica il numero di GPU richieste.
 
</syntaxhighlight>L'opzione <code>--user</code> è necessaria per evitare che i processi girino come utente <code>root</code>. '''<u>I processi che non seguono questo standard e girano come <code>root</code> possono essere killati in qualsiasi momento.</u>'''  L'opzione <code>--cpus</code> è fortemente consigliata per evitare di occupare erroneamente l'interezza delle CPU. Una euristica per specificare <code><X></code> è scegliere un valore compreso tra <code>8*nGPUs</code> e <code>24*nGPUs</code> dove <code>nGPUs</code> indica il numero di GPU richieste.
  
=== Esempio di workflow ===
+
===Esempio di workflow===
  
# Creo una workdir per un nuovo progetto sui dischi non-SSD (dentro <code>~/raid/</code>):<syntaxhighlight lang="bash">
+
#Creo una workdir per un nuovo progetto sui dischi non-SSD (dentro <code>~/raid/</code>):<syntaxhighlight lang="bash">
 
mkdir ~/raid/my-project
 
mkdir ~/raid/my-project
 
cd ~/raid/my-project
 
cd ~/raid/my-project
 
</syntaxhighlight>
 
</syntaxhighlight>
# Creo un file <code>Dockerfile</code> scegliendo un'immagine di partenza (<code>FROM</code>) e installando i miei requisiti software (<code>RUN</code>).<syntaxhighlight lang="bash">
+
#Creo un file <code>Dockerfile</code> scegliendo un'immagine di partenza (<code>FROM</code>) e installando i miei requisiti software (<code>RUN</code>).<syntaxhighlight lang="bash">
 
cat << EOF > Dockerfile
 
cat << EOF > Dockerfile
 
FROM nvcr.io/nvidia/pytorch:22.09-py3
 
FROM nvcr.io/nvidia/pytorch:22.09-py3
Riga 111: Riga 142:
 
EOF
 
EOF
 
</syntaxhighlight>
 
</syntaxhighlight>
# Costruisco la mia immagine:<syntaxhighlight lang="bash">
+
#Costruisco la mia immagine:<syntaxhighlight lang="bash">
 
# sostituire <username> con il proprio nome utente
 
# sostituire <username> con il proprio nome utente
docker build -t <username>/my-project:latest -f - < Dockerfile
+
docker build -t <username>/my-project:latest - < Dockerfile
 
</syntaxhighlight>
 
</syntaxhighlight>
# Creo uno script bash <code>drun.sh</code> per lanciare comandi dentro dei container nati dalla mia immagine. Questo è il contenuto di <code>drun.sh</code>:<syntaxhighlight lang="bash">
+
#Creo uno script bash <code>drun.sh</code> per lanciare comandi dentro dei container nati dalla mia immagine. Questo è il contenuto di <code>drun.sh</code>:<syntaxhighlight lang="bash">
 
#!/bin/bash
 
#!/bin/bash
  
Riga 131: Riga 162:
 
      
 
      
 
</syntaxhighlight>dove:
 
</syntaxhighlight>dove:
#* <code>--interactive --tty</code>: opzioni necessarie per processi interattivi (e.g., bash),
+
#*<code>--interactive --tty</code>: opzioni necessarie per processi interattivi (e.g., bash),
#* <code>--rm</code>: rimuove il container alla terminazione del processo (i container saranno effimeri, se ne creerà uno nuovo ad ogni invocazione),
+
#*<code>--rm</code>: rimuove il container alla terminazione del processo (i container saranno effimeri, se ne creerà uno nuovo ad ogni invocazione),
#* <code>--user $(id -u):$(id -g)</code>: esegue il processo con uid:gid dell'utente sull'host,
+
#*<code>--user $(id -u):$(id -g)</code>: esegue il processo con uid:gid dell'utente sull'host,
#* <code>--cpus 32</code>: limita l'utilizzo a 32 CPU,
+
#*<code>--cpus 32</code>: limita l'utilizzo a 32 CPU,
#* <code>--gpus '"device=0,2"'</code>: rende la prima e la terza GPU visibili al container,
+
#*<code>--gpus '"device=0,2"'</code>: rende la prima e la terza GPU visibili al container,
#* <code>--volume $PWD:$PWD</code>: monta la cartella corrente nel container allo stesso path (qualsiasi modifica all'interno di questa cartella è condivisa tra host e container),
+
#*<code>--volume $PWD:$PWD</code>: monta la cartella corrente nel container allo stesso path (qualsiasi modifica all'interno di questa cartella è condivisa tra host e container),
#* <code>--workdir $PWD</code>: cambia la cartella di lavoro alla cartella corrente nel container,
+
#*<code>--workdir $PWD</code>: cambia la cartella di lavoro alla cartella corrente nel container,
#* <code><username>/my-project:latest</code>: utilizza questa immagine come base del container,
+
#*<code><username>/my-project:latest</code>: utilizza questa immagine come base del container,
#* <code>$@</code>: variabile bash che viene sostituita con tutti gli argomenti passati a questo script.
+
#*<code>$@</code>: variabile bash che viene sostituita con tutti gli argomenti passati a questo script.
# Preparo del codice da lanciare. Ad esempio, due script python:<syntaxhighlight lang="bash">
+
#Preparo del codice da lanciare. Ad esempio, due script python:<syntaxhighlight lang="bash">
 
# due script di esempio da lanciare
 
# due script di esempio da lanciare
 
cat << EOF > count_gpus.py
 
cat << EOF > count_gpus.py
Riga 153: Riga 184:
 
EOF
 
EOF
 
</syntaxhighlight>
 
</syntaxhighlight>
# Lancio dei job nei containers.<syntaxhighlight lang="bash">
+
#Lancio dei job nei containers.<syntaxhighlight lang="bash">
 
# mi assicuro che drun.sh sia eseguibile
 
# mi assicuro che drun.sh sia eseguibile
 
chmod +x drun.sh
 
chmod +x drun.sh
Riga 164: Riga 195:
 
./drun.sh bash
 
./drun.sh bash
 
</syntaxhighlight>
 
</syntaxhighlight>
# '''NB:''' con questa configurazione, ogni modifica fatta all'infuori della cartella corrente <code>~/raid/my-project</code> non verrà mantenuta alla chiusura del container. Nel caso serva cambiare l'ambiente (installare/rimuovere pacchetti o software, etc.) si suggerisce di cambiare il <code>Dockerfile</code> e rieseguire la creazione dell'immagine (punto 3).  Questo workflow ha il vantaggio di rendere più facilmente riproducibile la creazione dell'ambiente di sviluppo/lancio e robusto a incidenti (se erroneamente viene cancellata l'immagine docker che stavo usando, mi basta ricostruirla con un <code>docker build</code> a partire dal <code>Dockerfile</code>).
+
#'''NB:''' con questa configurazione, ogni modifica fatta all'infuori della cartella corrente <code>~/raid/my-project</code> non verrà mantenuta alla chiusura del container. Nel caso serva cambiare l'ambiente (installare/rimuovere pacchetti o software, etc.) si suggerisce di cambiare il <code>Dockerfile</code> e rieseguire la creazione dell'immagine (punto 3).  Questo workflow ha il vantaggio di rendere più facilmente riproducibile la creazione dell'ambiente di sviluppo/lancio e robusto a incidenti (se erroneamente viene cancellata l'immagine docker che stavo usando, mi basta ricostruirla con un <code>docker build</code> a partire dal <code>Dockerfile</code>).

Versione attuale delle 15:11, 28 mar 2023

DRAFT: Questa pagina è una bozza.

Guida per gli utenti del Cluster di calcolo e NVIDIA DGX in AI@Edge.

Architettura Cluster

AI@Edge mette a disposizione:


Cluster di Calcolo

E' costituito da:

  • Un nodo frontend;
  • Quattro nodi di calcolo identici;
  • Un nodo di storage.

Il nodo frontend ha le seguenti caratteristiche:

CPU: 1 x AMD EPYC 7352 (24 cores, 48 threads)

System memory: 128GB

Storage: 4HDD in RAID 5

   /           200GB

   /home       500GB (contiene le home degli utenti ed e' esportata via NFS sul frontend e sui nodi di calcolo)

   /opt/share  9.8TB (contiene software condiviso ed e' esportata via NFS sul frontend e sui nodi di calcolo)


Ciascun nodo di calcolo ha le seguenti caratteristiche:

CPU: 2 x AMD EPYC 7413 (48 cores, no HT)

System memory: 512GB

GPU: 1 x NVIDIA A100 GPU

Storage: 440GB


Il nodo di storage dispone di

   2 SSD in RAID1 per il sistema operativo;

   4 SSD in RAID5 5.2TB dedicati al folder /datafast (esportata via NFS sul frontend e sui nodi di calcolo)

   8 HDD in RAID5 63.7TB dedicati al folder /data (esportata via NFS sul frontend e sui nodi di calcolo)


  

TODO: 4 nodi con XX caratteristiche, frontend che con SLURM comanda sotto nodi, lista mountpoints/paths di interesse (dati e software)

NVIDIA DGX A100

TODO caratteristiche DGX, lista mountpoints e path di interesse

Richiesta Creazione Utente sul Cluster

TODO Chi può accedere al momento.

TODO elenco amministratori per laboratiorio. Contattare tizio, caio e fornire le seguenti info...

Accesso e Utilizzo Cluster di calcolo

Una volta ottenuto l'utente si accede al cluster tramite ssh tramite il comando:

TODO Si accede al frontend

ssh <username>@edge-mst1.isti.cnr.it

Verrà richiesta la password (il cursore del terminale non si muove quando si inserisce la password).

N.B.: Se si tratta del primo accesso è caldamente consigliato il cambio della password. Per farlo utilizzare il comando: passwd, verrà chiesto di inserire la password vecchia e, successivamente, la password nuova (due volte).

E' obbligatorio l'utilizzo di slurm per lanciare jobs sul cluster. La documentazione ufficiale e' disponibile ai seguenti link:
https://slurm.schedmd.com/documentation.html
https://slurm.schedmd.com/tutorials.html

A questo punto è possibile vedere le risorse disponibili sul cluster tramite il comando sinfo che ritornerà la lista delle partizioni, i rispettivi limiti di tempo e i relativi nodi associati. L'output del comando è il seguente:

PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
debug        up   infinite      4   idle gn[01-04]
short        up    1:30:00      1   idle gn01
long*        up 3-00:00:00      4   idle gn[01-04]

Come è possibile vedere, a disposizione dell'utente sono presenti due partizioni:

  • short: utilizzabile per job "brevi", un job lanciato su questa partizione verrà, infatti, chiuso dopo 1:30 ore dall'inizio del run;
  • long: utilizzabile per job più lunghi, ha un tempo limite di 3 giorni.

N.B.: Per le attività di calcolo, sempre utilizzare una di queste partizioni, mai svolgere operazioni di calcolo sul nodo di frontend.

Run di un job

Il run di job può avvenire secondo due modalità:

  • modalità interattiva;
  • modalità batch.

Modalità interattiva

Si può aprire una sessione interattiva di Bash con il seguente comando:

srun -n1 -p short --pty /bin/bash


Per un tutorial e alcuni esempi di utilizzo si può vedere la wiki: https://gitlab.com/w895/centro_calcolo_isti/-/wikis/home

Accesso e Utilizzo NVIDIA DGX A100

Si accede alla DGX via ssh con certificato preinstallato (nessuna password viene richiesta):

ssh <username>@edge-nd1.isti.cnr.it

È fortemente consigliato l'utilizzo di Docker (quiun tutorial) per creare l'ambiente con il software necessario e lanciare processi. Vedi la sezione Esempio di workflow per una guida di esempio all'utilizzo consigliato.


Si richiede:

  1. di taggare le proprie immagini docker con nomi nel formato <username>/<nome_immagine> (es: fabiocarrara/my-project:latest). Le immagini che non seguono questo standard possono essere cancellate periodicamente per recuperare spazio.
  2. di NON lanciare e tenere attivi job e/o servizi interattivi (es. jupyter notebooks, server http/flask, etc.). I processi che non seguono questo standard possono essere killati in qualsiasi momento.
  3. di aggiungere ad ogni invocazione di docker run le opzioni --user e --cpus come segue:
    docker run \
        ...
        --user $(id -u):$(id -g) \
        --cpus <X> \  # sostituire <X> con un numero di CPU consono al numero di GPU utilizzate
        ...
    
    L'opzione --user è necessaria per evitare che i processi girino come utente root. I processi che non seguono questo standard e girano come root possono essere killati in qualsiasi momento. L'opzione --cpus è fortemente consigliata per evitare di occupare erroneamente l'interezza delle CPU. Una euristica per specificare <X> è scegliere un valore compreso tra 8*nGPUs e 24*nGPUs dove nGPUs indica il numero di GPU richieste.

Esempio di workflow

  1. Creo una workdir per un nuovo progetto sui dischi non-SSD (dentro ~/raid/):
    mkdir ~/raid/my-project
    cd ~/raid/my-project
    
  2. Creo un file Dockerfile scegliendo un'immagine di partenza (FROM) e installando i miei requisiti software (RUN).
    cat << EOF > Dockerfile
    FROM nvcr.io/nvidia/pytorch:22.09-py3
    RUN pip install transformers
    EOF
    
  3. Costruisco la mia immagine:
    # sostituire <username> con il proprio nome utente
    docker build -t <username>/my-project:latest - < Dockerfile
    
  4. Creo uno script bash drun.sh per lanciare comandi dentro dei container nati dalla mia immagine. Questo è il contenuto di drun.sh:
    #!/bin/bash
    
    docker run \
        --interactive --tty \
        --rm \
        --user $(id -u):$(id -g) \
        --cpus 32 \
        --gpus '"device=0,2"' \
        --volume $PWD:$PWD \
        --workdir $PWD \
        <username>/my-project:latest \
        $@
    
    dove:
    • --interactive --tty: opzioni necessarie per processi interattivi (e.g., bash),
    • --rm: rimuove il container alla terminazione del processo (i container saranno effimeri, se ne creerà uno nuovo ad ogni invocazione),
    • --user $(id -u):$(id -g): esegue il processo con uid:gid dell'utente sull'host,
    • --cpus 32: limita l'utilizzo a 32 CPU,
    • --gpus '"device=0,2"': rende la prima e la terza GPU visibili al container,
    • --volume $PWD:$PWD: monta la cartella corrente nel container allo stesso path (qualsiasi modifica all'interno di questa cartella è condivisa tra host e container),
    • --workdir $PWD: cambia la cartella di lavoro alla cartella corrente nel container,
    • <username>/my-project:latest: utilizza questa immagine come base del container,
    • $@: variabile bash che viene sostituita con tutti gli argomenti passati a questo script.
  5. Preparo del codice da lanciare. Ad esempio, due script python:
    # due script di esempio da lanciare
    cat << EOF > count_gpus.py
    import torch
    num_of_gpus = torch.cuda.device_count()
    print(num_of_gpus)
    EOF
    
    cat << EOF > test.py
    import transformers
    print(transformers.__version__)
    EOF
    
  6. Lancio dei job nei containers.
    # mi assicuro che drun.sh sia eseguibile
    chmod +x drun.sh
    
    # lancio script python
    ./drun.sh python count_gpus.py
    ./drun.sh python test.py
    
    # lancio una bash nel container
    ./drun.sh bash
    
  7. NB: con questa configurazione, ogni modifica fatta all'infuori della cartella corrente ~/raid/my-project non verrà mantenuta alla chiusura del container. Nel caso serva cambiare l'ambiente (installare/rimuovere pacchetti o software, etc.) si suggerisce di cambiare il Dockerfile e rieseguire la creazione dell'immagine (punto 3). Questo workflow ha il vantaggio di rendere più facilmente riproducibile la creazione dell'ambiente di sviluppo/lancio e robusto a incidenti (se erroneamente viene cancellata l'immagine docker che stavo usando, mi basta ricostruirla con un docker build a partire dal Dockerfile).