Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.
Announcements
Welcome to the Intel Community. If you get an answer you like, please mark it as an Accepted Solution to help others. Thank you!

Question on parallel_reduce

Petros_Mamales
Beginner
51 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
Black Belt
51 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.
Petros_Mamales
Beginner
51 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 ;-))
Reply