使用 OpenMP 任务递归计算 pi

下面的代码使用递归方法计算 PI 的值。修改 MAX_PARALLEL_RECURSIVE_LEVEL 值以确定何时递归深度停止创建任务。使用这种方法从递归应用程序中创建并行性:你创建的任务越多,创建的并行任务越多,但每个任务的工作量也越少。因此,试验应用程序以便了解在哪个级别创建进一步的任务不会在性能方面受益是很方便的。

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

double pi_r (double h, unsigned depth, unsigned maxdepth, unsigned long long begin, unsigned long long niters)
{
    if (depth < maxdepth)
    {
        double area1, area2;

        // Process first half
        #pragma omp task shared(area1)
        area1 = pi_r (h, depth+1, maxdepth, begin, niters/2-1);

        // Process second half
        #pragma omp task shared(area2)
        area2 = pi_r (h, depth+1, maxdepth, begin+niters/2, niters/2);

        #pragma omp taskwait

        return area1+area2;
    }
    else
    {

        unsigned long long i;
        double area = 0.0;

        for (i = begin; i <= begin+niters; i++)
        {
            double x = h * (i - 0.5);
            area += (4.0 / (1.0 + x*x));
        }

        return area;
    }
}

double pi (unsigned long long niters)
{
    double res;
    double h = 1.0 / (double) niters;

    #pragma omp parallel shared(res)
    {
#define MAX_PARALLEL_RECURSIVE_LEVEL 4

        #pragma omp single
        res = pi_r (h, 0, MAX_PARALLEL_RECURSIVE_LEVEL, 1, niters);
    }
    return res * h;
}

int main (int argc, char *argv[])
{
#define NITERS (100*1000*1000ULL)

    printf ("PI (w/%d iters) is %lf\n", NITERS, pi(NITERS));

    return 0;
}