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

Unable to compile TBB program

Swarnendu
Beginner
3,806 Views

I am unable to compile the following TBB program on DevCloud.

#include <cassert>
#include <chrono>
#include <iostream>
#include <tbb/task.h>
#include <tbb/tbb.h>

using std::cout;
using namespace std::chrono;
using namespace tbb;

using HR = high_resolution_clock;
using HRTimer = HR::time_point;

uint64_t CUTOFF = 16;

uint64_t SerialFib(uint64_t n) {
if (n < 2)
return n;
else
return SerialFib(n - 1) + SerialFib(n - 2);
}

class FibTask : public tbb::task {
public:
const uint64_t n;
uint64_t* const sum;

FibTask(uint64_t n_, uint64_t* sum_) : n(n_), sum(sum_) {}

// Overrides virtual function task::execute
task* execute() {
if (n < CUTOFF) {
*sum = SerialFib(n);
} else {
uint64_t x, y;
FibTask& a = *new (allocate_child()) FibTask(n - 1, &x);
FibTask& b = *new (allocate_child()) FibTask(n - 2, &y);
// Set ref_count to "two children plus one for the wait".
set_ref_count(3);
// Start b running.
spawn(b);
// Start a running and wait for all children (a and b).
spawn_and_wait_for_all(a);
// Do the sum
*sum = x + y;
}
return NULL;
}
};


uint64_t ParallelFib(uint64_t n) {
uint64_t sum;
FibTask& a = *new (task::allocate_root()) FibTask(n, &sum);
task::spawn_root_and_wait(a);
return sum;
}

int main() {
HRTimer start = HR::now();
uint64_t serialFib = SerialFib(50);
HRTimer end = HR::now();
auto duration = duration_cast<microseconds>(end - start).count();
cout << "Sequential Fibonacci in " << duration << " us\n";

start = HR::now();
uint64_t parFib = ParallelFib(50);
end = HR::now();
assert(serialFib == parFib);
duration = duration_cast<microseconds>(end - start).count();
cout << "Task-based Fibonacci in " << duration << " us\n";

return EXIT_SUCCESS;
}

I use the following: g++ -std=c++11 -fopenmp fibonacci-blocking.cpp -o fibonacci -ltbb.

Could someone please help what is the mistake in my setup here?

0 Kudos
1 Solution
Ivan_K_Intel1
Employee
3,736 Views

The Intel DevCloud systems have the oneAPI bundle which contains a reworked TBB version (called oneTBB).

Some of the origin TBB interfaces were reworked in oneTBB. All changed interfaces are described here.

Regards the tbb::task interface, it was deprecated in TBB 2020 and removed in oneTBB. To find Fibonacci numbers, you can use other still actual oneTBB interfaces (e.g. parallel_reduce).

Example of Fibonacci numbers calculation using the tbb::parallel_reduce algorithm:

#include <cassert>
#include <chrono>
#include <iostream>
#include <tbb/tbb.h>

using std::cout;
using namespace std::chrono;
using namespace tbb;

using HR = high_resolution_clock;
using HRTimer = HR::time_point;

uint64_t CUTOFF = 16;

uint64_t SerialFib(uint64_t n) {
if (n < 2)
return n;
else
return SerialFib(n - 1) + SerialFib(n - 2);
}

typedef long long value;

//! Matrix 2x2 class
struct Matrix2x2
{
    //! Array of values
    value v[2][2];
    Matrix2x2() {}
    Matrix2x2(value v00, value v01, value v10, value v11) {
        v[0][0] = v00; v[0][1] = v01; v[1][0] = v10; v[1][1] = v11;
    }
    Matrix2x2 operator * (const Matrix2x2 &to) const;
};
//! Identity matrix
static const Matrix2x2 MatrixIdentity(1, 0, 0, 1);
//! Default matrix to multiply
static const Matrix2x2 Matrix1110(1, 1, 1, 0);
//! Raw arrays matrices multiply
void Matrix2x2Multiply(const value a[2][2], const value b[2][2], value c[2][2])
{
    for( int i = 0; i <= 1; i++)
        for( int j = 0; j <= 1; j++)
            c[i][j] = a[i][0]*b[0][j] + a[i][1]*b[1][j];
}

Matrix2x2 Matrix2x2::operator *(const Matrix2x2 &to) const
{
    Matrix2x2 result;
    Matrix2x2Multiply(v, to.v, result.v);
    return result;
}


//! Functor for parallel_reduce
struct parallel_reduceFibBody {
    Matrix2x2 sum;
    int split_flag;  //< flag to make one less operation for split bodies
    //! Constructor fills sum with initial matrix
    parallel_reduceFibBody() : sum( Matrix1110 ), split_flag(0) { }
    //! Splitting constructor
    parallel_reduceFibBody( parallel_reduceFibBody& other, split ) : sum( Matrix1110 ), split_flag(1/*note that it is split*/) {}
    //! Join point
    void join( parallel_reduceFibBody &s ) {
        sum = sum * s.sum;
    }
    //! Process multiplications
    void operator()( const blocked_range<int> &r ) {
        for( int k = r.begin() + split_flag; k < r.end(); ++k )
            sum = sum * Matrix1110;
        split_flag = 0; // reset flag, because this method can be reused for next range
    }
};
//! Root function
value parallel_reduceFib(int n)
{
    parallel_reduceFibBody b;
    parallel_reduce(blocked_range<int>(2, n, 3), b); // do parallel reduce on range [2, n) for b
    return b.sum.v[0][0];
}

int main() {
HRTimer start = HR::now();
uint64_t serialFib = SerialFib(50);
HRTimer end = HR::now();
auto duration = duration_cast<microseconds>(end - start).count();
cout << "Sequential Fibonacci in " << duration << " us\n";

start = HR::now();
uint64_t parFib = parallel_reduceFib(50);
end = HR::now();
assert(serialFib == parFib);
duration = duration_cast<microseconds>(end - start).count();
cout << "Fibonacci-based Fibonacci in " << duration << " us\n";

return EXIT_SUCCESS;
}

 

View solution in original post

0 Kudos
6 Replies
RaeesaM_Intel
Moderator
3,791 Views

Hi,


Thank you for posting in Intel Forums.

We are moving this case to  Intel® oneAPI Threading Building Blocks Forum so that the subject matter experts can help you out.


Regards,

Raeesa



0 Kudos
Ivan_K_Intel1
Employee
3,750 Views

Hi!

Could you share more detailed information about the issue: error log, information about the execution environment (tbb version, compiler version)?

I am successfully compiled this example using the online compiler (tbb version: 2020.3, compiler version: gcc 5.5): https://godbolt.org/z/GTYs9E

0 Kudos
Swarnendu
Beginner
3,744 Views

I am trying to compile the TBB cloud on Intel DevCloud. These are the steps I am following.

1) SSH into DevCloud
2) Compile the program: g++ -std=c++11 fibonacci-blocking.cpp -o fibonacci -ltbb
3) Compilation error

u47641@login-2:~/cs610$ g++ -std=c++11 fibonacci-blocking.cpp -o fibonacci -ltbb
fibonacci-blocking.cpp:23:34: error: expected class-name before '{' token
class FibTask : public tbb::task {
^
fibonacci-blocking.cpp:31:3: error: 'task' does not name a type; did you mean 'tanl'?
task* execute() {
^~~~
tanl
fibonacci-blocking.cpp: In function 'uint64_t ParallelFib(uint64_t)':
fibonacci-blocking.cpp:53:28: error: 'allocate_root' is not a member of 'tbb::v1::task'
FibTask& a = *new (task::allocate_root()) FibTask(n, &sum);
^~~~~~~~~~~~~
fibonacci-blocking.cpp:54:9: error: 'spawn_root_and_wait' is not a member of 'tbb::v1::task'
task::spawn_root_and_wait(a);
^~~~~~~~~~~~~~~~~~~
u47641@login-2:~/cs610$

I tried the following as well, but it does not help.

export ONEAPI_INSTALL=/opt/intel/inteloneapi
source $ONEAPI_INSTALL/setvars.sh --dnnl-configuration=cpu_tbb --force> /dev/null 2>&1
icpc -std=c++11 fibonacci-blocking.cpp -o fibonacci -ltbb

This is on a login node, I face the same problem on compute nodes.

0 Kudos
Ivan_K_Intel1
Employee
3,737 Views

The Intel DevCloud systems have the oneAPI bundle which contains a reworked TBB version (called oneTBB).

Some of the origin TBB interfaces were reworked in oneTBB. All changed interfaces are described here.

Regards the tbb::task interface, it was deprecated in TBB 2020 and removed in oneTBB. To find Fibonacci numbers, you can use other still actual oneTBB interfaces (e.g. parallel_reduce).

Example of Fibonacci numbers calculation using the tbb::parallel_reduce algorithm:

#include <cassert>
#include <chrono>
#include <iostream>
#include <tbb/tbb.h>

using std::cout;
using namespace std::chrono;
using namespace tbb;

using HR = high_resolution_clock;
using HRTimer = HR::time_point;

uint64_t CUTOFF = 16;

uint64_t SerialFib(uint64_t n) {
if (n < 2)
return n;
else
return SerialFib(n - 1) + SerialFib(n - 2);
}

typedef long long value;

//! Matrix 2x2 class
struct Matrix2x2
{
    //! Array of values
    value v[2][2];
    Matrix2x2() {}
    Matrix2x2(value v00, value v01, value v10, value v11) {
        v[0][0] = v00; v[0][1] = v01; v[1][0] = v10; v[1][1] = v11;
    }
    Matrix2x2 operator * (const Matrix2x2 &to) const;
};
//! Identity matrix
static const Matrix2x2 MatrixIdentity(1, 0, 0, 1);
//! Default matrix to multiply
static const Matrix2x2 Matrix1110(1, 1, 1, 0);
//! Raw arrays matrices multiply
void Matrix2x2Multiply(const value a[2][2], const value b[2][2], value c[2][2])
{
    for( int i = 0; i <= 1; i++)
        for( int j = 0; j <= 1; j++)
            c[i][j] = a[i][0]*b[0][j] + a[i][1]*b[1][j];
}

Matrix2x2 Matrix2x2::operator *(const Matrix2x2 &to) const
{
    Matrix2x2 result;
    Matrix2x2Multiply(v, to.v, result.v);
    return result;
}


//! Functor for parallel_reduce
struct parallel_reduceFibBody {
    Matrix2x2 sum;
    int split_flag;  //< flag to make one less operation for split bodies
    //! Constructor fills sum with initial matrix
    parallel_reduceFibBody() : sum( Matrix1110 ), split_flag(0) { }
    //! Splitting constructor
    parallel_reduceFibBody( parallel_reduceFibBody& other, split ) : sum( Matrix1110 ), split_flag(1/*note that it is split*/) {}
    //! Join point
    void join( parallel_reduceFibBody &s ) {
        sum = sum * s.sum;
    }
    //! Process multiplications
    void operator()( const blocked_range<int> &r ) {
        for( int k = r.begin() + split_flag; k < r.end(); ++k )
            sum = sum * Matrix1110;
        split_flag = 0; // reset flag, because this method can be reused for next range
    }
};
//! Root function
value parallel_reduceFib(int n)
{
    parallel_reduceFibBody b;
    parallel_reduce(blocked_range<int>(2, n, 3), b); // do parallel reduce on range [2, n) for b
    return b.sum.v[0][0];
}

int main() {
HRTimer start = HR::now();
uint64_t serialFib = SerialFib(50);
HRTimer end = HR::now();
auto duration = duration_cast<microseconds>(end - start).count();
cout << "Sequential Fibonacci in " << duration << " us\n";

start = HR::now();
uint64_t parFib = parallel_reduceFib(50);
end = HR::now();
assert(serialFib == parFib);
duration = duration_cast<microseconds>(end - start).count();
cout << "Fibonacci-based Fibonacci in " << duration << " us\n";

return EXIT_SUCCESS;
}

 

0 Kudos
Swarnendu
Beginner
3,726 Views

Thanks, the example works.

The task-based example continues to work on my TBB 2020 desktop installation (Ubuntu 20.04). Do you know when the deprecations will be merged into the Desktop versions? Or will oneTBB and desktop TBBs continue to be separate for now?

0 Kudos
Ivan_K_Intel1
Employee
3,718 Views

I don't know the non-Intel distribution channels plans about switching from the TBB to oneTBB library.

If you want to use the oneTBB library on Ubuntu 20.04, you can download one of the oneAPI toolkits or the oneTBB GitHub package.

Also, I want to note, that the oneTBB is in the Beta stage now, the Gold release will be available later.

0 Kudos
Reply