Software de desarrollo instalado

El cluster lamb hace uso del sistema de Linux Environment Modules para organizar el software de desarollo instalado en el cluster para que los usuarios puedan compilar y ejecutar sus programas o modelos. Este herramienta llamada Modules permite generar un menú de software para que el usuario seleccione al momento algún paquete.

Uso de módulos

Con este sistema se puede modificar de forma dinámica el ambiente de la sesión del usuario, esto con la intención de facilitar el uso de las diferentes herramientas de desarrollo instaladas en lamb.

Note

Por defecto ningún módulo está cargado al iniciar una sesión en el cluster. Todo el software o bibliotecas necesarias para correr sus tareas, deben de ser explicitamente cargadas usando modules para que funcionen correctamente. Si se desea que se cargue un cierto paquete cada vez que se inicie sesión hay que agregar al archivo .bashrc la linea de module load paquete.

Compiladores Intel y GNU

En lamb se cuenta con los compiladores secuenciales y paralelos (MPI) de Intel y los compiladores secuenciales y paralelos (openmpi) de GNU.

intel-tools-2018
intel-tools-2019
oneapi2022
openmpi-4.1-gcc-7.5

Herramientas de CDF (CDFTOOLS,netcdf,cdo..)

Se pueden usar las bibliotecas instaladas HDF5, netcdf-c, netcdf-fortran, pnetcdf, cdo, nco, ncview; generadas con los compiladores paralelos de Intel y GNU. Mediante la invocación del mando module:

Para intel (solo usar una a la vez):

module load netcdfIntel2018
module load netcdfIntel2019
netcdfOneAPI2022

Para openmpi:

module load netcdfOpenMPI

Note

Recomendable usar las herramientas de desarrollo de Intel.

Miniforge3 (ipython,conda,mamba)

En lamb se encuentran instaladas la versiones 3.9.7 y 3.12.5 de python. Se recomienda el uso de la versión 3.12.5 y se habilita usando el mando: module load miniforge3.

Se tiene el siguiente código en python. interpol.py

import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from scipy import interpolate

x = np.linspace(0, 10, num=10, endpoint=True)
y = np.cos(-x**2/9.0)

f = interpolate.interp1d(x, y)
f2 = interpolate.interp1d(x, y, kind='cubic')
xnew = np.linspace(0, 10, num=200, endpoint=True)
tck = interpolate.splrep(x, y, s=0)
f3 = interpolate.splev(xnew, tck , der=0)

plt.plot(x, y, 'o', xnew, f(xnew), '-', xnew, f2(xnew), '--', xnew, f3)
plt.title('Intepolacion 1D - metodos')
plt.legend(['data', 'linear', 'cubic','Cubic Spline'], loc='best')
plt.savefig('interpol1D.png', dpi=250, format='png')

Preparamos el script para enviar la tarea al manejador de recursos, por ejemplo interpol.pbs

#!/bin/bash
#PBS -N interpol
#PBS -q intel
#PBS -o interpol.out
#PBS -e interpol.err
#PBS -l nodes=1

# Cambiarse al directorio donde se envio la tarea.
cd $PBS_O_WORKDIR
echo Inicio: `date` > tiempo.log
start=`date +%s`

module load miniforge3
python interpol.py

echo Final : `date` >> tiempo.log
end=`date +%s`
echo Tiempo ejecución : $((end-start)) seg. >> tiempo.log

Para ejecutar la tarea escribimos:

$ qsub interpol.pbs

El resultado de la operación correcta de ésta tarea debe producir dos archivos, una imagen png interpol1D.png y el archivo tiempo.log.

Si en caso de que se requiera ciertas versiones de paquetes y de otra versión del intérprete de python, que no coinciden con los instalados en el miniforge, se recomienda la creación personalizada y en su cuenta de un ambiente virtual de python.

Uso de ambientes virtuales

Un ambiente virtual es un ambiente personalizado de python con su propio intérprete, bibliotecas y scripts, generados a partir de otro entorno instalado de python. En el caso del cluster se tiene instalado python 3.12 y a partir de éste ambiente se pueden crear ambientes personalizados en su cuenta.

Crear un ambiente virtual en la linea de mandos

  1. Cargar el módulo de python miniforge3
$ module load miniforge3
  1. Crear el ambiente virtual.
$ conda create -n test-env python=3.8

Collecting package metadata (current_repodata.json): done
Solving environment: done

## Package Plan ##

   environment location: /home/judelga/.conda/envs/test-env

 added / updated specs:
  - python=3.8


The following packages will be downloaded:

package                    |            build
---------------------------|-----------------
_openmp_mutex-5.1          |            1_gnu          21 KB
ca-certificates-2023.05.30 |       h06a4308_0         120 KB
:
:
xz-5.4.2                   |       h5eee18b_0         642 KB
zlib-1.2.13                |       h5eee18b_0         103 KB
------------------------------------------------------------
                                       Total:        51.7 MB

The following NEW packages will be INSTALLED:

_libgcc_mutex      pkgs/main/linux-64::_libgcc_mutex-0.1-main
_openmp_mutex      pkgs/main/linux-64::_openmp_mutex-5.1-1_gnu
ca-certificates    pkgs/main/linux-64::ca-certificates-2023.05.30-h06a4308_0
ld_impl_linux-64   pkgs/main/linux-64::ld_impl_linux-64-2.38-h1181459_1
:
:
pip                pkgs/main/linux-64::pip-23.1.2-py38h06a4308_0
python             pkgs/main/linux-64::python-3.8.17-h955ad1f_0
readline           pkgs/main/linux-64::readline-8.2-h5eee18b_0
setuptools         pkgs/main/linux-64::setuptools-67.8.0-py38h06a4308_0
zlib               pkgs/main/linux-64::zlib-1.2.13-h5eee18b_0

Proceed ([y]/n)? y

Preparing transaction: done

Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use
#
#     $ conda activate test-env
#
# To deactivate an active environment, use
#
#     $ conda deactivate
  1. Activar el ambiente.
$ conda activate test-env

Y se muestra en el prompt el nombre del ambiente entre paréntesis:

(test-env)
  1. Verificar que haya sido creado el ambiente con:
$ conda env list

test-env              *  /home/judelga/.conda/envs/test-env


$ conda list

# packages in environment at /home/judelga/.conda/envs/test-env:
#
# Name                    Version                   Build  Channel
_libgcc_mutex             0.1                 conda_forge    conda-forge
_openmp_mutex             4.5                       2_gnu    conda-forge
bzip2                     1.0.8                hd590300_5    conda-forge
ca-certificates           2024.6.2             hbcca054_0    conda-forge
ld_impl_linux-64          2.40                 hf3520f5_2    conda-forge
libffi                    3.4.2                h7f98852_5    conda-forge
libgcc-ng                 13.2.0               h77fa898_7    conda-forge
libgomp                   13.2.0               h77fa898_7    conda-forge
libnsl                    2.0.1                hd590300_0    conda-forge
libsqlite                 3.45.3               h2797004_0    conda-forge
libuuid                   2.38.1               h0b41bf4_0    conda-forge
libxcrypt                 4.4.36               hd590300_1    conda-forge
libzlib                   1.3.1                h4ab18f5_1    conda-forge
ncurses                   6.5                  h59595ed_0    conda-forge
openssl                   3.3.1                h4ab18f5_0    conda-forge
pip                       24.0               pyhd8ed1ab_0    conda-forge
python                    3.8.19          hd12c33a_0_cpython    conda-forge
readline                  8.2                  h8228510_1    conda-forge
setuptools                70.0.0             pyhd8ed1ab_0    conda-forge
tk                        8.6.13          noxft_h4845f30_101    conda-forge
wheel                     0.43.0             pyhd8ed1ab_1    conda-forge
xz                        5.2.6                h166bdaf_0    conda-forge

Crear un ambiente virtual a partir de un archivo yaml

Un archivo .yml es un archivo de texto que contiene una lista de dependencias de paquetes que se instalarán dentro del ambiente virtual.

PASOS.

  1. Crear un archivo de configuración en formato yaml o bien usar algun archivo preexistente como environment.yml de algun paquete en python. Por ejemplo para el software GLMTools se requiere el siguiente ambiente de desarrollo.
name: glmval
channels:
- conda-forge
- defaults
dependencies:
- hdf5
- netcdf4
- numpy
- pandas
- pip
- pyclipper
- python=3.6
- scipy
- xarray
- pip:
  - git+https://github.com/deeplycloudy/lmatools.git
   - git+https://github.com/deeplycloudy/stormdrain.git

La primera linea del archivo yaml debe tener el nombre del nuevo ambiente. En este caso el ambiente se llamará glmval

  1. Se procede a crear el ambiente con:
$ conda env create -f environment.yml
  1. Verificar que haya sido creado el ambiente llamado glmval con:
$ conda env list


# conda environments:
#
base                     /opt/miniforge3
copernicusmarine         /opt/miniforge3/envs/copernicusmarine
glmval                   /home/judelga/.conda/envs/glmval
test-env              *  /home/judelga/.conda/envs/test-env

Mandos útiles de ambientes virtuales en python

  1. Para crear un ambiente virtual de python con algunos paquetes en especifico.
$ conda create -n myenv scipy numpy python=3.6

$ conda create --name myenv jupyterlab=3.2 matplotlib=3.5 numpy=1.21
  1. Para instalar un paquete en un ambiente virtual por ejemplo numba en myenv:
$ conda activate myenv

(myenv)$ conda install numba

## Package Plan ##

environment location: /home/computo/.conda/envs/myenv

added / updated specs:
  - numba

The following NEW packages will be INSTALLED:

 libllvm10          pkgs/main/linux-64::libllvm10-10.0.1-hbcb73fb_5
 llvmlite           pkgs/main/linux-64::llvmlite-0.36.0-py36h612dafd_4
 numba              pkgs/main/linux-64::numba-0.53.1-py36ha9443f7_0
 tbb                pkgs/main/linux-64::tbb-2020.3-hfd86e86_0
  1. Listar los ambientes instalados.
$ conda env list
  1. Listar los paquetes instalados de un ambiente virtual.
$ conda list -n myenv
  1. Activar un ambiente virtual de python.
$ conda activate test-env
  1. Desactivar el ambiente actual cargado.
(test-env) $ conda deactivate
  1. Borrar un ambiente virtual.
$ conda remove --name myenv --all

JupyterLab

Con Jupyter Notebook y JupyterLab se pueden ejecutar comandos de Python o Julia desde una interface web. Estos comandos se ejecutan en los recursos reservados de lamb, y se reciben los resultados numéricos o gráficos, embebidos en la misma interface web.

Jupyter Notebook v7.2.2 y JupyterLab v4.2.5 está disponibe a través de la carga del módulo miniforge3.

Pasos:

  1. Tomar un nodo de cómputo para ejecutar jupyter notebook, esto mediante la realización de un script PBS.

notebook-job.pbs

#!/bin/bash

#PBS -N notebook-job
#PBS -l nodes=1,walltime=01:00:00
#PBS -q intel
#PBS -o notebook-job.out
#PBS -e notebook-job.err

cd $PBS_O_WORKDIR

module load miniforge3

JUPYTERPORT=9999
echo "ssh -N -L $JUPYTERPORT:$(hostname):$JUPYTERPORT $USER@lamb.cicese.mx"
jupyter notebook --no-browser --ip=$(hostname) --port=$JUPYTERPORT --NotebookApp.token=''
  1. Enviar el script:
% qsub notebook-job.pbs
  1. Revisar el contenido del archivo notebook-job.out. En la primera linea de este archivo estará un comando de ssh que se necesita ejecutar en nuestro equipo local (PC, Laptop). El mando será algo como lo siguiente:
ssh -N -L 9999:node17:9999 miusuario@lamb.cicese.mx
  1. Copiar este mando y ejecutarlo en una sesión en el equipo local, ssh preguntará por su contraseña de acceso a lamb. Una vez escrita se puede abrir el navegador (firefox, chrome) y teclear http://localhost:9999 para ejecutar el dashboard o interface web de jupyter notebook, y con http://localhost:9999/lab se puede ingresar a JupyterLab.

Tambien se puede acceder a JupyterLab desde la sección View y Open JupyterLab de la interface de jupyter notebook.

_images/jupyterlab.png
  1. Una vez finalizado de usar el jupyter notebook o jupyterlab cerrar toda la conexión mediante el dashboard seleccionando Shut Down de la sección de File de cada interface o abortar la conexión ssh que se abrió en su equipo local y eliminar la tarea del PBS con qdel en lamb.

Mandos utiles de modules

 $ module avail
El cual listara los siguientes módulos definidos:

---------------------------- /usr/share/Modules/modulefiles -----------------------------
anaconda-python-3.9  debugger/latest      gcc-9.4.0            matlab-R2017b    netcdfOneAPI2022     seacasProject
cmake-3.18-gnu       dot                  gmt-6.2.0            matlab-R2023b        netcdfOpenMPI        tbb/2021.7.1
compiler/2022.2.1    dpl/2021.7.2         icc/2022.2.1         miniforge3           mpi/2021.7.1         textlive
compiler/latest      dpl/latest           icc/latest           mkl/2022.2.1         mpi/latest           oneapi2022
compiler-rt/2022.2.1 gcc-7.5.0            intel-tools-2018     mkl/latest           netcdfIntel2018      openmpi-4.1-gcc-7.5
debugger/2021.7.1    gcc-7.5.0-spack      intel-tools-2019     module-git           netcdfIntel2019      R-4.1.1
$ module load oneapi2022

$ module list
Listará los modulos que estan cargados incluyendo oneapi2022:

Currently Loaded Modulefiles:

1) miniforge3             3) icc/2022.2.1           5) mkl/2022.2.1           7) compiler/2022.2.1
2) compiler-rt/2022.2.1   4) tbb/2021.7.1           6) mpi/2021.7.1           8) oneapi2022
  $ module display oneapi2022
Muestra el contenido del módulo de MPI intel 2022


-------------------------------------------------------------------
/usr/share/Modules/modulefiles/oneapi2022:

module-whatis    Compilador intel 2021 (MPI+MKL)
conflict         intel-tools-2019
module           load icc/2022.2.1
module           load mkl/2022.2.1
module           load mpi/2021.7.1
module           load compiler/2022.2.1
module           load compiler-rt/2022.2.1
module           load tbb/2021.7.1
-------------------------------------------------------------------

Matlab

¿Que versión de matlab esta disponible?

En lamb se encuentra instalada la versión R2017b y R2023b de matlab, si se desea usar el matlab 2023b se tendra que cargar el módulo con:

$ module load matlab-R2023b

¿Como ejecuto MATLAB?

Warning

Hay que asegurarnos que ejecutar MATLAB en un nodo de cómputo y no en el nodo maestro lamb. Es posible asi utilizar todos los cores de un nodo sin ninguna configuración especial. (Aunque es posible definir desde qsub cuantos cores pretendemos utilizar).

Ejecutar MATLAB interactivamente:

Para ejecutar Matlab interactivamente, necesitamos crear una sesión interactiva en un nodo de cómputo. Para hacer esto en lamb solicitamos la sesión con 1 nodo de cómputo, con el siguiente comando:

$ qsub -X -I -l nodes=1,walltime=24:00 -q intel -d $PWD
  qsub: waiting for job 12788 to start
  qsub: job 12788 ready

$ _

Una vez que la sesión interactiva comience, podemos cargar los módulos apropiados y empezar Matlab como se describe a continuación:

$ module load matlab-R2023b
$ matlab -nodisplay -nosplash -r "miScript ; exit" < /dev/null > matrun.out 2> matrun.err

Este comando ejecutará los contenidos de miScript.m, enviando la salida de consola al archivo matrun.out y los mensajes de error a matrun.err.

También es posible tener una sesión interactiva de matlab, solo limitados en cuanto a la visualización de gráficos.

$ module load matlab-R2023b
$ matlab -nodisplay -nosplash
                   < M A T L A B (R) >
          Copyright 1984-2023 The MathWorks, Inc.
         R2023b (23.2.0.2365128) 64-bit (glnxa64)
                   August 23, 2023



  To get started, type one of these: helpwin, helpdesk, or demo.
  For product information, visit www.mathworks.com.
  >>

Ejecución de MATLAB por lotes (paralelo)

Se cuenta con licencias del toolbox Parallel Computing de matlab, con esto se puede paralelizar ciclos de matlab en varios cores de un nodo de procesamiento, se usan los llamados workers para lograr esto. Los workers son procesos de MATLAB que se ejecutan en segundo plano sin un escritorio gráfico.

Suponiendo que tenemos el siguiente código de matlab. Una función programada en stiffODEfun.m

function dy = stiffODEfun(t,y,c)
% This is a modified example from MATLAB's documentation at:
% http://www.mathworks.com/help/matlab/ref/ode15s.html
% The difference here is that the coefficient c is passed as an argument.
 dy = zeros(2,1);
 dy(1) = y(2);
 dy(2) = c*(1 - y(1)^2)*y(2) - y(1);
end

Y el programa principal de matlab stiffODE.m con un ciclo paralelizado con parfor

%{
 This script samples a parameter of a stiff ODE and solves it both in
 serial and parallel (via parfor), comparing both the run times and the
 max absolute values of the computed solutions. The code -- especially the
 serial part -- will take several minutes to run on Eagle.
%}

 % open the local cluster profile
%p = parcluster('local');

% open the parallel pool, recording the time it takes
time_pool = tic;
parpool(10);
time_pool = toc(time_pool);
fprintf('Opening the parallel pool took %g seconds.\n', time_pool)

% create vector of random coefficients on the interval [975,1050]
 nsamples = 100; % number of samples
coef = 975 + 50*rand(nsamples,1); % randomly generated coefficients

% compute solutions within serial loop
time_ser = tic;
y_ser = cell(nsamples,1); % cell to save the serial solutions
 for i = 1:nsamples
  if mod(i,10)==0
    fprintf('Serial for loop, i = %d\n', i);
  end
  [~,y_ser{i}] = ode15s(@(t,y) stiffODEfun(t,y,coef(i)) ,[0 10000],[2 0]);
 end
time_ser = toc(time_ser);

% compute solutions within parfor
time_parfor = tic;
y_par = cell(nsamples,1); % cell to save the parallel solutions
err = zeros(nsamples,1); % vector of errors between serial and parallel solutions
parfor i = 1:nsamples
  if mod(i,10)==0
    fprintf('Parfor loop, i = %d\n', i);
  end
  [~,y_par{i}] = ode15s(@(t,y) stiffODEfun(t,y,coef(i)) ,[0 10000],[2 0]);
  err(i) = norm(y_par{i}-y_ser{i}); % error between serial and parallel solutions
end
time_parfor = toc(time_parfor);
time_par = time_parfor;

% print results
fprintf('RESULTS\n\n')
fprintf('Serial time : %g\n', time_ser)
fprintf('Parfor time : %g\n', time_par)
fprintf('Speedup : %g\n\n', time_ser/time_par)
fprintf('Max error between serial and parallel solutions = %e\n', max(abs(err)))

% close the parallel pool
delete(gcp)
exit

Para ejecutarlo en uno de los nodos de procesamiento se necesita crear un script de PBS. En este caso estamos paralelizando el ciclo for de matlab con 10 workers, el script de PBS queda:

Ejemplo : worker.pbs

#!/bin/bash

## Directivas
#PBS -N worker
#PBS -p intel
#PBS -o worker.out
#PBS -e worker.err
#PBS -l nodes=1:ppn=10

# Cambiarse al directorio donde se envio la tarea.
cd $PBS_O_WORKDIR
module load matlab-R2023b
matlab -nosplash -nodisplay -nodesktop -r "stiffODE; exit;"

Para enviar la tarea al manejador de colas se ejecuta:

$ qsub worker.pbs

Se revisa el archivo worker.out una vez que termine la ejecución.

$ cat worker.out


Starting parallel pool (parpool) using the 'Processes' profile ...
Connected to parallel pool with 10 workers.
Opening the parallel pool took 15.5551 seconds.
Serial for loop, i = 10
Serial for loop, i = 20
Serial for loop, i = 30
Serial for loop, i = 40
Serial for loop, i = 50
Serial for loop, i = 60
Serial for loop, i = 70
Serial for loop, i = 80
Serial for loop, i = 90
Serial for loop, i = 100
Parfor loop, i = 50
Parfor loop, i = 10
Parfor loop, i = 30
Parfor loop, i = 20
Parfor loop, i = 70
Parfor loop, i = 40
Parfor loop, i = 80
Parfor loop, i = 60
Parfor loop, i = 90
Parfor loop, i = 100
RESULTS

Serial time : 3.66127
Parfor time : 1.32643
Speedup : 2.76024

Max error between serial and parallel solutions = 0.000000e+00
Parallel pool using the 'Processes' profile is shutting down.