Liczby Fibonacciego z zadaniami OpenMP

Czy istnieje jakaś korzyść z używania OpenMP do równoległego obliczania liczby Fibonacciego?

Istnieje kilka przykładów online, które obliczają liczby Fibonacciego za pomocątask dyrektywa w OpenMP. Na przykład whttp://docs.oracle.com/cd/E19205-01/820-7883/girtd/index.html i tuhttp://openmp.org/forum/viewtopic.php?f=3&t=1231

Niektóre z tych przykładów twierdzą, że wydajność jest lepsza w przypadku OpenMP. Nie rozumiem tego, ponieważ obliczanie serii Fibonacciego jest, moim zdaniem, zasadniczo nierównoległe (ignorowanie metod opartych na rozwiązaniach zamkniętych, np. Ze wzoru Bineta).

Ponadto rekursja, na której opierają się przykłady OpenMP, ma znacznie gorszą wydajność (o kilka rzędów wielkości gorszą) niż obliczanie iteracyjnie liczb (jest to dobrze znaneWersja iteracyjna i rekurencyjna ma taką samą złożoność?). Ale kiedy używam OpenMP, jest jeszcze wolniej! Wydaje się głupie, aby użyć przykładu, aby zademonstrować, jak używać funkcji OpenMP, co daje gorszą wydajność. Więc próbuję zrozumieć, dlaczego te przykłady kodu istnieją?

Oto kod, którego użyłem do testowania funkcji.

#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);

}

questionAnswers(1)

yourAnswerToTheQuestion