唯一の賢明な方法は、並列処理を特定のレベルでカットすることです。これを下回ると、オーバーヘッドが実行中の作業よりも大きくなるため、意味がありません。それを行うための最良の方法は、2つの別々のfib
実装(たとえば、シリアル実装fib_ser
とパラレル実装)fib
を用意し、指定されたしきい値の下でそれらを切り替えることです。
int fib_ser(int n)
{
if (n < 2)
return n;
else
return fib_ser(n-1) + fib_ser(n-2);
}
int fib(int n)
{
int i, j;
if (n <= 20)
return fib_ser(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;
}
}
ここで、しきい値はn == 20
です。これは任意に選択され、その最適値はマシンやOpenMPランタイムによって異なります。
if
もう1つのオプションは、次の句を使用してタスクを動的に制御することです。
int fib(int n)
{
int i, j;
if (n<2)
return n;
else
{
#pragma omp task shared(i) if(n > 20)
i=fib(n-1);
#pragma omp task shared(j) if(n > 20)
j=fib(n-2);
#pragma omp taskwait
return i+j;
}
}
これにより、2つの明示的なタスクがオフn <= 20
になり、コードがシリアルで実行されますが、OpenMPコード変換によるオーバーヘッドが発生するため、個別のシリアル実装を使用した以前のバージョンよりも実行速度が低下します。