⚛️ ☕ Quantum Espresso#
Quantum Espresso (QE) es un código DFT que implementa pseudopotenciales y ondas planas de manera eficiente para obtener la densidad electrónica de sistemas materiales y moleculares, que es muy usado por un buen número de usuarias/os en los clusters de UNC Supercómputo. El código está diseñado para correr de manera eficiente en infraestructuras HPC aprovechando los protocolos de paralelización MPI/OpenMP.
El software está disponible a través de modules.
Almacenamiento#
Los clusters cuentan con distintos sistemas para el almacenamiento de archivos. Es importante distinguir entre almacenamiento local y almacenamiento remoto.
Ver almacenamiento /home y /scratch.
Buenas prácticas en la gestión de datos#
Almacene archivos esenciales y de largo plazo en la partición home
Para tareas computacionales, copie los archivos de entrada necesarios al espacio scratch local al inicio de su trabajo y transfiera los archivos de salida de regreso a la partición home al finalizar. Este enfoque aprovecha las capacidades de alta velocidad del espacio scratch durante la computación, asegurando al mismo tiempo que los datos importantes se preserven en la partición home.
Monitoree y limpie regularmente los archivos en la partición home
Para liberar espacio y cumplir con las políticas del sistema respecto al uso de almacenamiento de datos ya que el espacio en la partición home es limitado. Se recomienda fuertemente borrar todos los archivos temporales que hayan sido generados por los códigos de cálculo y mantener sólo los archivos esenciales.
Archivos generados por QE#
El proceso de entrada/salida (I/O) de archivos en una corrida típica
de optimización de geometría (relax) con QE implica la creación y gestión
de varios archivos temporales y permanentes que contienen información esencial para la simulación.
A continuación, se detalla cómo QE maneja estos archivos durante una ejecución de pw.x en modo relax.
Variables clave#
outdir
Especifica el directorio donde QE almacena archivos temporales y de salida. Debe ser accesible para todos los procesos en ejecuciones paralelas. Por ejemplo:
&CONTROL outdir = '/scratch/$USER/qe_temp' ... /
Es recomendable que
outdirapunte a un sistema de archivos rápido y local al nodo de cómputo para mejorar el rendimiento de I/O. Recomendamos usar la variable del entornoESPRESSO_TMPDIRpara definir el directorio de almacenamiento de archivos en lugar de la variableoutdiren el input para QE.prefix
Define el prefijo utilizado para nombrar los archivos generados. Por ejemplo:
&CONTROL prefix = 'mi_simulacion' ... /
QE creará un subdirectorio llamado
mi_simulacion.save/dentro deoutdir, que contendrá los archivos necesarios para reiniciar o continuar la simulación.
Estructura de directorios#
Durante una corrida de pw.x en modo relax, QE genera varios archivos:
prefix.save/
Contiene información esencial de la simulación, como la densidad de carga, potenciales y funciones de onda. Este directorio es crucial para reiniciar simulaciones interrumpidas.
prefix.wfc*
Archivos binarios que almacenan las funciones de onda de los electrones.
prefix.igk*
Contienen información sobre los vectores de onda utilizados en la simulación.
prefix.dos, prefix.bands, etc.
Dependiendo de las opciones de salida seleccionadas, QE puede generar archivos adicionales con información sobre la densidad de estados, bandas electrónicas, entre otros.
Durante los cálculos realizados con pw.x,
cada ciclo scf genera un proceso de lectura/escritura que puede involucrar desde unos pocos cientos de MB hasta decenas de GB,
dependiendo del tamaño del sistema y de los parámetros utilizados.
En modos como relax, md o neb, este proceso se repite múltiples veces, ya que se ejecutan varios ciclos scf sucesivos.
Por este motivo, no se recomienda escribir los archivos temporales en el directorio /home,
ya que no está optimizado para operaciones intensivas de I/O.
Para mejorar el rendimiento, se aconseja redireccionar estos archivos a un directorio temporal en cada nodo de cálculo.
Ver también
Para ver un ejemplo de cómo implemetar esto, ver script de slurm.
Paralelismo#
Quantum Espresso implementa varias estrategias de paralelización, y entenderlas es de gran importancia para aprovechar al máximo un cluster de alto rendimiento. Todos los detalles sobre paralelismo en QE se pueden consultar en esta sección del manual. Resumimos aquí algunas ideas principales.
Estrategias comunes#
Las estrategias de paralelización más comúnmente utilizados son:
MPI («Message Passing Interface»):
Capa principal de paralelismo (estados electrónicos).
Distribuye los puntos-k y las funciones de onda entre los procesos (ranks).
OpenMP (multihilo):
Puede usarse para paralelizar bucles sobre grillas FFT, grillas en el espacio real y vectores-G.
Funciona mejor cuando se combina con MPI en una configuración híbrida.
Paralelismo por Grupos o «Pools» (
-npool):Útil cuando se tienen múltiples puntos-k.
Cada grupo maneja un subconjunto de puntos-k, muy eficiente para metales o sistemas grandes.
Paralelismo por Imágenes (
-nimage):Para cálculos NEB.
Distribuye cada imagen de la trayectoria a diferentes grupos de procesos.
Paralelismo en la Diagonalización (
-ndiag):Paraleliza la diagonalización de matrices para cada punto-k.
Particularmente importante para sistemas grandes con muchas bandas.
Funciona con ScaLAPACK o ELPA.
Grupos de Tareas (
-ntg):Menos utilizado.
Distribuye las FFT entre grupos para reducir el uso de memoria.
Guía rápida de parámetros#
Parámetro |
Descripción |
Cuándo Usarlo |
Ejemplo |
|---|---|---|---|
|
Paralelismo por puntos k. |
Sistemas con múltiples puntos k (metales, superceldas, grillas densas). |
|
|
Paralelismo por imágenes(NEB o caminos de reacción). |
Cálculos NEB. |
|
|
Paralelismo en la diagonalización. |
Sistemas grandes con muchas bandas (>100) o funcionales híbridos. |
|
|
Paralelismo por grupos de tareas. |
Grandes redes de FFT o cuando la memoria por núcleo es limitada. |
|
|
Paralelismo por bandas. |
Sistemas muy grandes con muchas bandas, especialmente con DFT híbrido. |
|
|
Multihilo OpenMP. |
Cuando se usa una combinación de MPI y OpenMP. |
|
|
Especifica el archivo de entrada (alternativo a |
Sintaxis alternativa opcional. |
|
Guía para elegir los parámetros#
Característica del sistema |
Estrategia Recomendada |
|---|---|
Pocos átomos, muchos puntos k |
Usar |
Muchos átomos, pocos puntos k |
Usar |
Cálculo NEB |
Usar |
Cálculo de fonones |
Usar |
Memoria limitada por núcleo |
Usar |
DFT híbrido o meta-GGA |
Usar |
Guía para encontrar el punto óptimo#
Para poder escoger los parámetros de paralelización de manera adecuada y juiciosa es absolutamente necesario realizar un estudio de benchmarking.
Paso a paso:
Seleccionar un sistema representativo
Elegir un sistema realista y representativo del sistema bajo estudio, por ejemplo:
Un sólido periódico con ~100 - 300 átomos
Un camino de NEB con ~6 - 8 imágenes
Un sistema de molécula + superficie con 1 - 4 puntos-k
Importante
Para todos los benchmarks, mantener fija la entrada: geometría, cutoffs, pseudopotenciales, etc.
Probar configuraciones paralelas distintas
Variar el número de
ranks MPI,hilos OpenMPy usar distintas combinaciones de-npool,-ndiag, etc.ID de prueba
Nodos
MPI por nodo
Hilos
Núcleos totales
Notas
A
1
32
2
64
MPI por socket + OpenMP
B
2
64
1
128
Todo MPI
C
4
32
2
256
Híbrido MPI + OpenMP
D
4
64
1
256
Todo MPI (nodos densos)
Probar diferentes combinaciones, como por ejemplo:
-npool 4,-ndiag 4,-nb 2-npool 8,-ndiag 8, sin paralelismo por bandasUsar
OMP_NUM_THREADSpara habilitar OpenMP
Medir tiempos y escalabilidad
Después de cada corrida, extraer del output:
El tiempo total transcurrido (wall time)
Las líneas de «CPU/Wall» informadas por QE para cada una de las rutinas (de ser necesario)
Ejemplo de salida
output.log#Parallel routines PAW routines PAW_pot : 8.70s CPU 12.33s WALL ( 204 calls) PWSCF : 3m43.66s CPU 5m11.34s WALL This run was terminated on: 10:55:31 24Apr2025 =------------------------------------------------------------------------------= JOB DONE. =------------------------------------------------------------------------------=
Para obtener el tiempo total de ejecución se puede usar:
$ grep "PWSCF.*WALL" output.log
O agregar al script:
time srun … pw.x …Calcular la eficiencia paralela
Usar un tiempo de referencia \(T_{ref}\) (por ejemplo, la corrida en 1 nodo) y calcular:
Aceleración (speedup):
\[S_p = \frac{T_{ref}}{T_p}\]Eficiencia:
\[E_p = \frac{S_p}{p}\]donde \(p\) es la cantidad de nodos (o núcleos totales).
Una eficiencia menor al 50 - 60 % indica sobreescalado: se están malgastando núcleos.
Identificar el punto óptimo
Graficar:
Tiempo de ejecución vs cantidad de núcleos
Eficiencia vs cantidad de núcleos
Buscar el «hombro de la curva», es decir el punto donde agregar más núcleos apenas mejora el tiempo. Este es el punto óptimo de paralelización.
Ejemplo: Si duplicar los núcleos de 128 a 256 sólo reduce el tiempo un 15 %, conviene quedarse en 128.
Buenas prácticas para usuarios (resumen)#
Situación |
Estrategia paralela recomendada |
|---|---|
Sistema con muchos puntos-k |
Aumentar |
Sistema con muchas bandas |
Usar |
NEB con muchas imágenes |
Usar |
Poca memoria por núcleo |
Usar |
Script de slurm#
A continuación un script de ejemplo para usar como template, que incluye algunas de las buenas practicas que ya fueron explicadas:
1#!/bin/bash
2#SBATCH --partition=multi
3#SBATCH --nodes=4
4#SBATCH --ntasks-per-node=64
5#SBATCH --cpus-per-task=1
6#SBATCH --time=0-1:00
7#SBATCH --exclusive
8#SBATCH --output=output.log
9#SBATCH --error=error.log
10
11# Load Quantum ESPRESSO
12module load quantum-espresso/7.2
13
14export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK
15
16echo "USER = $USER"
17echo "SLURM_JOB_ID = $SLURM_JOB_ID"
18echo "SLURMD_NODENAME = $SLURMD_NODENAME"
19echo "SLURM_NODELIST = $SLURM_NODELIST"
20echo "SLURM_NNODES = $SLURM_NNODES"
21
22# Define scratch and temporary directories
23export SCRATCH_DIR=/scratch/$USER/$SLURM_JOB_ID
24export TMP_DIR=./tmp
25
26# Create directory for temporary files in /home partition
27mkdir -p "$TMP_DIR"
28# Create directories for temporary files in each local node /scratch partition
29srun --ntasks=$SLURM_NNODES --ntasks-per-node=1 mkdir -p "$SCRATCH_DIR"
30
31# Copy previous run's temporary files to scratch directory
32srun --ntasks=$SLURM_NNODES --ntasks-per-node=1 rsync -a "$TMP_DIR/" "$SCRATCH_DIR/"
33
34# Define relevant QE environment variables
35# Location of pseudopotentials - Edit this line if necessary
36export ESPRESSO_PSEUDO=~/QE_PSP
37# Directory for temporary files - Do not edit this line!
38export ESPRESSO_TMPDIR="$SCRATCH_DIR"
39# NB: Do not use keywords pseudo_dir & outdir in QE input
40
41# Run QE
42srun --cpu_bind=cores pw.x -in pw_relax.inp >> pw_relax.out
43exit_status=$?
44if [ $exit_status -ne 0 ]; then
45 echo "pw.x exited with status $exit_status"
46 # Optionally perform additional error handling here
47fi
48
49# Synchronize files from scratch to home directory
50echo "Initiating sync at $(date)"
51srun --ntasks=$SLURM_NNODES --ntasks-per-node=1 rsync -a "$SCRATCH_DIR/" "$TMP_DIR/"
52if [ $? -ne 0 ]; then
53 echo "Warning: rsync operation failed."
54elif
55 echo "Sync completed."
56fi
En este ejemplo, se utilizan 4 nodos para lanzar un cálculo ejecutando pw.x.
En principio, lo único que sería necesario editar es:
La ruta a los pseudopotenciales (línea 36) se recomienda, tal como en el ejemplo, utilizar la variable de ambiente
ESPRESSO_PSEUDOen lugar de declarar la ruta en el inputNombres de los archivos input / output (línea 42)
El input que se utilice en este caso debe contener siguientes keywords en el módulo &CONTROL:
&CONTROL
calculation = 'relax' ,
restart_mode = 'restart' ,
max_seconds = 172000,
disk_io = 'low' ,
verbosity = 'high' ,
nstep = 50 ,
/
Como se puede ver que no se utilizan las keywords outdir ni pseudo_dir,
ya que ambos directorios vienen definidos en el script de slurm mediante las variables de ambiente ESPRESSO_TMPDIR y ESPRESSO_PSEUDO, respectivamente.
Por otro lado, es importante utilizar la keyword max_seconds para evitar que el cálculo exceda el tiempo límite de la cola de cálculo,
para que de este modo se escriban archivos temporales para un hacer un restart.
El restart_mode se pone directamente en restart, ya que en la nueva versión de QE no da error aunque el cálculo sea from_scratch.
De este modo, si es necesario realizar un restart,
solo basta volver a enviar el script a la cola sin realizar ninguna modificación, ni en el propio script ni el input.
Incluso, es posible lanzar los sucesivos cálculos en distinta cantidad de nodos de manera transparente.
Nota
Al ejecutar pw.x en modo scf, los archivos se escriben únicamente al finalizar el ciclo de autoconsistencia,
ya sea porque se alcanzó la convergencia (conv_thr),
se completó el número máximo de pasos (electron_maxstep)
o se agotó el tiempo máximo asignado al cálculo (max_seconds).
En cualquier caso, ocurre un único evento de escritura, por lo que este tipo de cálculos pueden realizarse de la manera habitual, es decir, utilizando la partición /home para almacenar los archivos temporales.
De todas formas, el script propuesto es igualmente compatible y se recomienda su uso para minimizar posibles errores.