Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.

Question on parallel_reduce

Petros_Mamales
Beginner
244 Views
Hi,
I hope I am submirring this to the right place..
I have a simple program that calculates the sums of vectors (views to a buffer) using a single sweep.
My issue is that in two different calculations I get very different results. There is a good chance that I do something really wrong since I am relatively new to tbb.
I have two versions of the calculation: in one at join the partial sums are added on. In the second they are added to an outside buffer.
I have ran similar tasks with one target (instead of a "vector" w/out problems using similar methods (to the first). I would like the second, if it worked because it would be much more light weight per thread.
I use tbb 3 on visual studio 2010 and on windows 7.
Thank you very much in advance for the help,
Petros.

#define MAXFACTORS 100

//stl

#include

using namespace std;

//tbb

#include "tbb\\parallel_reduce.h"

#include "tbb\\blocked_range.h"

//define a vector to be a view to data:

class Vector{

public:

size_t size_;

size_t stride_;

double * data_;

Vector()

{}

Vector(size_t size, double * const pdata, size_t stride )

:size_(size),

data_(pdata),

stride_(stride)

{}

~Vector()

{}

double & operator[]( const size_t i ){ return *(data_ + i* stride_ ); }

double const & operator[]( const size_t i ) const { return *(data_ + i* stride_ ); }

};

//define the class to be used by tbb:

class moment_calculator_local{

private:

Vector * vars_;

const size_t size_;

public:

double m1_[MAXFACTORS];

moment_calculator_local( Vector * const vars, const size_t size )

:vars_( vars ),

size_(size) {

for ( size_t i = 0; i != size_; ++i ) m1_ = 0L;

}

~moment_calculator_local()

{}

const size_t size() const { return size_;}

void operator()( const tbb::blocked_range< size_t > & r ) {

const size_t nVars = size_;

size_t jVar;

for( size_t i = r.begin(); i != r.end(); ++i ) {

for ( jVar = 0; jVar != nVars; ++jVar ) {

const Vector & view_j = vars_[jVar];

const double var_j_i = view_j;

m1_[ jVar ] += var_j_i ;

}

}

}

moment_calculator_local( moment_calculator_local & ec, tbb::split & splt )

:vars_( ec.vars_ ),

size_(ec.size_){

memcpy( m1_, ec.m1_, ec.size_* sizeof(double)/sizeof(char) );

}

void join ( const moment_calculator_local & ec ) {

size_t nVars = size_;

for ( size_t j = 0; j != nVars; ++j )

m1_ += ec.m1_;

}

};

class moment_calculator_global{

private:

Vector * vars_;

const size_t size_;

double * const tgt_;

public:

double m1_[MAXFACTORS];

moment_calculator_global( Vector * const vars, const size_t size, double * const tgt )

:vars_( vars ),

size_(size),

tgt_(tgt) {

for ( size_t i = 0; i != size_; ++i ) m1_ = 0L;

}

~moment_calculator_global()

{}

const size_t size() const { return size_;}

void operator()( const tbb::blocked_range< size_t > & r ) {

const size_t nVars = size_;

size_t jVar;

for( size_t i = r.begin(); i != r.end(); ++i ) {

for ( jVar = 0; jVar != nVars; ++jVar ) {

const Vector & view_j = vars_[jVar];

const double var_j_i = view_j;

m1_[ jVar ] += var_j_i ;

}

}

}

moment_calculator_global( moment_calculator_global & ec, tbb::split & splt )

:vars_( ec.vars_ ),

size_(ec.size_),

tgt_(ec.tgt_){

memcpy( m1_, ec.m1_, ec.size_* sizeof(double)/sizeof(char) );

}

void join ( const moment_calculator_global & ec ) {

size_t nVars = size_;

for ( size_t j = 0; j != nVars; ++j )

tgt_ += ec.m1_;

}

};

int main(){

const size_t dimension = 5;

const size_t mcSize = 10000;

const size_t sampleSize = dimension * mcSize;

double * pdata = new double[ sampleSize ];

//create uniform random data in [0,1]

for ( size_t i = 0; i != sampleSize; ++i )

pdata = double(rand())/double(RAND_MAX) - 0.5;

//create Vectors corresponding to the columns of the sample

Vector vars[dimension];

for (size_t i = 0; i != dimension; ++i )

vars = Vector( mcSize, pdata + i, dimension );

moment_calculator_local mc( vars, dimension );

tbb::parallel_reduce( tbb::blocked_range(0, mcSize, 1000 ),

mc,

tbb::auto_partitioner() );

moment_calculator_local mc2( vars, dimension );

tbb::parallel_reduce( tbb::blocked_range(0, mcSize, 1000 ),

mc2,

tbb::auto_partitioner() );

cout << "Adding the results locally:" << endl;

cout << "\\t1st:\\t\\t2nd:" << endl;

cout << "\\t===:\\t\\t===:" << endl;

for ( size_t i = 0; i != dimension; ++i )

cout << i << "\\t" << mc.m1_ << "\\t\\t" << mc2.m1_ << endl;

cout << endl;

double m1Tgt[dimension]; std::fill( m1Tgt, m1Tgt + dimension, 0.L );

double m2Tgt[dimension]; std::fill( m2Tgt, m2Tgt + dimension, 0.L );

moment_calculator_global mc21( vars, dimension, m1Tgt );

tbb::parallel_reduce( tbb::blocked_range(0, mcSize, 1000 ),

mc21,

tbb::auto_partitioner() );

moment_calculator_global mc22( vars, dimension, m2Tgt );

tbb::parallel_reduce( tbb::blocked_range(0, mcSize, 1000 ),

mc22,

tbb::auto_partitioner() );

cout << "Adding the results to gloabal target buffer:" << endl;

cout << "\\t1st:\\t\\t2nd:" << endl;

cout << "\\t===:\\t\\t===:" << endl;

for ( size_t i = 0; i != dimension; ++i )

cout << i << "\\t" << m1Tgt << "\\t\\t" << m2Tgt << endl;

return 1;

}


0 Kudos
3 Replies
TimP
Honored Contributor III
244 Views
There is a forum specifically for TBB; you will likely wait longer for a TBB expert to glance at this forum.
Tools are provided for insertion of code, such as the stubby pencil tool on the toolbar, and the file attachment tool. I can't see anyone making an effort to make sense of your mangled post.
0 Kudos
Petros_Mamales
Beginner
244 Views
Thank you for your reply. Tried to find the TBB forum w/out much luck I am afraid. Also tried touse the applet to upload the code snippet w/out much luck either. I guessthat was not my day ;-))
0 Kudos
Reply