I am trying to learn how to use TBB, so I'm modifying a sample program I found that is designed to compute powers of an array of complex numbers. Originally, it was passing an array into the parallel_for loop, but I am trying to change it so that it passes in a vector. However, I cannot get my code to compile; I get the following error (compiled using g++ -g program_name.cpp -ltbb):
error: passing ‘const std::complex<double>’ as ‘this’ argument
discards qualifiers [-fpermissive] result[i] = z;
My code is below:
#include <cstdlib>
#include <cmath>
#include <complex>
#include <ctime>
#include <iostream>
#include <iomanip>
#include "tbb/tbb.h"
#include "tbb/blocked_range.h"
#include "tbb/parallel_for.h"
#include "tbb/parallel_for_each.h"
#include "tbb/task_scheduler_init.h"
using namespace std;
using namespace tbb;
typedef complex<double> dcmplx;
dcmplx random_dcmplx ( void )
{
double e = 2*M_PI*((double) rand())/RAND_MAX;
dcmplx c(cos(e),sin(e));
return c;
}
class ComputePowers
{
vector<dcmplx> c; // numbers on input
int d; // degree
vector<dcmplx> result; // output
public:
ComputePowers(vector<dcmplx> x, int deg, vector<dcmplx> y): c(x), d(deg), result(y) { }
void operator() ( const blocked_range<size_t>& r ) const
{
for(int i=r.begin(); i!=r.end(); ++i)
{
dcmplx z(1.0,0.0);
for(int j=0; j < d; j++) {
z = z*c[i];
};
result[i] = z;
}
}
};
int main ( int argc, char *argv[] )
{
int deg = 100;
int dim = 10;
vector<dcmplx> r;
for(int i=0; i<dim; i++)
r.push_back(random_dcmplx());
vector<dcmplx> s(dim);
task_scheduler_init init(task_scheduler_init::automatic);
parallel_for(blocked_range<size_t>(0,dim),
ComputePowers(r,deg,s));
for(int i=0; i<dim; i++)
cout << scientific << setprecision(4)
<< "x[" << i << "] = ( " << s[i].real()
<< " , " << s[i].imag() << ")\n";
return 0;
}
You're trying to modify non-mutable
member field result
in const
-qualified operator()
.
Resolve this discrepancy.
Edit #1: I have already mentioned the two keywords above. Either:
Remove const
qualifier from operator()
:
void operator() ( const blocked_range<size_t>& r ) { ... }
Make result
mutable
:
mutable vector<dcmplx> result;
Additional erorrs may emerge after applying (although strongly preferred) variant no. 1. No. 2 is just for completeness and is used only in marginal situations.
It indeed results in an error with the 1st variant. This is because tbb::parallel_for
takes Func
by const&
, so it can call only const
-qualified member functions on your functor. Why? TBB doesn't want to waste performance by copying large functors (STL passes them by value).
I don't know what's the common practice here, I've never used this library.
Edit #2: Probably all you were missing was that result
wasn't a reference:
vector<dcmplx> &result;
Now you'll be able to modify it, even in const
-qualified operator()
. Modifying a member that gets destructed afterwards wouldn't make sense.
Don't forget to change the constructor's signature to pass y
by reference, too.
Off topic issues in your code:
Not included <vector>
header
using namespace bulky_namespace
globally
not using size_t
for i
in the for
-loop
maybe more...