【问题标题】:How to parallelize the below for loop如何并行化以下for循环
【发布时间】:2019-06-24 15:05:07
【问题描述】:

我正在尝试集成曲线的功能,并将串行代码转换为并行程序,我正在使用openMP。

我已经使用 openMP parallel for 并行化了 for 循环并实现了更少的程序时间,但问题是结果不是预期的,线程中有些东西搞砸了,我想知道如何并行化N 个线程的 for 循环。

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

double f(double x){
  return sin(x)+0.5*x;
}


int main(){
  int n=134217728,i;
  double a=0,b=9,h,x,sum=0,integral;

  double start = omp_get_wtime();
  h=fabs(b-a)/n;

  omp_set_dynamic(0);
  omp_set_num_threads(64);
  #pragma omp parallel for reduction (+:sum) shared(x)
  for(i=1;i<n;i++){
    x=a+i*h;
    sum=sum+f(x);
  }

  integral=(h/2)*(f(a)+f(b)+2*sum);
  double end = omp_get_wtime();
  double time = end - start;
  printf("Execution time: %2.3f seconds\n",time);
  printf("\nThe integral is: %lf\n",integral);
}

预期的输出是 22.161130,但每次运行程序时它都会发生变化。

【问题讨论】:

  • 您的并行循环累积在全局变量 sum 上并用作临时共享变量 x 因为竞争而无法工作。如果需要临时变量,请使用 reduction 并声明私有变量。另外,你真的有 64 个内核吗?
  • 对总和使用原子更新。
  • 用reduction和shared var x更新了代码,还是有区别
  • x 必须是私有的。

标签: c openmp


【解决方案1】:

您尝试并行化的循环在每次迭代中修改相同的变量xsum,并行化非常麻烦。

您可以重写代码以使并行化路径更加明显:

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

double f(double x) {
    return sin(x) + 0.5 * x;
}

int main() {
    int n = 1 << 27, i, j;
    double a = 0, b = 9, h, x, sum, integral;
    double sums[64] = { 0 };

    double start = omp_get_wtime();
    h = fabs(b - a) / n;

    omp_set_dynamic(0);
    omp_set_num_threads(64);
    #pragma omp parallel for

    for (j = 0; j < 64; j++) {
        for (i = 0; i < n; i += 64) {
            sums[j] += f(a + i * h + j * h);
        }
    }
    sum = 0;
    for (j = 0; j < 64; j++) {
        sum += sums[i];
    }

    integral = (h / 2) * (f(a) + f(b) + 2 * sum);
    double end = omp_get_wtime();
    double time = end - start;
    printf("Execution time: %2.3f seconds\n", time);
    printf("\nThe integral is: %lf\n", integral);
    return 0;
}

【讨论】:

  • 我不明白您为什么从代码中删除了缩减。我认为你的答案会更好地解释一下。
  • 这是一个很好的例子,说明如何不这样做。此代码是错误共享的标准示例,将导致在宽机器上减慢 100 倍。请不要在家里尝试这个(除非你想教人们比赛条件)。
  • @MichaelKlemm:感谢您的评论。事实上,我不做并行计算,这个建议既幼稚又不恰当。我将删除此答案,但您可能希望通过发布有效答案来分享您的专业知识。
  • 不,留下回复。这是真正的教育,所以我认为保留它会很好。
猜你喜欢
  • 1970-01-01
  • 2020-02-18
  • 2020-07-20
  • 1970-01-01
  • 2016-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-04
相关资源
最近更新 更多