Boost logo

Boost Users :

Subject: Re: [Boost-users] OpenMP and Boost - can they be used together?
From: Max S. Kaznady (max.kaznady_at_[hidden])
Date: 2010-09-16 10:44:15


I fixed the problem... basically, entries of a double array get
rounded when summed, and the order in which the sum is performed
matters, so the final answer might differ by some small number due to
rounding. Using an "ordered" directive fixes this. If anyone else is
having this issue, here is sample code, see the comment in the code
about the for loop.

Also, notice how the reduction clause is used and how the sum variable
is no longer shared - that was another issue with the code.

#include <iostream>
#include <omp.h>
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/matrix.hpp>

#define ENABLE_OPENMP_SCORE 1
#define N 100
#define NUMTHREADS 32

using std::cout;
using std::endl;
using boost::numeric::ublas::matrix;

class Compute {
  matrix<double> data1;

public:
  Compute() {
    data1 = matrix<double> (N, N);
    for (unsigned i = 0; i < N; ++i)
      for (unsigned j = 0; j < N; ++j)
        //data1(i, j) = i * N + j;
        data1(i, j) = 1.0/(i * N + j + 1.0);
  }

  double compute_score() {

    double sc = 0.0;
    unsigned i, j;

#pragma omp parallel \
  private(i,j) \
  reduction(+:sc) \
  if (ENABLE_OPENMP_SCORE)
    {
      omp_set_num_threads(NUMTHREADS);

/* Use the line below - it works, because the loop interations are ordered. */
//#pragma omp for ordered schedule(static) collapse(2) nowait
/* This line does not have an "ordered" directive, so the loop
iterations are performed in any order, and due to rounding, the sum is
slightly different each time. */
#pragma omp for schedule(static) collapse(2) nowait
      for (i = 0; i < N; ++i) {
        for (j = 0; j < N; ++j) {
          sc += data1(i, j);
        }
      }
    }
    //cout << data1 << endl;
    return sc;
  }
};

int main(void) {

  Compute comp;

  double oldval = comp.compute_score(), newval;
  cout.precision(32);
  cout << "--" << endl;
  while (1) {
    newval = comp.compute_score();
    cout << "--" << endl;
    if (newval != oldval) {
      cout << " newval - oldval = diff, " << newval << " - " << oldval << " = "
          << newval - oldval << endl;
      exit(1);
    }
    oldval = newval;
  }

  return 0;
}

On Wed, Sep 15, 2010 at 11:42 PM, dhruva <dhruvakm_at_[hidden]> wrote:
> Hi,
>  With my limited knowledge of OpenMP, I am attempting to give some hints.
>
> On Thu, Sep 16, 2010 at 5:04 AM, Max S. Kaznady <max.kaznady_at_[hidden]> wrote:
>> Hello,
>>
>> I wrote a simple parallel program which computes the sum of elements
>> across a matrix using Boost. When I use OpenMP, the program runs give
>> different sums. When I use just simple arrays like double array[N][N],
>> instead of boost::numeric::ublas::matrix<double>, the code work just
>> fine and as expected. Does anyone know what is going on? It looks like
>> the score function is not being modified properly, because Boost array
>> returns just fine.
>>
>
>> [code]
>>
>>  double sc = 0.0;
>>  unsigned i, j;
>>  matrix<double> temp(N, N);
>>
>> #pragma omp parallel \
>>  shared(sc,temp) \
>
> Not sure if you can share a user defined type which does not point to
> a contiguous
> block of memory. Could you please try using a normal array instead of
> boost array
> only for 'temp' and see what happens. I am doubting race conditions since OpenMP
> cannot guarantee synchronous write access to 'temp' IIRC using memory barriers.
>
> -dhruva
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net