写入不同线程中的共享变量不会使用openMP

时间:2017-01-27 20:55:43

标签: c++ multithreading openmp

我目前正在学习openMP基础知识,所以我选择了一个简单的练习并开始解决:我得到了一个接近Pi值的串行程序的实现,我被要求给它并行实现。

连续程序:

static long num_steps = 100000;
double step;
void main ()
{           
    int i;   
    double x, pi, sum = 0.0;
    step = 1.0/(double) num_steps;
    for (i=0;i< num_steps; i++){
         x = (i+0.5)*step;
         sum = sum + 4.0/(1.0+x*x);
    }
    pi = step * sum;
}

它在0到1的间隔内计算4.0 /(1 +x²)dx积分的近似值。

本教程使用的是增量方法,在每个步骤中都给出了一些块,所以现在,我可以使用带有一些运行时函数的并行构造。

对我来说,显而易见的事情就是划分和执行部分求和。这是我的解决方案:

int main()
{
    const long num_steps = 100000;
    double step;
    double pi, sum = 0.0;
    step = 1.0/(double) num_steps;
    int num_steps_perthread = num_steps/4;
    double start_time = omp_get_wtime();
    #pragma omp parallel num_threads(4)
    {
        double x,partial_sum = 0.0;
        int init = num_steps_perthread * omp_get_thread_num();
        std::cout << init <<"\n";

        for (int i = init;i< init+num_steps_perthread; i++){
            x = (i+0.5)*step;
            partial_sum += 4.0/(1.0+x*x);
        }
        sum += partial_sum;// this line data race
    }
    pi = step * sum;
    double time = omp_get_wtime() - start_time;
    std::cout << pi << " computed in " << time;


    return 0;
}

所以在提问之前,这是我对openMP并行构造的假设(如果我错了,请纠正我):

  • 构造范围内的任何变量都是本地线程变量。
  • 范围之外的任何变量都是共享的。
  • 我们可以通过一些关键字控制变量的状态(现在我不知道确切的语法)

当我运行程序时,我得到预期的输出,但通常(IMO)我不应该,因为我已经写了一个数据竞赛(它在代码中表示)。变量sum由多个线程写入。

我认为一种可能的情况是,例如,线程号2写入sum并更新它的值,但是在处理器更新内存位置的整个层次结构(高速缓存和RAM的级别)之前另一个线程(假设线程4) )获取旧值并使用它的部分总和更新它。所以我们不会有一个补充,而是覆盖。

1)sum = 0 2)线程2添加它的partial_sum。让我们说+2。 sum = 2但其他内存位置仍保留旧值。 3)线程4选择旧值并添加到它。 4)用线程2更新和的所有存储器位置是结果。 5)更新线程4的结果会覆盖该值。

问题:

  • 我的心理模型是否正确?
  • 或openMP是否添加了隐式同步?
  • 我的假设是真的吗?
  • openMP是否有任何隐式添加?

注意:我知道openMP中的工作共享,只是本教程的方法强加了这种解决方案。

0 个答案:

没有答案