为什么OpenMP减少条款需要同时进行减少?

时间:2013-05-23 06:24:01

标签: c openmp reduction

OpenMP'并行'构造和'SIMD'构造(修订版4.0中的新增内容)定义reduction子句,该子句告诉编译器执行缩减的变量以及缩减运算符是什么。 但是为什么编译器需要程序员告诉它这个信息呢?例如,GCC能够在不获得程序员帮助的情况下识别减少量(参见herehere)。 是否有任何循环的例子在没有指定减少条款的情况下不能并发?

1 个答案:

答案 0 :(得分:2)

减少是一种通过删除同步点并以内存视图的宽松一致性为代价来提高并行应用程序性能的简单机制。从以下示例中可以立即明确显示减少条款的必要性:

想象一下,您有一个代码可以搜索无序的NUM_ITEMS项集合,目标是查找符合给定条件的所有项目,并将它们收集到数组matches中至于计算这些项目的某些属性的总和。这些物品的订购顺序无关紧要。序列代码可能是这样的:

int num_matches = 0;
int prop_sum = 0;

for (i = 0; i < NUM_ITEMS; i++)
{
   if (criteria(item[i]))
   {
      match[num_matches] = item[i];
      num_matches++;
      prop_sum += item[i]->some_property;
   }
}

num_matchesprop_sum都是变量,其值随着循环的进行而累积。但是这两个变量都有完全不同的语义。尽管可以将prop_sum计算为部分和的总和,但num_matches不能,因为它在输出数组中用作索引。 prop_sum是减少的典型候选者,而num_matches不仅可以减少,而且还必须利用显式同步构造,以防止数据争用和不同的线程覆盖{{1}的同一元素}:

match

虽然您可能认为编译器可能足够聪明,可以注意int num_matches = 0; int prop_sum = 0; #pragma omp parallel for reduction(+:prop_sum) for (i = 0; i < NUM_ITEMS; i++) { if (criteria(item[i])) { #pragma omp critical(update_matches) { match[num_matches] = item[i]; num_matches++; } prop_sum += item[i]->some_property; } } 的使用方式并自动生成原子增量,但OpenMP的目标是在平台和编译器之间可移植供应商。这意味着如果你编写一个符合标准的OpenMP程序并编译并与一个编译器一起正常工作,那么它应该编译并与其他编译器一起正常工作。该标准由许多不同的供应商编写,并非每个人都拥有这种超级智能数据依赖性发现机制。此外,当涉及编译单元外部的数据时,很难获得可靠的检测。

num_matches不是必需品 - 它只是一种便利。你可以实现自己的减少,例如使用原子增量,这对您的平台来说可能是最佳的,但在其他不提供有效原子增量的平台上可能远非最佳。另一方面,预计每个编译器将生成以给定目标平台的最佳方式实现reduction子句的代码。

相关问题