Anterior Siguiente

A veces es necesario que solo uno de los threads de la región paralela ejecute una parte del código. Esto se logra creando una región interna de ejecución secuencial con la directiva single. Cualquiera de los hilos de la región paralela puede asumir el control de esa región secuencial. Todos los hilos se sincronizan al final de la región single (barrera implícita), a menos que se use la cláusula nowait.

Sintaxis básica

#pragma omp parallel 
{
    <parallel region code>
    #pragma omp single 
    {
        <serial region code>
    } // implicit barrier here
    <parallel region code>
} // implicit barrier here

Ejemplo 1

Dentro de la región paralela creamos una región secuencial y vemos cuál de los hilos la asumió:

#include <stdio.h>
#include <omp.h>

int main(){
    int m = omp_get_thread_num();
    printf("master thread=%d in serial region\n", m);
    
    #pragma omp parallel
    {
        int t = omp_get_thread_num();
        printf("thread=%d in parallel region\n", t);
        
        #pragma omp single
        {
            int s = omp_get_thread_num();
            printf("thread=%d in single region\n", s);
        } // implict barrier here

        printf("thread=%d says goodbye\n", t);
    }
    
    printf("master thread=%d in serial region\n", m);
}

Descarga el código aquí.

¿Cómo compilar?

clang -fopenmp -I/home/user/llvm/llvm-build/projects/openmp/runtime/src/ 
     -o single-000 single-000.c

¿Cómo ejecutar?

./single-000 

Salida

master thread=0 in serial region
thread=0 in parallel region
thread=0 in single region
thread=2 in parallel region
thread=3 in parallel region
thread=1 in parallel region
thread=0 says goodbye
thread=2 says goodbye
thread=3 says goodbye
thread=1 says goodbye
master thread=0 in serial region

En este caso el hilo 2 asumió el control de la región interna, pero podría ser cualquiera de los 4. Los 4 hilos se despiden en bloque, y siempre después de que la región singlehaya terminado.

Ejemplo 2

Dentro de la región paralela creamos una región secuencial con nowait y vemos el orden de impresión de las despedidas:

#include <stdio.h>
#include <omp.h>

int main(){
    int m = omp_get_thread_num();
    printf("master thread=%d in serial region\n", m);
    
    #pragma omp parallel
    {
        int t = omp_get_thread_num();
        printf("thread=%d in parallel region\n", t);
        
        #pragma omp single nowait
        {
            int s = omp_get_thread_num();
            printf("thread=%d in single region\n", s);
        } // no barrier here

        printf("thread=%d says goodbye\n", t);
    }
    
    printf("master thread=%d in serial region\n", m);
}

Descarga el código aquí.

¿Cómo compilar?

clang -fopenmp -I/home/user/llvm/llvm-build/projects/openmp/runtime/src/ 
     -o single-001 single-001.c

¿Cómo ejecutar?

./single-001

Salida

master thread=0 in serial region
thread=0 in parallel region
thread=0 in single region
thread=0 says goodbye
thread=3 in parallel region
thread=3 says goodbye
thread=2 in parallel region
thread=2 says goodbye
thread=1 in parallel region
thread=1 says goodbye
master thread=0 in serial region

En este caso el hilo 0 asumió el control de la región interna. Cada hilo se despide inmediatamente, sin esperar a que la región secuencial haya terminado.

Preguntas

  • Modifica el programa de tal manera que se fuerce al hilo 3 a ejecutar la región single.
  • ¿Por qué el programa no termina de ejecutarse?
  • Si no tuviésemos la directiva single, ¿cómo lograríamos el mismo propósito?
  • ¿Qué aplicaciones le darías a esta directiva?
Anterior Siguiente
Estás en el Nivel 1: Introducción a la programación paralela con OpenMP. ¿Deseas volver al inicio?