使用OpenMP并行化Fibonacci数字计算有什么好处吗?
有几个在线例子使用OpenMP中的 task
指令计算斐波纳契数。例如,在http://docs.oracle.com/cd/E19205-01/820-7883/girtd/index.html和此处http://openmp.org/forum/viewtopic.php?f=3&t=1231
其中一些示例声称使用OpenMP可以提高性能。我不明白这一点,因为根据我的理解,计算Fibonacci系列基本上是非平行的(忽略基于封闭形式解的方法,例如来自Binet的公式)。
此外,OpenMP示例所基于的递归具有比迭代计算数字更差的性能(几个数量级更差)(这是众所周知的Iterative and recursive version has same complexity?)。但是当我使用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);
}
答案 0 :(得分:3)
您发布的link中的代码几乎等于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;
}
}
在该示例下,您可以找到以下内容:
注意:有更有效的算法来计算Fibonacci 数字。这种经典的递归算法用于说明 目的。
所以我认为这只是为教学目的而举一个小例子。