为什么这个OpenMP代码适用于动态调度而不适用于静态?

时间:2014-05-13 00:52:01

标签: openmp

我正在通过构建一个使用以下算法计算pi的简单程序来学习OpenMP:

pi = 4/1 - 4/3 + 4/5 - 4/7 + 4/9...

问题是当我将调度更改为静态时,它无法正常工作。当线程数为1时,它完美地工作。它也可以在动态调度下正确运行,尽管每次运行时结果都会略有不同。知道可能是什么问题吗?

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

#define N       100
#define CSIZE   1
#define nthread 2

int pi()
{
int i, chunk;
float pi = 0, x = 1;

chunk = CSIZE;
omp_set_num_threads(nthread);

#pragma omp parallel shared(i, x, chunk)
{
    if (omp_get_num_threads() == 0)
    {
        printf("Number of threads = %d\n", omp_get_num_threads());
    }

    printf("Thread %d starting...\n", omp_get_thread_num());

    #pragma omp for schedule(dynamic, chunk)
    for (i = 1; i <= N; i++)
    {
        if (i % 2 == 0)
            pi = pi - 4/x;
        else
            pi = pi + 4/x;

        x = x + 2;

        printf("Pi is currently %f at iteration %d with x = %0.0f on thread %d\n",
                pi, i, x, omp_get_thread_num());
    }
}

return EXIT_SUCCESS;
}

1 个答案:

答案 0 :(得分:1)

在我测试代码时在循环中使用printf使得动态在第一个线程上完成所有工作而在第二个线程上没有任何工作(使程序有效地串行)。如果您删除printf语句,则会发现pi的值是随机的。这是因为您在xpi中有竞争条件。

除了使用x,您可以除以2*i+1(从{0}开始为零)。而不是使用分支来获取符号,您可以使用i。要获得sign = -2*(i%2)+1,您需要使用pi进行缩减。

#pragma omp for schedule(static) reduction(+:pi)