【问题标题】:How to remove dependencies in this OpenMP summation exemple如何在此 OpenMP 求和示例中删除依赖项
【发布时间】:2020-10-18 07:13:47
【问题描述】:

我现在开始使用 OpenMP,并且需要使用 OpenMP 在此任务中实现并行性:

for (i = 0; i < N; i++){
 index += i*alpha + 4;
 sum += array[index];
}

我打算使用归约运算符来获得 sum 变量的正确值,但为了做到这一点,我需要先解决索引变量的依赖关系。 我该怎么做?

感谢大家的帮助!

【问题讨论】:

    标签: c++ parallel-processing dependencies openmp


    【解决方案1】:

    由于顺序依赖,循环不能直接并行化。但是,它可以首先分成两部分

    for (i = 0; i < N; i++) {
     index += i*alpha + 4;
     tmp[i] = index;
    }
    for (i = 0; i < N; i++) {
     sum += array[tmp[i]];
    }
    

    一旦拆分,第一个循环会呈现出扫描模式,并且可以并行化,尽管并行版本可能不会比顺序版本快。第二个循环是一个简单的reduction,可以很容易地并行化。

    使用 OpenMP 执行扫描模式通常有点棘手。希望由于 alpha 似乎是一个循环常量index 的所有值都可以轻松预测,这要归功于基本的数学属性:

    index_i = index_init + 0*alpha+4 + 1*alpha+4 + 2*alpha+4 + ... + i*alpha+4
            = index_init + (0+1+2+...+i)*alpha + 4*(i+1)
            = index_init + (i*(i+1)/2)*alpha + 4*(i+1)
            = index_init + (i+1)*(i*alpha + 8)/2
    

    因此我们可以编写最终的结果代码:

    #pragma omp parallel for reduction(+:sum)
    for (i = 0; i < N; i++) {
     sum += array[index + (i*(i+1)/2)*alpha + 4*(i+1)];
    }
    

    此外,如果alpha 是整数并且index 从零开始,则数组索引可以稍微快一些:

    #pragma omp parallel for reduction(+:sum)
    for (i = 0; i < N; i++) {
     sum += array[(i+1)*(i*alpha+8)/2];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多