Search code examples
c++cparallel-processingopenmpreduction

How to implement argmax with OpenMP?


I am trying to implement a argmax with OpenMP. If short, I have a function that computes a floating point value:

double toOptimize(int val);

I can get the integer maximizing the value with:

double best = 0;
#pragma omp parallel for reduction(max: best)
for(int i = 2 ; i < MAX ; ++i)
{
    double v = toOptimize(i);
    if(v > best) best = v;
}

Now, how can I get the value i corresponding to the maximum?

Edit:

I am trying this, but would like to make sure it is valid:

double best_value = 0;
int best_arg = 0;
#pragma omp parallel
{
  double local_best = 0;
   int ba = 0;
#pragma omp for reduction(max: best_value)
  for(size_t n = 2 ; n <= MAX ; ++n)
  {
    double v = toOptimize(n);
    if(v > best_value)
    {
      best_value = v;
      local_best = v;
      bn = n;
    }
  }
#pragma omp barrier
#pragma omp critical
  {
    if(local_best == best_value)
      best_arg = bn;
  }
}

And in the end, I should have best_arg the argmax of toOptimize.


Solution

  • Your solution is completely standard conformant. Anyhow, if you are willing to add a bit of syntactic sugar, you may try something like the following:

    #include<iostream>
    
    using namespace std;
    
    double toOptimize(int arg) {
      return arg * (arg%100);
    }
    
    class MaximumEntryPair {
    public:
    
      MaximumEntryPair(size_t index = 0, double value = 0.0) : index_(index), value_(value){}
    
      void update(size_t arg) {
        double v = toOptimize(arg);
        if( v > value_ ) {
          value_ = v;
          index_ = arg;
        }
      }
    
      bool operator<(const MaximumEntryPair& other) const {
        if( value_ < other.value_ ) return true;
        return false;
      }  
    
      size_t index_;
      double value_;
    };
    
    
    
    int main() {
      MaximumEntryPair best;
    #pragma omp parallel 
      {
        MaximumEntryPair thread_local;
        #pragma omp for
        for(size_t ii = 0 ; ii < 1050 ; ++ii) {
          thread_local.update(ii);
        } // implicit barrier
    #pragma omp critical
        {
          if ( best < thread_local ) best = thread_local;
        }
    
      } // implicit barries
      cout << "The maximum is " << best.value_ << " obtained at index " << best.index_ << std::endl;
      cout << "\t toOptimize(" << best.index_ << ") = " << toOptimize(best.index_) << std::endl;
      return 0;
    }