我希望找到for循环内部计算值的最大值,并存储其相应的索引 max_calc_value 和 i_max < / em> 在这里,下面是我的伪代码。我想知道是否可以在这里进行某种减少:
double max_calc_value = -DBL_MAX; // minimum double value
#pragma omp parallel for
for (int i = 20; i < 1000; i++) {
this_value = my_slow_function(large_double_vector_array, param1*i, .., param5+i);
if (this_value > max_calc_value){
max_calc_value = this_value;
i_max = i;
}
}
答案 0 :(得分:6)
如果您愿意,可以定义自定义缩小功能并将其并行使用。在您的具体示例中,这可能只会使代码比仅使用critical
部分更麻烦。但是,如果您的实际代码可以全局受益于使用此自定义缩减功能,这不仅适用于最终的并行缩减,而且适用于本地代码...
所以万一它适用于你,这里有一个如何工作的例子:
#include <iostream>
#include <omp.h>
struct dbl_int {
double val;
int idx;
};
const dbl_int& max( const dbl_int& a, const dbl_int& b) {
return a.val > b.val ? a : b;
}
#pragma omp declare reduction( maxVal: dbl_int: omp_out=max( omp_out, omp_in ) )
int main() {
dbl_int di = { -100., -1 };
#pragma omp parallel num_threads( 10 ) reduction( maxVal: di )
{
di.val = omp_get_thread_num() % 7;
di.idx = omp_get_thread_num();
}
std::cout << "Upon exit, value=" << di.val << " and index=" << di.idx << std::endl;
return 0;
}
这给了我:
~/tmp $ g++ -fopenmp myred.cc -o myred
~/tmp $ ./myred
Upon exit, value=6 and index=6
答案 1 :(得分:2)
处理它的最佳方法是定义一个自定义缩减操作,如Gilles&#39;回答。如果您的编译器仅支持OpenMP 3.1或更早版本(在OpenMP 4.0中引入了自定义缩减操作),那么正确的解决方案是在每个线程中执行本地缩减,然后依次组合本地缩减:
double max_calc_value = -DBL_MAX; // minimum double value
#pragma omp parallel
{
int my_i_max = -1;
double my_value = -DBL_MAX;
#pragma omp for
for (int i = 20; i < 1000; i++) {
this_value = my_slow_function(large_double_vector_array, param1*i, .., param5+i);
if (this_value > my_value){
my_value = this_value;
my_i_max = i;
}
}
#pragma omp critical
{
if (my_value > max_calc_value) {
max_calc_value = my_value;
i_max = my_i_max;
}
}
}
这最小化了critical
构造的同步开销,并以简化的方式显示了reduction
子句的实际实现方式。
答案 2 :(得分:1)
您可以尝试&#34; omp critical&#34;:
double max_calc_value = -DBL_MAX; // minimum double value
#pragma omp parallel for
for (int i = 20; i < 1000; i++)
{
a_value = my_slow_function(large_double_vector_array, param1*i, .., param5+i);
#pragma omp critical
{
if (a_value > max_calc_value){
max_calc_value = a_value;
i_max = i;
}
}
}