Optimization 具有OpenMP任务的斐波那契数

Optimization 具有OpenMP任务的斐波那契数,optimization,recursion,openmp,fibonacci,Optimization,Recursion,Openmp,Fibonacci,使用OpenMP并行化斐波那契数计算有什么好处吗 有几个在线示例使用OpenMP中的task指令计算斐波那契数。例如在和这里 其中一些示例声称OpenMP的性能更好。我不理解这一点,因为根据我的理解,计算斐波那契级数基本上是非并行的(忽略基于封闭形式解的方法,例如从比奈公式) 此外,OpenMP示例所基于的递归比迭代计算数字(这是众所周知的)的性能差得多(差几个数量级)。但当我使用OpenMP时,它甚至更慢!用一个例子来演示如何使用性能较差的OpenMP功能似乎很愚蠢。 所以我试图理解为什么会有

使用OpenMP并行化斐波那契数计算有什么好处吗

有几个在线示例使用OpenMP中的
task
指令计算斐波那契数。例如在和这里

其中一些示例声称OpenMP的性能更好。我不理解这一点,因为根据我的理解,计算斐波那契级数基本上是非并行的(忽略基于封闭形式解的方法,例如从比奈公式)

此外,OpenMP示例所基于的递归比迭代计算数字(这是众所周知的)的性能差得多(差几个数量级)。但当我使用OpenMP时,它甚至更慢!用一个例子来演示如何使用性能较差的OpenMP功能似乎很愚蠢。 所以我试图理解为什么会有这些代码示例

下面是我用来测试函数的代码

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

}
#包括
#包括
#包括
内联uint64纤维迭代(常数大小){
uint64_t fn0=0;
uint64_t fn1=1;
uint64_t fn2=0;
如果(n==0)返回fn0;
如果(n==1)返回fn1;
对于(int i=2;i而言,您发布的中的代码几乎等于OpenMP 3.1标准中的示例A.15.4c

int fib(int n) {
  int i, j;
  if (n<2)
    return n;
  else {
    #pragma omp task shared(i)
    i=fib(n-1);
    #pragma omp task shared(j)
    j=fib(n-2);
    #pragma omp taskwait
    return i+j;
  }
}
intfib(intn){
int i,j;

如果(谢谢,这回答了我的问题。我该读一下OpenMP标准了。使用OpenMP性能较差的示例似乎有点愚蠢。我的意思是,递归算法,即使比迭代算法慢,也比OpenMP算法慢。好吧,我认为只有当你用它来展示OpenMP如何提高性能时才愚蠢并行性能(不幸的是,就像OpenMP论坛中那样)。如果你用它来显示程序的逻辑,我认为它是完全正确的(比如当一个人通过在循环中向相同的标量添加
1
来解释
reduce
子句)谢谢,这证实了我的想法——论坛是错误的。我甚至在论坛中尝试了guys的建议,只在n>20时使用OpenMP(如果您感兴趣,请参阅我的代码)。对于n>20,这要快得多,但比没有OpenMP更糟糕。