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. .. code-block:: shell 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): .. code-block:: bash module load netcdfIntel2018 module load netcdfIntel2019 netcdfOneAPI2022 Para openmpi: .. code-block:: bash 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`` .. code-block:: python 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`` .. code-block:: bash #!/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: .. code-block:: shell $ 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`` .. code-block:: shell $ module load miniforge3 2. Crear el ambiente virtual. .. code-block:: shell $ 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 3. Activar el ambiente. .. code-block:: shell $ conda activate test-env Y se muestra en el prompt el nombre del ambiente entre paréntesis: *(test-env)* 4. Verificar que haya sido creado el ambiente con: .. code-block:: shell $ 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. .. code-block:: cfg 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** 2. Se procede a crear el ambiente con: .. code-block:: shell $ conda env create -f environment.yml 3. Verificar que haya sido creado el ambiente llamado ``glmval`` con: .. code-block:: shell $ 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. .. code-block:: shell $ conda create -n myenv scipy numpy python=3.6 $ conda create --name myenv jupyterlab=3.2 matplotlib=3.5 numpy=1.21 2. Para instalar un paquete en un ambiente virtual por ejemplo **numba** en **myenv**: .. code-block:: shell $ 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 3. Listar los ambientes instalados. .. code-block:: shell $ conda env list 4. Listar los paquetes instalados de un ambiente virtual. .. code-block:: shell $ conda list -n myenv 5. Activar un ambiente virtual de python. .. code-block:: shell $ conda activate test-env 6. Desactivar el ambiente actual cargado. .. code-block:: shell (test-env) $ conda deactivate 7. Borrar un ambiente virtual. .. code-block:: shell $ 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** .. code-block:: bash #!/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='' 2) Enviar el script: .. code-block:: bash % qsub notebook-job.pbs 3) 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: .. code-block:: bash ssh -N -L 9999:node17:9999 miusuario@lamb.cicese.mx 4) 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. .. image:: jupyterlab.png 5) 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 ^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: shell :emphasize-lines: 1 $ module avail | El cual listara los siguientes módulos definidos: | .. code-block:: shell ---------------------------- /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 .. code-block:: shell :emphasize-lines: 1 $ module load oneapi2022 $ module list | Listará los modulos que estan cargados incluyendo oneapi2022: | .. code-block:: shell 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 .. code-block:: shell :emphasize-lines: 1 $ module display oneapi2022 | Muestra el contenido del módulo de MPI intel 2022 | | .. code-block:: cfg ------------------------------------------------------------------- /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: .. code-block:: shell $ 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: .. code-block:: shell $ 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: .. code-block:: shell $ 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. .. code-block:: shell $ 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`` .. code-block:: matlab 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* .. code-block:: matlab %{ 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`` .. code-block:: bash #!/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: .. code-block:: shell $ qsub worker.pbs Se revisa el archivo ``worker.out`` una vez que termine la ejecución. .. code-block:: shell $ 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.