GPU tesla k40m¶
El cluster lamb cuenta con 4 nodos (n1,n2,n3,n4) que tienen una tarjeta NVIDIA Tesla K40m. Esta tarjeta tiene 2880 CUDA cores y memoria RAM GDDR5 de 12 GB. Tiene un nivel de computo de 3.5 (capacidad de CUDA)
Para obtener información de la tarjeta GPU y ver que procesos estan corriendo en la GPU:
$ ssh -X n1
$ nvidia-smi
Tensorflow¶
TensorFlow es una biblioteca de código abierto que permite crear modelos de aprendizaje automático (ML) con Python.
Instalación de tensorflow¶
La versión a instalar es tensorflow 2.4.1
- Ingresar a uno de los nodos de lamb que tiene una tarjeta de GPU.
$ ssh n1
- Cargar el módulo de miniforge3
$ module load miniforge3
- Crear un ambiente virtual de python, en este caso se llamara tensorflow y que tenga python 3.8
$ conda create -n tensorflow python=3.8
- Activar el ambiente.
$ conda activate tensorflow
- Instalar los siguientes paquetes.
# Se instala por defecto cudatoolkit 11.0.221
$ conda install cudnn==8.0.5.39
# Es importante hacerlo con pip
$ pip install tensorflow-gpu==2.4.1
Prueba de tensorflow¶
$ python
>>> import tensorflow as tf
>>> tf.config.list_physical_devices('GPU')
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]
>>> from tensorflow.python.client import device_lib
>>> device_lib.list_local_devices()
[name: "/device:CPU:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: 4231884091369338600
, name: "/device:GPU:0"
device_type: "GPU"
memory_limit: 11132368320
locality {
bus_id: 1
links {
}
}
Usando PBS+tensorflow¶
Se usará éste ejemplo de python con tensorflow:
test-tensorflow.py
from __future__ import print_function
'''
Basic Multi GPU computation example using TensorFlow library.
Author: Aymeric Damien
Project: https://github.com/aymericdamien/TensorFlow-Examples/
'''
'''
This tutorial requires your machine to have 1 GPU
"/cpu:0": The CPU of your machine.
"/gpu:0": The first GPU of your machine
'''
import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='3'
import numpy as np
import datetime
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
# Processing Units logs
log_device_placement = True
# Num of multiplications to perform
n = 10
'''
Example: compute A^n + B^n on 2 GPUs
Results on 8 cores with 2 GTX-980:
* Single GPU computation time: 0:00:11.277449
* Multi GPU computation time: 0:00:07.131701
'''
# Create random large matrix
A = np.random.rand(10000, 10000).astype('float32')
B = np.random.rand(10000, 10000).astype('float32')
# Create a graph to store results
c1 = []
c2 = []
def matpow(M, n):
if n < 1: #Abstract cases where n < 1
return M
else:
return tf.matmul(M, matpow(M, n-1))
'''
Single GPU computing
'''
with tf.device('/gpu:0'):
a = tf.placeholder(tf.float32, [10000, 10000])
b = tf.placeholder(tf.float32, [10000, 10000])
# Compute A^n and B^n and store results in c1
c1.append(matpow(a, n))
c1.append(matpow(b, n))
with tf.device('/cpu:0'):
sum = tf.add_n(c1) #Addition of all elements in c1, i.e. A^n + B^n
t1_1 = datetime.datetime.now()
with tf.Session(config=tf.ConfigProto(log_device_placement=log_device_placement)) as sess:
# Run the op.
sess.run(sum, {a:A, b:B})
t2_1 = datetime.datetime.now()
print("Single GPU computation time: " + str(t2_1-t1_1))
Se crea el script de PBS y haciendo referencia a la cola gpu
que es la que contiene los 4 nodos que tienen tarjeta Tesla K40m
tensorflow.pbs
#!/bin/bash
#PBS -N tensorflow
#PBS -q gpu
#PBS -l nodes=1
#PBS -o tensorflow.out
#PBS -e tensorflow.err
module load miniforge3
source activate base
conda activate tensorflow
cd $PBS_O_WORKDIR
python test_tensorflow.py
Se envía el script:
$ qsub tensorflow.pbs
Y se revisa la salida del archivo tensorflow.out
:
$ cat tensorflow.out
Single GPU computation time: 0:00:21.743607
MatMul: (MatMul): /job:localhost/replica:0/task:0/device:GPU:0
MatMul_1: (MatMul): /job:localhost/replica:0/task:0/device:GPU:0
:
:
Pytorch¶
PyTorch es un marco de aprendizaje profundo de código abierto basado en software que se emplea para crear redes neuronales, combinando la biblioteca de aprendizaje automático(ML) de Torch con una API de alto nivel basada en Python
Instalación de pytorch¶
La versión a instalar es pytorch 2.7.0
- Ingresar a uno de los nodos de lamb que tiene una tarjeta de GPU.
$ ssh n1
- Cargar los siguientes módulos
$ module purge
$ module load miniforge3
$ module load cuda-11.8
$ module load gcc-9.4.0
- Descargar los fuentes de pytorch
$ git clone --recursive https://github.com/pytorch/pytorch
$ cd pytorch
- Con un editor de texto, crear un ambiente virtual a partir del siguiente archivo yaml (
pytorch.yaml
) com python 3.9 Modificar nombre del ambiente si se desea.
name: pytorch
channels:
- pytorch
- conda-forge
dependencies:
- _libgcc_mutex=0.1=conda_forge
- _openmp_mutex=4.5=2_gnu
- bzip2=1.0.8=h4bc722e_7
- c-ares=1.34.4=hb9d3cd8_0
- ca-certificates=2025.1.31=hbcca054_0
- keyutils=1.6.1=h166bdaf_0
- krb5=1.21.3=h659f571_0
- ld_impl_linux-64=2.43=h712a8e2_4
- libcurl=8.12.1=h332b0f4_0
- libedit=3.1.20250104=pl5321h7949ede_0
- libev=4.33=hd590300_2
- libexpat=2.6.4=h5888daf_0
- libffi=3.4.6=h2dba641_0
- libgcc=14.2.0=h767d61c_2
- libgcc-ng=14.2.0=h69a702a_2
- libgomp=14.2.0=h767d61c_2
- liblzma=5.6.4=hb9d3cd8_0
- libnghttp2=1.64.0=h161d5f1_0
- libnsl=2.0.1=hd590300_0
- libsqlite=3.49.1=hee588c1_1
- libssh2=1.11.1=hf672d98_0
- libstdcxx=14.2.0=h8f9b012_2
- libstdcxx-ng=14.2.0=h4852527_2
- libuuid=2.38.1=h0b41bf4_0
- libuv=1.50.0=hb9d3cd8_0
- libxcrypt=4.4.36=hd590300_1
- libzlib=1.3.1=hb9d3cd8_2
- magma-cuda118=2.6.1=1
- ncurses=6.5=h2d0b736_3
- nvtx=0.2.11=py39h8cd3c5a_0
- openssl=3.4.1=h7b32b05_0
- pip=25.0.1=pyh8b19718_0
- python=3.9.21=h9c0c6dc_1_cpython
- python_abi=3.9=5_cp39
- pyyaml=6.0.2=py39h9399b63_2
- readline=8.2=h8c095d6_2
- rhash=1.4.5=hb9d3cd8_0
- setuptools=75.8.0=pyhff2d567_0
- tk=8.6.13=noxft_h4845f30_101
- tzdata=2025a=h78e105d_0
- wheel=0.45.1=pyhd8ed1ab_1
- yaml=0.2.5=h7f98852_2
- zstd=1.5.7=hb8e6e7a_1
- pip:
- astunparse==1.6.3
- attrs==25.1.0
- certifi==2025.1.31
- charset-normalizer==3.4.1
- cmake==3.31.4
- exceptiongroup==1.2.2
- expecttest==0.3.0
- filelock==3.17.0
- fsspec==2025.2.0
- hypothesis==6.127.2
- idna==3.10
- intel-cmplr-lib-ur==2024.2.1
- intel-openmp==2024.2.1
- jinja2==3.1.5
- lintrunner==0.12.7
- markupsafe==3.0.2
- mkl-include==2024.2.2
- mkl-static==2024.2.2
- mpmath==1.3.0
- networkx==3.2.1
- ninja==1.11.1.3
- numpy==2.0.2
- optree==0.14.0
- packaging==24.2
- psutil==7.0.0
- requests==2.32.3
- six==1.17.0
- sortedcontainers==2.4.0
- sympy==1.13.3
- tbb==2021.13.1
- types-dataclasses==0.6.6
- typing-extensions==4.12.2
- urllib3==2.3.0
- Crear el ambiente virtual ejecutando:
$ conda env create -f pytorch.yaml
- Activar el ambiente de pytorch
$ conda activate pytorch
- Definir las siguientes variables ambientales.
$ export USE_XPU=0
$ export USE_XNNPACK=0
$ export CMAKE_PREFIX_PATH="${CONDA_PREFIX:-'$(dirname $(which conda))/../'}:${CMAKE_PREFIX_PATH}"
- Estando en el directorio de pytorch agregar al archivo
CMakeLists.txt
lo siguiente (linea 89):
set(CUDA_HOME /opt/cuda)
set(CUDATOOLKIT_ROOT /opt/cuda-11.8)
set(CUDATOOLKIT_INCLUDE_DIRS /opt/cuda-11.8/include)
set(CMAKE_CUDA_COMPILER /opt/cuda/bin/nvcc)
set(CMAKE_THREAD_LIBS_INIT "-lpthread")
set(CMAKE_HAVE_THREADS_LIBRARY 1)
set(CMAKE_USE_WIN32_THREADS_INIT 0)
set(CMAKE_USE_PTHREADS_INIT 1)
set(THREADS_PREFER_PTHREAD_FLAG ON)
- Compilar e instalar pytorch
# Ejecutar un "clean" cada vez que se soluciona algun errror en la compilacion
$ python setup.py clean
# Compilacion dura como 45 minutos
$ python setup.py develop >& setupPytorch.out &
- Probar pytorch
$ conda list |grep torch
$ python -c 'import torch; print(torch.cuda.is_available());'
True <-- debe de aparecer
- Instalar torchvision
$ conda install torchvision==0.19.1=cuda118py39he2f9dfe_1
Usando PBS+pytorch¶
Ejecutando este ejemplo en un solo nodo con un solo gpu.
- Primero el programa en python que usa pytorch y cuda (
polynomial.py
).
import torch
import math
class LegendrePolynomial3(torch.autograd.Function):
"""
We can implement our own custom autograd Functions by subclassing
torch.autograd.Function and implementing the forward and backward passes
which operate on Tensors.
"""
@staticmethod
def forward(ctx, input):
"""
In the forward pass we receive a Tensor containing the input and return
a Tensor containing the output. ctx is a context object that can be used
to stash information for backward computation. You can cache arbitrary
objects for use in the backward pass using the ctx.save_for_backward method.
"""
ctx.save_for_backward(input)
return 0.5 * (5 * input ** 3 - 3 * input)
@staticmethod
def backward(ctx, grad_output):
"""
In the backward pass we receive a Tensor containing the gradient of the loss
with respect to the output, and we need to compute the gradient of the loss
with respect to the input.
"""
input, = ctx.saved_tensors
return grad_output * 1.5 * (5 * input ** 2 - 1)
dtype = torch.float
#device = torch.device("cpu")
device = torch.device("cuda:0") # Uncomment this to run on GPU
# Create Tensors to hold input and outputs.
# By default, requires_grad=False, which indicates that we do not need to
# compute gradients with respect to these Tensors during the backward pass.
x = torch.linspace(-math.pi, math.pi, 2000, device=device, dtype=dtype)
y = torch.sin(x)
# Create random Tensors for weights. For this example, we need
# 4 weights: y = a + b * P3(c + d * x), these weights need to be initialized
# not too far from the correct result to ensure convergence.
# Setting requires_grad=True indicates that we want to compute gradients with
# respect to these Tensors during the backward pass.
a = torch.full((), 0.0, device=device, dtype=dtype, requires_grad=True)
b = torch.full((), -1.0, device=device, dtype=dtype, requires_grad=True)
c = torch.full((), 0.0, device=device, dtype=dtype, requires_grad=True)
d = torch.full((), 0.3, device=device, dtype=dtype, requires_grad=True)
learning_rate = 5e-6
for t in range(2000):
# To apply our Function, we use Function.apply method. We alias this as 'P3'.
P3 = LegendrePolynomial3.apply
# Forward pass: compute predicted y using operations; we compute
# P3 using our custom autograd operation.
y_pred = a + b * P3(c + d * x)
# Compute and print loss
loss = (y_pred - y).pow(2).sum()
if t % 100 == 99:
print(t, loss.item())
# Use autograd to compute the backward pass.
loss.backward()
# Update weights using gradient descent
with torch.no_grad():
a -= learning_rate * a.grad
b -= learning_rate * b.grad
c -= learning_rate * c.grad
d -= learning_rate * d.grad
# Manually zero the gradients after updating weights
a.grad = None
b.grad = None
c.grad = None
d.grad = None
print(f'Result: y = {a.item()} + {b.item()} * P3({c.item()} + {d.item()} x)')
- Se crea el script de PBS (
pytorch.pbs
)
#!/bin/bash
#PBS -N pytorch
#PBS -q gpu
#PBS -l nodes=1
#PBS -o pytorch.out
#PBS -e pytorch.err
module purge
module load miniforge3
module load cuda-11.8
module load gcc-9.4.0
source activate base
conda activate pytorch
cd $PBS_O_WORKDIR
python polynomial.py
- Se envia el script
$ qsub pytorch.pbs
- Ejecutando el mando
nvidia-smi
en el nodo asignado se puede verificar que esta corriendo en un GPU.
$ ssh n1
$ nvidia-smi
- La salida se puede ver en el archivo
pytorch.out
:
$ more pytorch.out