Para compilar con optimizaciones específicas de la arquitectura en un entorno de supercomputación heterogéneo como PROTEUS, donde coexisten nodos con diferentes generaciones de procesadores (Intel y AMD), existen dos metodologías: compilación nativa directa en el propio nodo de cálculo y compilación orientada a arquitectura desde el nodo de login.
Consideraciones al compilar en el nodo de login (Cabecera)
Un error frecuente en computación de alto rendimiento (HPC) es ejecutar el comando de compilación directamente tras iniciar sesión, empleando el flag -march=native.
El nodo de login (o cabecera) tiene una arquitectura de CPU distinta que la de los nodos de cálculo dedicados al cálculo (como Nix o Rodas). Si se utiliza -march=native en el nodo de login:
-
El compilador detectará la CPU del nodo de login y generará código optimizado exclusivamente para ella.
-
Al enviar el trabajo a un nodo de cálculo de última generación, el programa se ejecutará, pero no aprovechará las instrucciones vectoriales avanzadas (como AVX-512) del nodo de destino, resultando en una pérdida masiva de rendimiento.
-
Inversamente, si el nodo de login fuese más moderno que el de cálculo, el programa abortará inmediatamente con un fallo de tipo
Illegal Instruction.
Para evitar esto, el investigador debe optar por uno de los dos métodos siguientes:
Método 1: Compilación Nativa Directa (Vía Sesión Interactiva Slurm)
Este método consiste en reservar temporalmente un nodo de cálculo del tipo específico en el que se desea ejecutar la simulación, acceder a él de forma interactiva y compilar in situ utilizando la detección automática del hardware y compilar con el flag -march=native, el cual detectará y activará automáticamente todas las extensiones vectoriales (AVX-512, FMA, etc.) del hardware de forma transparente para el investigador.
Procedimiento:
-
Solicitar una sesión interactiva en la partición destino: Use el comando
srunde Slurm para obtener una shell interactiva en un nodo de la familia deseada (por ejemplo, nodos Nix con arquitectura AMD Zen 4):srun --partition=nix --tasks=1 --cpus-per-task=4 --time=00:30:00 --pty bash(Este comando le asignará 4 núcleos en un nodo de cálculo durante 30 minutos y abrirá una terminal directamente en dicha máquina).
-
Cargar el entorno de compilación: Una vez dentro del nodo de cálculo, cargue el compilador y las bibliotecas matemáticas necesarias:
module load gcc/15.1 -
Compilar con optimización nativa: Dado que ahora el compilador se está ejecutando en la CPU de destino final, el parámetro
-march=nativefuncionará de manera correcta y precisa:gcc -O3 -march=native -fopenmp mi_simulacion.c -o mi_simulacion.exe -lm -
Cerrar la sesión interactiva: Una vez generado el ejecutable, libere el nodo de cálculo para el resto de la comunidad científica:
exit
-
Ventajas: No requiere conocer el nombre técnico de la microarquitectura; el compilador realiza la detección y optimización de registros e instrucciones de forma automática y transparente.
-
Desventajas: Requiere esperar a que el gestor Slurm conceda el nodo interactivo si el clúster está bajo alta ocupación.
Alternativa: compilación integrada en el script de envío (sbatch)
Esta alternativa evita la sesión interactiva y la compilación manual. En su lugar, se insertan las directivas de carga de módulos y los comandos de compilación al inicio del propio submit script (fichero .sh).
Slurm recibirá el script, asignará el nodo de cálculo de la partición seleccionada y, antes de lanzar la simulación, compilará el código fuente de forma nativa.
Ejemplo:
#!/bin/bash
#SBATCH --job-name=fisica_compilacion_nativa
#SBATCH --partition=metis # Selección de la familia de nodos (ej. Intel Cascadelake)
#SBATCH --ntasks=1 # Número de tareas
#SBATCH --cpus-per-task=8 # Núcleos asignados (útil si la compilación o simulación usan OpenMP)
#SBATCH --time=04:00:00 # Tiempo total estimado (Compilación + Ejecución)
#SBATCH --output=simulacion_%j.log # Archivo de salida estructurado con el ID del trabajo
# ==============================================================================
# 1. CONFIGURACIÓN DEL ENTORNO
# ==============================================================================
# Limpiar entornos previos y cargar la suite de compilación requerida
module purge
module load gcc/15.1
# ==============================================================================
# 2. COMPILACIÓN NATIVA EN EL NODO ASIGNADO
# ==============================================================================
# Dado que este script se ejecuta dentro de un nodo de la partición 'metis',
# '-march=native' optimizará el binario específicamente para dicha arquitectura.
echo "Iniciando compilación nativa en el nodo: $SLURM_NODELIST"
gcc -O3 -march=native -fopenmp mi_simulacion.c -o mi_simulacion.exe -lm
# Control de errores: Si la compilación falla, abortar el trabajo inmediatamente
if [ $? -ne 0 ]; then
echo "ERROR: La compilación ha fallado. Abortando el trabajo Slurm." >&2
exit 1
fi
echo "Compilación completada con éxito. Iniciando simulación..."
# ==============================================================================
# 3. EJECUCIÓN DEL BINARIO ÓPTIMO
# ==============================================================================
# Configurar variables de paralelismo si aplica
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK
# Ejecutar el binario generado ad-hoc
./mi_simulacion.exe
echo "Trabajo finalizado correctamente."
-
Ventajas:
-
Garantía de optimización: Se elimina el riesgo humano de compilar en una arquitectura y ejecutar por error en otra diferente. Si el script se mueve a otro nodo (por ejemplo, de
nixarodas), el binario se recompilará automáticamente adaptándose a la nueva CPU sin modificar una sola línea del código. - Reproducibilidad científica: El script de envío actúa como un registro exacto del código fuente empleado, las bibliotecas cargadas y el compilador utilizado para obtener esos resultados de simulación concretos.
-
- Consideraciones:
-
Tiempo límite (
--time): Aunque es muy improbable, en aquellos casos en el que el tiempo de compilación sea muy elevado, se tiene que tener en cuenta a la hora de especificar el tiempo límite de ejecución. -
Gestión de ficheros: Se recomienda que el script verifique el código de salida de la compilación (mediante la variable
$?), tal como se muestra en el ejemplo. De lo contrario, si la compilación falla por un error de sintaxis, Slurm intentará ejecutar el binario antiguo (si existía previamente) o generará un fallo en cascada que entorpecerá la depuración. - Envíos masivos: Si se envía numerosas y simultáneas veces el mismo script, se corre el riesgo de condiciones de carrera sobre las versiones de los binarios en caso de trabajar en el mismo directorio.
-
B) Utilizando la suite Intel OneAPI (icx / icpx / ifx)
La suite de Intel cuenta con directivas de vectorización avanzadas adicionales. La versión actual de Intel OneAPI, basada en LLVM, admite la sintaxis -march= y las directivas -x. Se recomiendan estas últimas porque aseguran que el compilador inserte comprobaciones de CPU en el ejecutable.
| Partición / Nodo Destino | Fabricante | Flag Óptimo Intel (-x…) | Flag Alternativo LLVM (-march=) | Extensión Vectorial Máxima |
| Kratos / Apolo | Intel | -xSSE4.2 |
-march=westmere |
SSE4.2 |
| Hermes v1 | Intel | -xCORE-AVX2 |
-march=haswell |
AVX2 / FMA3 |
| Hermes v2 | Intel | -xCORE-AVX2 |
-march=broadwell |
AVX2 / FMA3 |
| Metis v1 | Intel | -xCORE-AVX512 |
-march=skylake-avx512 |
AVX-512 |
| Metis v2 | Intel | -xCASCADELAKE |
-march=cascadelake |
AVX-512 (con VNNI) |
| Nix / Orion / Perseo / Quimera | AMD | No recomendado ⚠️ | -march=znver4 |
AVX-512 / FMA3 |
| Rodas | AMD | No recomendado ⚠️ | -march=znver5 |
AVX-512 / FMA3 |
⚠️ Advertencia Crítica sobre el uso de -x en CPUs AMD (Nodos Nix, Orion, Rodas, etc.): Los flags de la familia -x (ej. -xCORE-AVX2 o -xCORE-AVX512) obligan al compilador a introducir un código de verificación de firma de CPU (CPU Dispatcher) en el ejecutable. Si un binario compilado con -x detecta en tiempo de ejecución que se está ejecutando sobre un procesador que no es de la marca GenuineIntel (como las CPUs AMD EPYC del clúster), el programa abortará inmediatamente con un mensaje de error o ignorará las extensiones vectoriales degradando drásticamente el rendimiento a instrucciones SSE básicas.
Para compilar códigos con la suite de Intel destinados a nodos AMD, utilice únicamente el flag -march=znver4 o -march=znver5.
Ventajas de las directivas -x en Nodos Intel
Al compilar de forma cruzada para nodos Intel (como las familias Hermes o Metis), se aconseja priorizar el uso de los flags específicos -xCORE-AVX512 o -xCASCADELAKE frente a -march. Esto permite al compilador de Intel activar de forma agresiva la SVML (Short Vector Math Library), una biblioteca matemática altamente optimizada que vectoriza funciones complejas comunes en física computacional (como sin(), exp(), log() o sqrt()), logrando rendimientos muy superiores a la biblioteca estándar de GNU (libm).
Método 2: Compilación Cruzada desde el Nodo de Login
Este método permite al investigador compilar inmediatamente desde el nodo de login, sin necesidad de acceder a los nodos de cálculo. Para ello, se prescinde de -march=native y se instruye explícitamente al compilador sobre qué arquitectura debe emular para la generación del binario.
-
Ventajas: Inmediata, no es necesario crear una sesión interactiva. Permite generar múltiples binarios para distintas arquitecturas en una sola sesión de trabajo.
-
Desventajas: Exige que el usuario conozca con precisión la microarquitectura del nodo donde correrá el trabajo y que el compilador del sistema sea lo suficientemente reciente como para reconocer dicho parámetro.
Sintaxis según el compilador y nodo de destino:
Para compilar desde el nodo de login apuntando a las diferentes particiones de PROTEUS, aplique los siguientes flags específicos:
A) Utilizando GCC o LLVM/Clang (Versiones modernas)
Para mayor agilidad, se presenta la tabla de correspondencias técnicas necesarias para la configuración de las directivas en sus Makefiles o scripts de entorno:
| Partición / Nodo Destino | Fabricante | Flag Común –march= |
Versión Mínima GCC | Versión Mínima LLVM | Extensión Vectorial Máxima |
| Kratos / Apolo | Intel | westmere |
11.5 (Sistema) | 14.0.6 (Cargar) | SSE4.2 |
| Hermes v1 | Intel | haswell |
11.5 (Sistema) | 14.0.6 (Cargar) | AVX2 / FMA3 |
| Hermes v2 | Intel | broadwell |
11.5 (Sistema) | 14.0.6 (Cargar) | AVX2 / FMA3 |
| Metis v1 | Intel | skylake-avx512 |
11.5 (Sistema) | 14.0.6 (Cargar) | AVX-512 |
| Metis v2 | Intel | cascadelake |
11.5 (Sistema) | 14.0.6 (Cargar) | AVX-512 |
| Nix / Orion / Perseo / Quimera | AMD | znver4 |
13.1 (Cargar 15.1) | 16.0 (Cargar v20.1.6) | AVX-512 / FMA3 |
| Rodas | AMD | znver5 |
14.1 (Cargar 15.1) | 19.0 (Cargar v20.1.6) | AVX-512 / FMA3 |
Nota: Las versión base de GCC del sistema (11.5) cubre perfectamente todo el parque de nodos Intel. Para la infraestructura moderna de AMD (nodos Nix, Orion, Perseo, Quimera o Rodas), es imperativo que cargue la versión más moderna de GCC (15.1 de LLVM mediante el administrador de entornos (module load llvm/20.1.6), ya que LLVM 14 carece de los modelos de coste de pipeline y del repertorio de instrucciones necesarios para estas arquitecturas.
C) Utilizando la suite AOCC (clang / clang++ / flang)
Para la suite AOCC 5.0.0 (AMD Optimizing C/C++ Compiler), la estrategia de optimización cambia de enfoque. AOCC es un entorno de compilación de alto rendimiento desarrollado por AMD, basado en la infraestructura de código abierto LLVM, pero que incorpora pases de optimización heurística, vectorización agresiva y generación de código altamente refinados para la microarquitectura de procesadores AMD EPYC.
Los comandos de la suite de AOCC son clang (para C), clang++ (para C++) y flang (para Fortran). Al estar basado en LLVM, comparte flags estandarizados, pero su modelo de coste está estrictamente diseñado para exprimir el hardware AMD.
A continuación, se presenta la tabla equivalente para la suite AOCC de PROTEUS:
| Partición / Nodo Destino | Fabricante | Flag Recomendado AOCC | Estado de Soporte / Rendimiento | Extensión Vectorial Máxima |
| Kratos / Apolo | Intel | -march=westmere |
No recomendado (Subóptimo) | SSE4.2 |
| Hermes v1 | Intel | -march=haswell |
No recomendado (Subóptimo) | AVX2 / FMA3 |
| Hermes v2 | Intel | -march=broadwell |
No recomendado (Subóptimo) | AVX2 / FMA3 |
| Metis v1 | Intel | -march=skylake-avx512 |
No recomendado (Subóptimo) | AVX-512 |
| Metis v2 | Intel | -march=cascadelake |
No recomendado (Subóptimo) | AVX-512 |
| Nix / Orion / Perseo / Quimera | AMD | -march=znver4 |
Óptimo (Rendimiento Máximo) | AVX-512 / FMA3 |
| Rodas | AMD | -march=znver5 |
Óptimo (Rendimiento Máximo) | AVX-512 / FMA3 |
⚠️ Uso de AOCC en Arquitecturas Intel:
Dado que el núcleo de AOCC es LLVM, el compilador puede generar binarios funcionales para procesadores Intel utilizando los flags de arquitectura correspondientes (v.g., -march=cascadelake). Sin embargo, las optimizaciones de bajo nivel del pipeline, la vectorización de bucles y la gestión del mapa de cachés de AOCC están parametrizadas específicamente para los núcleos Zen de AMD. Compilar códigos para nodos Intel con AOCC resultará en un rendimiento inferior al obtenido con GCC o Intel OneAPI.
Utilice AOCC exclusivamente cuando el destino de sus simulaciones físicas sean nodos AMD (nodos Nix, Orion, Perseo, Quimera o Rodas).
Interacción con Bibliotecas Científicas (AOCL)
Para maximizar la eficiencia con AOCC, se recomienda enlazar de manera nativa con las AOCL (AMD Optimizing CPU Libraries), que incluyen versiones optimizadas de BLAS (BLIS), LAPACK (FLAME) y FFTW. Estas bibliotecas se acoplan perfectamente con los pases de vectorización avanzada de AOCC 5.0.0, especialmente al procesar grandes volúmenes de tensores o matrices distribuidas en los nodos Rodas (Zen 5).