【问题标题】: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];
}