Números de Fibonacci con tareas OpenMP

¿Hay algún beneficio al usar OpenMP para paralelizar los cálculos de los números de Fibonacci?

Hay varios ejemplos en línea que calculan los números de Fibonacci usando eltask Directiva en OpenMP. Por ejemplo enhttp://docs.oracle.com/cd/E19205-01/820-7883/girtd/index.html y aquíhttp://openmp.org/forum/viewtopic.php?f=3&t=1231

Algunos de estos ejemplos afirman que el rendimiento es mejor con OpenMP. No entiendo esto como el cálculo de la serie de Fibonacci es, a mi entender, fundamentalmente no paralelo (ignorar los métodos basados ​​en soluciones de forma cerrada, por ejemplo, de la fórmula de Binet).

Además, la recursión, en la que se basan los ejemplos de OpenMP, tiene un rendimiento mucho peor (varios órdenes de magnitud peores) que el cálculo iterativo de los números (esto es bien conocido¿La versión iterativa y recursiva tiene la misma complejidad?). ¡Pero cuando uso OpenMP es incluso más lento! Parece tonto usar un ejemplo para demostrar cómo usar una función de OpenMP que da peor rendimiento. ¿Entonces estoy tratando de entender por qué existen estos ejemplos de código?

Aquí está el código que utilicé para probar las funciones.

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

inline uint64_t fib_iterative(const size_t n) {
    uint64_t fn0 = 0;
    uint64_t fn1 = 1;
    uint64_t fn2 = 0;
    if(n==0) return fn0;
    if(n==1) return fn1;

    for(int i=2; i<(n+1); i++) {
        fn2 = fn0 + fn1;
        fn0 = fn1;
        fn1 = fn2;
    }
    return fn2;
}

inline uint64_t fib_recursive(uint64_t n) {
    if ( n == 0 || n == 1 ) return(n);
    return(fib_recursive(n-1) + fib_recursive(n-2));
}

int fib_recursive_omp(int n) {
    int i, j;
    if (n<2)
    return n;
    else {
       #pragma omp task shared(i) firstprivate(n)
       i=fib_recursive_omp(n-1);

       #pragma omp task shared(j) firstprivate(n)
       j=fib_recursive_omp(n-2);

       #pragma omp taskwait
       return i+j;
    }
}

int fib_recursive_omp_fix(int n) {
    int i, j;
    if (n<2)
    return n;
    else {
        if ( n < 20 )
        {
            return(fib_recursive_omp_fix(n-1)+fib_recursive_omp_fix(n-2));
        }
        else {
           #pragma omp task shared(i) firstprivate(n)
           i=fib_recursive_omp_fix(n-1);

           #pragma omp task shared(j) firstprivate(n)
           j=fib_recursive_omp_fix(n-2);

           #pragma omp taskwait
           return i+j;
        }
    }
}

int main() {
    const size_t n = 40;
    uint64_t result;
    double dtime;

    dtime = omp_get_wtime();
    result = fib_iterative(n);
    dtime = omp_get_wtime() - dtime;
    printf("iterative time %f, results %lu\n", dtime, result);

    dtime = omp_get_wtime();
    result = fib_recursive(n);
    dtime = omp_get_wtime() - dtime;
    printf("recursive time %f, results %lu\n", dtime, result);

    dtime = omp_get_wtime();
    result = fib_recursive_omp(n);
    dtime = omp_get_wtime() - dtime;
    printf("recursive omp time %f, results %lu\n", dtime, result);

    omp_set_num_threads(1);
    dtime = omp_get_wtime();
    result = fib_recursive_omp_fix(n);
    dtime = omp_get_wtime() - dtime;
    printf("recursive omp fix 1 thread time %f, results %lu\n", dtime, result);

    omp_set_num_threads(2);
    dtime = omp_get_wtime();
    result = fib_recursive_omp_fix(n);
    dtime = omp_get_wtime() - dtime;
    printf("recursive omp fix 2 thread, time %f, results %lu\n", dtime, result);

}

Respuestas a la pregunta(1)

Su respuesta a la pregunta