使用OpenMP 3.1,可以使用reduction
min
子句:
double m;
#pragma omp parallel for reduction(min:m)
for (int i=0;i< n; i++){
if (a[i]*2 < m) {
m = a[i] * 2;
}
return m;
假设我还需要最小元素的索引;有没有办法使用reduction
条款?我相信替代方法是使用nowait
和critical
手动编写减少量。
答案 0 :(得分:5)
假设我还需要最小元素的索引;有没有办法为此使用减少条款?
不幸的是,没有。 OpenMP中可能减少的列表非常小。特别是,min
和max
是唯一的“更高级别”功能,它们不可自定义。完全没有。
我必须承认,我不喜欢OpenMP的缩减方法,正是因为它不是可扩展的,所以设计只适用于特殊情况。当然,这些都是有趣的特殊情况,但它仍然是一个糟糕的方法。
对于此类操作,您需要通过将线程局部结果累积到线程局部变量并在最后组合它们来自行实现减少。
执行此操作的最简单方法(实际上非常接近OpenMP如何实现减少)是为每个线程创建一个包含元素的数组,并使用omp_get_thread_num()
来访问元素。但请注意,如果阵列中的元素共享高速缓存行,则会由于错误共享而导致性能下降。要缓解这个问题,请填充数组:
struct min_element_t {
double min_val;
size_t min_index;
};
size_t const CACHE_LINE_SIZE = 1024; // for example.
std::vector<min_element_t> mins(threadnum * CACHE_LINE_SIZE);
#pragma omp parallel for
for (int i = 0; i < n; ++i) {
size_t const index = omp_get_thread_num() * CACHE_LINE_SIZE;
// operate on mins[index] …
}