【问题标题】:Problem using pragma omp parallel for to compute pi使用 pragma omp parallel for 计算 pi 的问题
【发布时间】:2021-11-23 20:25:00
【问题描述】:

我已经编写了以下代码来计算 pi 的值并且它可以工作:

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

static long num_steps = 1000000;
double step;
#define NUM_THREADS 16

int main()
{
    int i, nthreads;
    double tdata, pi, sum[NUM_THREADS];
    omp_set_num_threads(NUM_THREADS);
    step = 1.0 / (double)num_steps;

    tdata = omp_get_wtime();

    #pragma omp parallel
    {
        int i, id, nthrds;
        double x;
        id = omp_get_thread_num();
        nthrds = omp_get_num_threads();
        if (id == 0)
            nthreads = nthrds;
        for (i = id, sum[id] = 0.0; i < num_steps; i = i + nthrds)
        {
            x = (i + 0.5) * step;
            sum[id] = sum[id] + 4.0 / (1.0 + x * x);
        }
    }

    tdata = omp_get_wtime() - tdata;
    for (i = 0, pi = 0.0; i < nthreads; i++)
    {
        pi = pi + sum[i] * step;
    }
    printf("pi=%f and it took %f seconds", pi, tdata);
}

然后我了解到我可以使用#pragma omp parallel for,然后我不必手动将计算中断到不同的线程。所以我写了这个:

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

static long num_steps = 1000000;
double step;
#define NUM_THREADS 16

int main()
{
    int i;
    double tdata, pi, x, sum = 0.0;
    omp_set_num_threads(NUM_THREADS);
    step = 1.0 / (double)num_steps;

    tdata = omp_get_wtime();

    #pragma omp parallel for
    {
        for (i = 0; i < num_steps; i++)
        {
            x = (i + 0.5) * step;
            sum = sum + 4.0 / (1.0 + x * x);
        }
    }

    tdata = omp_get_wtime() - tdata;
    pi = sum * step;
    printf("pi = %f and compute time = %f seconds", pi, tdata);
}

但是,这不起作用并输出错误的 pi 值。我究竟做错了什么?谢谢。

【问题讨论】:

    标签: c multithreading parallel-processing thread-safety openmp


    【解决方案1】:

    您的代码中有两个竞争条件会导致错误的结果:

    • cmets中已经指出了一个,变量sum的更新(线程间共享),可以用@987654321解决@子句;
    • 另一个是变量x的更新,也是线程间共享的。这种竞争条件可以通过简单地将变量 private 设置为线程来解决。

    两种可能的解决方案:

    1. 使用 OpenMP 的 private 构造函数

       #pragma omp parallel for reduction(+:sum) private(x)
       for (i = 0; i < num_steps; i++)
       {
            x = (i + 0.5) * step;
            sum = sum + 4.0 / (1.0 + x * x);
       }
      
    2. 并行范围内声明变量'x'

       #pragma omp parallel for reduction(+:sum)
       for (i = 0; i < num_steps; i++)
       {
            double x = (i + 0.5) * step;
            sum = sum + 4.0 / (1.0 + x * x);
       }
      

    最终代码可能如下所示:

        #include <omp.h>
        #include <stdio.h>
    
        static long num_steps = 1000000;
        #define NUM_THREADS 16
    
        int main()
        {
            double sum = 0.0;
            omp_set_num_threads(NUM_THREADS);
            double step = 1.0 / (double)num_steps;
        
            double tdata = omp_get_wtime();
        
            #pragma omp parallel for reduction(+:sum)
            for (int i = 0; i < num_steps; i++)
            {
                 double x = (i + 0.5) * step;
                 sum = sum + 4.0 / (1.0 + x * x);
            }
        
            tdata = omp_get_wtime() - tdata;
            double pi = sum * step;
            printf("pi = %f and compute time = %f seconds", pi, tdata);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-22
      • 2021-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-07
      • 1970-01-01
      相关资源
      最近更新 更多