Ús de GPU

Introducció

En aquest exemple, explorarem com enviar a Multivac un programa usant la GPU per a fer una xarxa neuronal.

Actualment només la partició de robòtica té gpu i la màquina sputnik. A l’script de configuració s’ha de tenir en compte que hem d’utilitzar tota la màquina i no és multiusuari, ja que no es pot compartir una gpu amb aquestes característiques.

Crearem un arxiu per exemple anomenat test_gpu.py amb finalitats demostratives.

Codi d’exemple

import tensorflow as tf
from tensorflow.keras import layers, models, datasets

# Requereix fer un pip install tensorflow[and-cuda]==2.15.1

# Volem utilitzar GPU?
volem_usar_gpu = True

# Si no volem usar la GPU, activem que faci la xarxa amb CPU
if not volem_usar_gpu:
    tf.config.set_visible_devices([], 'GPU')

# Verificar i configurar les GPUS disponibles
gpus = tf.config.list_physical_devices('GPU')

print(gpus)
if gpus:
    try:
        # Configurem l'ús de memòria incremental
        for gpu in gpus:
            tf.config.experimental.set_memory_growth(gpu, True)
        print("Les GPUS estan configurades per a l'ús de memòria incremental.")
    except RuntimeError as e:
        print(e)
else:
    print("No s'ha detectat cap GPU, s'utilitzarà la CPU.")

# Carregar i preparar el dataset MNIST
(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()
train_images = train_images[..., tf.newaxis] / 255.0  # Afegir un canal per a les imatges en escala de grisos
test_images = test_images[..., tf.newaxis] / 255.0

# Definir l'arquitectura del model
model = models.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),  # Primera capa convolucional
    layers.MaxPooling2D((2, 2)),  # Primera capa d'agrupament
    layers.Conv2D(64, (3, 3), activation='relu'),  # Segona capa convolucional
    layers.MaxPooling2D((2, 2)),  # Segona capa d'agrupament
    layers.Conv2D(64, (3, 3), activation='relu'),  # Tercera capa convolucional
    layers.Flatten(),  # Aplanar les característiques
    layers.Dense(64, activation='relu'),  # Capa oculta amb 64 neurones i activació ReLU
    layers.Dense(10)  # Capa de sortida amb 10 neurones (una per a cada classe), sense activació
])

# Compilar el model
model.compile(optimizer='adam',
            loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
            metrics=['accuracy'])

# Entrenar el model
history = model.fit(train_images, train_labels, epochs=10, validation_data=(test_images, test_labels))

# Avaluar el model
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print(f'Precisió en el conjunt de prova: {test_acc}')

Execució

Crearem un virtual environment de python anomenat per exemple venv. Aquest pas només és necessari fer la primera vegada que es vol crear el venv, les altres vegades es pot reusar el mateix. Es requereix instal·lar el paquet tensorflow: pip install tensorflow[and-cuda]==2.15.1

$ python3 -m venv venv
$ source venv/bin/activate
$ pip install tensorflow[and-cuda]==2.15.1
$ deactivate

Crearem un document amb els parametres de configuració, per exemple: test_gpu.slurm` que conté la configuració d’execució per a aquest script de gpu.

VERSION=1.3
JOB_NAME=test_gpu
NAME_OUTPUT=out
PARTITION=robotica
N_TASKS=1
CPUS_PER_TASK=16
MAIL_TYPE=END,FAIL
MAIL_USER=nom.usuari@upc.edu
MEMORY=15000M
BEGIN=now
TIME_LIMIT=23:59:59 # En aquest exemple tenim un límit de 24h
LOG_OUTPUT=log
FORCED_NODES=sputnik #Molt important forçar aquest node
EXCLUDED_NODES=
ROUTE=~/tests/gpu_example
COMMANDS=(

    "hostname" #Per a saber a quina màquina s'ha executat
    "source $ROUTE/venv/bin/activate"
    "python3 $ROUTE/test_gpu.py"
    "deactivate"
)

Aquest script el llançarem des de iocex usant la següent comanda:

multivac test_gpu.slurm

El resultat del nostre programa un cop finalitzada l’execució serà visible al mateix directori a on hem fet l’execució.