MPI y OpenMP
Para los siguientes dos ejemplos con OpenMP usaremos el siguiente código en C++ prueba_openmp.cpp
.
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
void Hello(void); /* Thread function */
/*--------------------------------------------------------------------*/
int main(int argc, char* argv[]) {
int thread_count = strtol(argv[1], NULL, 10);
# pragma omp parallel num_threads(thread_count)
Hello();
return 0;
}
/* main */
/*-------------------------------------------------------------------
* * Function: Hello
* * Purpose: Thread function that prints message
* */
void Hello(void) {
int my_rank = omp_get_thread_num();
int thread_count = omp_get_num_threads();
printf("Hello from thread %d of %d\n", my_rank, thread_count); /* Hello */
}
Compilaremos el programa antes de crear y enviar el batch script.
module load gcc/5.5.0
g++ prueba_openmp.cpp -fopenmp -lpthread -o prueba_openmp
module unload gcc/5.5.0
OpenMP de un solo thread
- Crear el archivo
single_thread_openmp.sh
:
#!/bin/bash
# Nombre del job:
#SBATCH --job-name=single_thread_openmp
# Límite de tiempo de 10 min:
#SBATCH --time=10:00
./prueba_openmp
- Enviar a ejecutar el job:
sbatch single_thread_openmp.sh
OpenMP de múltiples threads
- Crear el archivo
multi_thread_openmp.sh
:
#!/bin/bash
# Nombre del job:
#SBATCH --job-name=multi_thread_omp_job
# Nombre del archivo de salida:
#SBATCH --output=multi_thread_omp_job.txt
# Numero de tasks:
#SBATCH --ntasks=1
# Numero de CPUs por task:
#SBATCH --cpus-per-task=4
# Límite de tiempo de 10 min:
#SBATCH --time=10:00
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK
./prueba_openmp
- Enviar a ejecutar el job:
sbatch multi_thread_openmp.sh
MPI multi-proceso
Para el siguiente ejemplo usaremos el código prueba_mpi.c
:
#include <mpi.h>
#include <stdio.h>
int main(int argc, char** argv) {
// Initialize the MPI environment
MPI_Init(NULL, NULL);
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
// Get the name of the processor
char processor_name[MPI_MAX_PROCESSOR_NAME];
int name_len;
MPI_Get_processor_name(processor_name, &name_len);
// Print off a hello world message
printf("Hello world from processor %s, rank %d out of %d processors\n",
processor_name, world_rank, world_size);
// Finalize the MPI environment.
MPI_Finalize();
}
- Compilar el programa mpi:
module load mpich/4.0
mpicc prueba_mpi.c -o prueba_mpi
module unload mpich/4.0
- Crear el archivo
multi_process_mpi.sh
:
#!/bin/bash
# Nombre del job:
#SBATCH -J prueba_mpi
# Nombre de la partición:
#SBATCH -p investigacion
# Número de nodos:
#SBATCH -N 2
# Número de tasks por nodo:
#SBATCH --tasks-per-node=3
# Carga del modulo MPICH 4.0
module load mpich/4.0
# Ejecución del compilado
mpirun prueba_mpi
# Descarga del módulo
module unload mpich/4.0
- Enviar a ejecutar el job:
sbatch multi_process_mpi.sh
MPI Y OpenMP a la vez (Híbrido)
Para este ejemplo usaremos el siguiente codigo hibrido y lo guardaremos en un archivo hibrido.c
.
#include <stdio.h>
#include <omp.h>
#include "mpi.h"
int main(int argc, char *argv[]) {
int numprocs, rank, namelen;
char processor_name[MPI_MAX_PROCESSOR_NAME];
int iam = 0, np = 1;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Get_processor_name(processor_name, &namelen);
#pragma omp parallel default(shared) private(iam, np)
{
np = omp_get_num_threads();
iam = omp_get_thread_num();
printf("Hello from thread %d out of %d from process %d out of %d on %s\n",
iam, np, rank, numprocs, processor_name);
}
MPI_Finalize();
}
- Compilar el programa híbrido:
module load mpich/4.0
mpicc -fopenmp hibrido.c -o hibrido
module unload mpich/4.0
- Crear el archivo
hibrido_mpi_openmp.sh
:
#!/bin/bash
# Un Job script para la ejecución de un código híbrido MPI-OpenMP
#SBATCH --job-name=hibrido_mpi_openmp
#SBATCH --output=hibrido_mpi_openmp.out
#SBATCH --ntasks=4
#SBATCH --cpus-per-task=8
#SBATCH --partition=docencia
# Cargar el modulo MPI.
module load mpich/4.0
# Configurar el valor de OMP_NUM_THREADS con el numero de CPUs por task solicitado.
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK
# Ejecutar el proceso con mpirun. Puede notar que no es necesario especificar el flag de MPI
# '-n' puesto que automaticamente utiliza el valor de la configuración de Slurm realizada
mpirun ./hibrido
module unload mpich/4.0
- Enviar a ejecutar el job:
sbatch hibrido_mpi_openmp.sh