使用 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
我相信替代方法是使用and手动编写减少critical
。
使用 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
我相信替代方法是使用and手动编写减少critical
。
假设我还需要最小元素的索引;有没有办法为此使用减少条款?
抱歉不行。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] …
}