Monografias.com > Computación > Programación
Descargar Imprimir Comentar Ver trabajos relacionados

Sincronización de los threads y tareas (OpenMP)




Enviado por Pablo Turmero




    Monografias.com
    ? Cuando no pueden eliminarse las dependencias de datos entre los threads, es necesario sincronizar su ejecución.

    OpenMP proporciona los mecanismos de sincronización más habituales: exclusión mutua y sincronización por eventos.
    Sincronización de threads

    Monografias.com
    1. Secciones Críticas
    Define un trozo de código que no puede ser ejecutado por más de un thread a la vez.

    OpenMP ofrece varias alternativas para la ejecución en exclusión mutua de secciones críticas. Las dos opciones principales son: critical y atomic.
    Exclusión mútua (SC)

    Monografias.com
    ? Directiva critical

    Define una única sección crítica para todo el programa, dado que no utiliza variables de lock.
    #pragma omp parallel firstprivate(MAXL)
    {

    #pragma omp for
    for (i=0; iMAXL) MAXL = A[i];
    }
    #pragma omp critical
    { if (MAXL>MAX) MAX = MAXL; }

    }
    OJO: la sección crítica debe ser lo “menor” posible!
    Exclusión mútua

    Monografias.com
    ? Secciones críticas “específicas” (named)
    #pragma omp parallel for
    for (i=0; iMAX)
    #pragma omp critical(M1)
    { if (A[i]>MAX) MAX = A[i]; }

    if (A[i] Ejemplo
    #pragma omp parallel private(nire_it)
    {
    omp_set_lock(&C1);
    mi_it = i;
    i = i + 1;
    omp_unset_lock(&C1);

    while (mi_it Ejemplo

    Monografias.com
    /* productor */

    dat = …;
    flag = 1;

    ? Sincronización punto a punto
    La sincronización entre procesos puede hacerse mediante flags (memoria común), siguiendo un modelo de tipo productor / consumidor.
    /* consumidor */

    while (flag==0) { };
    … = dat;

    Eventos (flags)

    Monografias.com
    Sin embargo, sabemos que el código anterior puede no funcionar correctamente en un sistema paralelo, dependiendo del modelo de consistencia de la máquina.

    Tal vez sea necesario desactivar las optimizaciones del compilador antes del acceso a las variables de sincronización.
    Eventos (flags)

    Monografias.com
    Para asegurar que el modelo de consistencia aplicado es el secuencial, OpenMP ofrece como alternativa la directiva:
    #pragma omp flush(X)
    que marca puntos de consistencia en la visión de la memoria (fence).
    /* productor */

    dat = …;
    #pragma omp flush(dat)
    flag = 1;
    #pragma omp flush(flag)

    /* consumidor */

    while (flag==0)
    { #pragma omp flush(flag) };
    #pragma omp flush(dat)
    … = dat;

    Eventos (flags)

    Monografias.com
    El modelo de consistencia de OpenMP implica tener que realizar una operación de flush tras escribir y antes de leer cualquier variable compartida.
    volatile int dat, flag;

    /* productor */

    dat = …;
    flag = 1;

    volatile int dat, flag;

    /* consumidor */

    while (flag==0) {};
    … = dat;

    En C se puede conseguir esto declarando las variables de tipo volatile.
    Eventos (flags)

    Monografias.com
    4. Secciones “ordenadas”

    #pragma omp ordered

    Junto con la cláusula ordered, impone el orden secuencial original en la ejecución de una parte de código de un for paralelo.
    #pragma omp paralell for ordered
    for (i=0; i Ejemplo 1: lista ligada

    while (puntero)
    {
    (void) ejecutar_tarea(puntero);
    puntero = puntero->sig;
    }

    Sin la directiva task, habría que contar el número de iteraciones previamente para transformar el while en un for.
    Tareas

    Monografias.com
    puntero = cabecera;
    #pragma omp parallel
    {
    #pragma omp single nowait
    {
    while(puntero) {
    #pragma omp task firstprivate(puntero)
    {
    (void) ejecutar_tarea(puntero);
    }
    puntero = puntero->sig ;
    }
    }
    }
    Tareas
    > Ejemplo 1: lista ligada – openmp

    Monografias.com
    long fibonacci(int n)
    { // f(0)=f(1)=1, f(n) = f(n-1) + f(n-2)

    long f1, f2, fn;

    if ( n == 0 || n == 1 ) return(n);

    f1 = fibonacci(n-1);
    f2 = fibonacci(n-2);

    fn = f1 + f2;

    return(fn);
    }
    Tareas
    > Ejemplo 2: fibonacci

    Monografias.com
    long fibonacci(int n)
    {
    long f1, f2, fn;

    if ( n == 0 || n == 1 ) return(n);

    #pragma omp task shared(f1)
    {f1 = fibonacci(n-1);}

    #pragma omp task shared(f2)
    {f2 = fibonacci(n-2);}

    #pragma omp taskwait

    fn = f1 + f2;

    return(fn);
    }
    Tareas
    > Ejemplo 2: fibonacci – openmp

    Monografias.com
    #pragma omp parallel shared(nth)
    {
    #pragma omp single nowait
    {
    result = fibonacci(n);
    }
    }
    Posibilidad de aplicar recursividad paralela a partir de un tamaño mínimo de cálculo?
    Tareas
    > Ejemplo 2: fibonacci – openmp

    Monografias.com
    ? Un par de funciones para “medir tiempos”

    ? omp_get_wtime();

    t1 = omp_get_wtime();

    t2 = omp_get_wtime();
    tiempo = t2 – t1;

    ? omp_get_wtick(); precisión del reloj
    Otras cuestiones

    Monografias.com
    ? Programar aplicaciones SMP resulta “más sencillo” que repartir datos por diferentes procesadores y comunicarse por paso de mensajes.

    Pero el uso de variables compartidas por varios threads puede llevar a errores no previstos si no se analiza detenidamente su comportamiento.

    Algunos errores típicos pueden producir carreras (races) en los resultados o dejar bloqueada la ejecución (deadlock).
    Otras cuestiones

    Monografias.com
    ? Carreras
    Definimos una carrera (race) como la consecución de resultados inesperados e irreproducibles debido a problemas en el acceso y sincronización de variables compartidas.
    #pragma omp parallel sections
    {
    #pragma omp section
    A = B + C;

    #pragma omp section
    B = A + C;

    #pragma omp section
    C = B + A;
    }
    !?
    Otras cuestiones: carreras

    Monografias.com
    CONT = 0;
    #pragma omp parallel sections
    { #pragma omp section
    A = B + C;
    #pragma omp flush (A)
    CONT = 1;
    #pragma omp flush (CONT)
    #pragma omp section
    { while (CONT<1)
    { #pragma omp flush (CONT) }
    B = A + C;
    #pragma omp flush (B)
    CONT = 2;
    #pragma omp flush (CONT)
    }
    #pragma omp section
    { while (CONT<2)
    { #pragma omp flush (CONT) }
    C = B + A;
    }
    }
    el contador permite la sincronización entre las secciones (eventos)
    las operaciones de flush aseguran la consistencia de la memoria.
    Otras cuestiones: carreras

    Monografias.com
    #pragma omp parallel private(tid, X)
    {
    tid = omp_get_thread_num();

    #pragma omp for reduction(+:total) nowait
    for (i=0; i0) omp_unset_lock(&C1);
    else
    {

    }

    (región paralela con secciones)


    #pragma omp section
    { omp_set_lock(&C1);
    A = A + func1();
    omp_set_lock(&C2);
    B = B * A;
    omp_unset_lock(&C2);
    omp_unset_lock(&C1);
    }

    #pragma omp section
    { omp_set_lock(&C2);
    B = B + func2();
    omp_set_lock(&C1);
    A = A * B;
    omp_unset_lock(&C1);
    omp_unset_lock(&C2);
    }

    Otras cuestiones: deadlock

    Monografias.com
    ? Recomendaciones:
    ? prestar atención al ámbito de las variables: shared, private, etc.

    ? utilizar con cuidado las funciones de sincronización.

    ? disponer de una versión equivalente secuencial para comparar resultados (serán siempre iguales?).
    Otras cuestiones: deadlock

    Monografias.com
    ? Llamadas en paralelo a funciones de librería
    ¿habrá problemas con la activación simultánea de más de una instancia de dichas funciones?

    Una librería es thread-safe (re-entrante) si lo anterior no es un problema. Si no es así, habría que utilizar una secuencia tipo:

    LOCK / CALL / UNLOCK
    Otras cuestiones

    Monografias.com
    ? Speed-up
    El objetivo de programar una aplicación en un sistema paralelo es:
    – ejecutar el problema más rápido.
    – ejecutar un problema de mayor tamaño.

    En ambos casos hay que tener en cuenta el overhead añadido al paralelizar el código.
    Otras cuestiones: speed-up

    Monografias.com
    ? Escribir programas paralelos OpenMP es fácil… y también lo es escribir programas de bajo rendimiento.

    ? Principales fuentes de pérdida de eficiencia

    ? el algoritmo en ejecución: Amdahl // desequilibrio de carga
    ? sincronización: grano muy fino
    ? comunicación: acceso a variables shared, cache (fallos, falsa compartición…)

    ? implementación de OpenMP / S.O.
    Limitaciones al rendimiento

    Monografias.com
    ? Ejemplos de mejora de la eficiencia:
    #pragma omp parallel for
    for (i=0;i

    Nota al lector: es posible que esta página no contenga todos los componentes del trabajo original (pies de página, avanzadas formulas matemáticas, esquemas o tablas complejas, etc.). Recuerde que para ver el trabajo en su versión original completa, puede descargarlo desde el menú superior.

    Todos los documentos disponibles en este sitio expresan los puntos de vista de sus respectivos autores y no de Monografias.com. El objetivo de Monografias.com es poner el conocimiento a disposición de toda su comunidad. Queda bajo la responsabilidad de cada lector el eventual uso que se le de a esta información. Asimismo, es obligatoria la cita del autor del contenido y de Monografias.com como fuentes de información.

    Categorias
    Newsletter