1. Indice de pagina
  2. 1. Objetivos
  3. 2. Explicación
  4. 2.1. Código Inicio
  5. 2.2. Ejercicios propuestos
  6. 2.3. Funciones necesarias
  7. 3. Solución
  8. 3.1. Apartado A
  9. 3.2. Apartado B
  10. 3.3. Apartado C
  11. 3.4. Apartado D

Sections

Objetivos

Explicación

Supongamos un programa que realiza dos tareas ejecutadas secuencialmente. Podemos tener una ejecución mas rápida si ejecutamos las dos tareas a la vez, OpenMP nos permite esto mediante las sections, secciones de código ejecutadas por una única hebra.

Código Inicio Descarga

Como puedes ver en el siguiente código, las dos tareas se ejecutan de modo secuencial, y se calcula el tiempo transcurrido mediante la función omp_getwtime.

#include <omp.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>
 
using namespace std;
 
 
void tarea_uno(){
    sleep(2);
}
 
void tarea_dos(){
    sleep(4);
}
 
int main (){
 
    double timeIni, timeFin;
 
    timeIni = omp_get_wtime();
 
    cout<<"Ejecutando tarea 1"<<endl;
    tarea_uno();
 
    cout<<"Ejecutando tarea 2"<<endl;
    tarea_dos();
 
 
    timeFin = omp_get_wtime();
 
    cout<<"Tiempo tardado = "<< timeFin - timeIni <<" segundos"<<endl;
 
}

Observamos el tiempo tardado en la ejecución es la suma de los tiempos de las tareas.

> g++ -fopenmp 04.cpp -o sections
> ./sections
Ejecutando tarea 1
Ejecutando tarea 2
Tiempo tardado = 6.0004 segundos

Ejercicios propuestos

Los tiempos tomados en este programa no cambiaran significativamente si no se ejecuta en una maquina con mas de 1 núcleo de procesamiento.

Funciones necesarias

Solución

Apartado A

A continuación vemos como se resuelve el problema.

Código Descarga

int main (){
    int thread;
    double timeIni, timeFin;
 
    timeIni = omp_get_wtime();
 
    omp_set_num_threads(2);
 
    #pragma omp parallel private(thread)
    {
 
    thread = omp_get_thread_num();
 
    #pragma omp sections
    {
    #pragma omp section
      {
          cout<<"Hebra "<<thread<<" Ejecutando tarea 1"<<endl;
          tarea_uno();
      }
 
    #pragma omp section
      {
          cout<<"Hebra "<<thread<<" Ejecutando tarea 2"<<endl;
          tarea_dos();
      }
 
    }//Fin Sections
 
    }//Fin Parallel
    timeFin = omp_get_wtime();
 
    cout<<"Tiempo tardado = "<< timeFin - timeIni <<" segundos"<<endl;
 
}

Si observamos el tiempo de ejecución del programa ha sido igual a la tarea que mas tarda.

Salida

> g++ -fopenmp 04.cpp -o sections
> ./sections
Hebra 1 Ejecutando tarea 2
Hebra 0 Ejecutando tarea 1
Tiempo tardado = 4.00065 segundos

Apartado B

Añadimos la siguiente salida para saber en que instante de tiempo abandonan las hebras el bloque sections.

Código

}//Fin Sections
    cout<<"Hebra "<<thread<<" salio del sections en el instante = "<<omp_get_wtime() -
timeIni <<endl;
}//Fin Parallel

Como vemos en la ejecución del código a pesar de que las tareas tienen 2 segundos de diferencia las dos hebras salen de la región sections a la vez. OpenMP realiza una sincronización de las hebras y su variables compartidas.

Salida

Hebra 1 Ejecutando tarea 2
Hebra 0 Ejecutando tarea 1
Hebra 1 salio del sections en el instante = 4.00052
Hebra 0 salio del sections en el instante = 4.00371
Tiempo tardado = 4.00374 segundos

Para evitar esa sincronización a la salida de algunas directivas se ha de añadir la clausula nowait.

Código

Como se observa en la salida, las hebras no se sincronizan al final del sections.

Salida

Hebra 1 Ejecutando tarea 2
Hebra 0 Ejecutando tarea 1
Hebra 0 salio del sections en el instante = 2.00067
Hebra 1 salio del sections en el instante = 4.00065
Tiempo tardado = 4.00092 segundos

Apartado C

Cuando el numero de hebras es superior al numero de section simplemente las hebras sin trabajo se quedan ociosas, o si esta presente nowait siguen ejecutando código después del sections.

Salida

Hebra 1 Ejecutando tarea 2
Hebra 0 Ejecutando tarea 1
Hebra 2 salio del sections en el instante = 0.000500483
Hebra 3 salio del sections en el instante = 0.000605175
Hebra 0 salio del sections en el instante = 2.00062
Hebra 1 salio del sections en el instante = 4.00066
Tiempo tardado = 4.00077 segundos

Apartado D

Cuando el numero de section es superior al numero de hebras, se reparten las section entre las hebras disponibles, cuando una de ellas termine de ejecutar una de ellas seguirá por otra, así hasta que todos los section sean ejecutados por una hebra.

Salida

Hebra 0 Ejecutando tarea 1
Hebra 0 Ejecutando tarea 2
Hebra 0 salio del sections en el instante = 6.00074
Tiempo tardado = 6.00087 segundos
Creado por: Daniel Guerrero Martínez y Sergio Rodríguez Lumley 2010

Valid HTML 4.01 Transitional