通过存储索引来减少omp max

时间:2014-07-16 13:25:34

标签: c++ reduction openmp

使用c ++ openmp 3.1我实现了最大缩减,它存储了一个对象向量的整数变量(得分)的最大值。但我也想存储矢量索引来访问具有最大分数的(s)对象。 我目前的unsuccesfull实现看起来像这样:

//s is a vector of sol objects which contain apart from other variables an  integer     score    variable s[].score            
int bestscore = 0;
int bestant = 0;                
#pragma omp parallel shared(bestant)
{//start parallel session
    #pragma omp for    nowait reduction(max : bestscore)
    for (int ant = 0; ant<maxsols; ++ant) // for all ants
    {
        //procedures on s[ant] object which update the  int s[ant].score
        if (s[ant].score > bestscore)
        {
            //find the object with the highest score
            bestscore = s[ant].score;
            bestant = ant;//i also want know which ant has the highest score
        }
    }
}

代码编译并运行。找到最大的bestscore,但是最好得到一个随机索引。与完成最快的线程相关联的蚂蚁以最佳方式存储。 bestscore以0开头,所以在大多数情况下,s [ant] .score会有更高的分数,而bestscore和bestant会更新。  我认为我需要一个减少运算符,以便在更新bestscore&#34;时更好。&#34;

3 个答案:

答案 0 :(得分:1)

试试这个

int bestscore = 0;
int bestant = 0;
#pragma omp parallel
{
    int bestscore_private = 0;
    int bestant_private = 0;
    #pragma omp for nowait
    for (int ant = 0; ant<maxsols; ++ant) {         
        if (s[ant].score > bestscore_private) {
            bestscore_private = s[ant].score;
            bestant_private = ant;
        }
    }
    #pragma omp critical 
    {
        if(bestscore_private>bestscore) {
            bestscore = bestscore_private;
            bestant = besant_private;
        }
    }
}

答案 1 :(得分:0)

两个观察结果:

  • 我认为您只需将bestscore_privatebestscore的值进行比较即可,这样可以减少比较次数。

  • 此外,至少在今天的操作中,您可以在内部中使用关键部分,如果有条件,则可以在bestscore_privatebestscore之间进行比较并行执行,并且不频繁(希望如此)对bestscore的更新将以严格的方式进行。

    int bestscore = 0;   int bestant = 0;   #pragma omp parallel   {

      int bestscore_private = 0;
      int bestant_private = 0;
      #pragma omp for nowait
      for (int ant = 0; ant<maxsols; ++ant) {         
          if (s[ant].score > bestscore_private) {
              bestscore_private = s[ant].score;
              bestant_private = ant;   
              if(bestscore_private>bestscore){   
                #pragma omp critical 
                {
    
                bestscore = bestscore_private;
                bestant = besant_private;
                }
              }
          }
      }
    

    }

答案 2 :(得分:0)

bestant 获得随机索引 i 的原因(如您所料)是因为 bestant 是共享的,并且不像 bestscore 那样从缩减子句中受益。 Z boson 提出的方案很好:critical 指令块被线程只执行一次,这样开销应该是有限的。

您当时使用的是 OpenMP 3.1 运行时。我想发帖解释这个限制自 OpenMP 4.0 以来已得到解决。您现在可以编写 user defined operator(请参阅 2.19.5.7 声明缩减指令)。

在您的情况下,解决方案可以是将两个值打包在一个结构中并 定义两个这样的结构元素如何在 #pragma parallel for 循环结束时组合。

//s is a vector of sol objects which contain apart from other variables an  integer     score    variable s[].score

typedef struct {
  int score;
  int ant;
} best_t;

best_t best = { 0, 0 };

// we declare our user reduction operator :
// it is called get_max, return a a value of type best_t.
// omp_out and omp_in are the predefined names of two private elements
// to combine in the end to the final shared variable.

#pragma omp declare reduction(get_max : best_t :\
    omp_out = omp_out.score > omp_in.score ? omp_out : omp_in)\
    initializer (omp_priv=(omp_orig))

                
#pragma omp parallel 
{//start parallel session
    #pragma omp for    nowait reduction(get_max : best)
    for (int ant = 0; ant<maxsols; ++ant) // for all ants
    {
        //procedures on s[ant] object which update the  int s[ant].score
        if (s[ant].score > best.score)
        {
            //find the object with the highest score
            best.score = s[ant].score;
            best.ant = ant;
        }
    }
}