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

TBB 3.0 back compatibility

sinedie
Beginner
794 Views
Hello,
Some codes that used to run with TBB 2.2 do not seem to work with TBB 3.0. I have gone through release notes and changes and it does not seem to indicate back compatibility issues. I use Xeon/CentOS 5.5 with intel64/cc4.1.0_libc2.4_kernel2.6.16.21

In general, using tbb/tbb.h does not seem to work, but a work around was to use all the relavant header fiiles.

More specifically the problems are with:
1. concurrent_bounded_queue
2. parallel_for_lambda
3. parallel_invoke

I am giving a sample code that works with TBB 2.2 and corresponding compilation errors with TBB 3.0

1. concurrent_bounded_queue
[bash]#include 
#include 

#define N 5

using namespace std;
using namespace tbb;

typedef concurrent_bounded_queue CQ;

int main()
{
        CQ cq;
        CQ::iterator it_cq;

        for ( int i=0; i Error:
[bash]concurrent_bounded_queue.cpp(9): error: concurrent_bounded_queue is not a template
  typedef concurrent_bounded_queue CQ;
          ^

concurrent_bounded_queue.cpp(14): error: name followed by "::" must be a class or namespace name
  	CQ::iterator it_cq;
  	^

concurrent_bounded_queue.cpp(14): error: expected a ";"
  	CQ::iterator it_cq;
  	             ^

concurrent_bounded_queue.cpp(21): error: identifier "it_cq" is undefined
  	for ( it_cq = cq.unsafe_begin(); it_cq != cq.unsafe_end(); it_cq++ ) {
  	      ^

concurrent_bounded_queue.cpp(36): warning #592: variable "x" is used before its value is set
  	cq.try_pop( x );
  	            ^

compilation aborted for concurrent_bounded_queue.cpp (code 2)
[/bash]

2. parallel_for with lambda (icc, -std=c++0x)
[bash]#include 
#include 
#include 

#define N 20 

using namespace std;
using namespace tbb;

void func( long *ptr_x )
{
        *ptr_x = -(*ptr_x);
}

void par_func(long a[])
{
        parallel_for( long(0), long(N/2), long(2), [=](long i) {func( &a );} );
}

int main()
{
        task_scheduler_init init(-1);

        long a;

        for ( long i=0; i = i;
        }

        par_func(a);

        for ( long i=0; i);
        }

        return 0;
}
[/bash]

Error:
[bash]parallel_for_lambda3.cpp(17): error: no instance of overloaded function "parallel_for" matches the argument list
            argument types are: (long, long, long, __lambda1)
  	parallel_for( long(0), long(N/2), long(2), [=](long i) {func( &a );} );
  	^

compilation aborted for parallel_for_lambda3.cpp (code 2)
[/bash]

3. parallel_invoke
[bash]#include 
#include 
#include 

#define N 10

using namespace std;
using namespace tbb;

class FObject {
        public:
                void operator ()()
                {
                        cout << "Hello World!" << endl;
                }
};

void Say()
{
        cout << "Yeah!" << endl;
}

int main()
{
        task_scheduler_init init(4);

        FObject f;

        parallel_invoke(f, Say);

        return 0;
}
[/bash]

Error:
[bash]parallel_invoke.cpp(3): catastrophic error: could not open source file "tbb/parallel_invoke.h"
  #include 
                                  ^

compilation aborted for parallel_invoke.cpp (code 4)
[/bash]

Interestingly, the header files that show the error "could not open source file" were in expected directories with read permission and seem fine.

What could be causing the above errors?

TIA,
-Sinedie
0 Kudos
1 Solution
Alexey-Kukanov
Employee
794 Views
The new error is different - as far as I can tell, the linker can not find a symbol that exists in TBB 3.0 but not in earlier versions. So it seems an old version of TBB is used, which confirms that the environment is screwed up.

I think the issue might be because the OS distribution mighthave installed an old version of TBB into system directories, like /usr/include and /usr/lib, and the tools search these directories even before any paths specified via INCLUDE, LIB, etc. One way to check where TBB binaries are taken from is to create a simplest TBB test that only uses e.g. task_scheduler_init which (in theory) should build without a problem, and then check dependencies with ldd; it should tell which libtbb.so is taken to resolve the dependency.

View solution in original post

0 Kudos
6 Replies
Andrey_Marochko
New Contributor III
794 Views
We do not test on CentOS, but I checked your CQ and parallel_for examples on Windows with VS2010 and icl 12.0, and on Linux with a various gcc including 4.4.4, and they work fine (except that gcc does not support lambdas). So I think there is something wrong with either your compiler or its settings. Check e.g. what does INCLUDES env. var. contain? It may point to a place where an older version of TBB is installed.
0 Kudos
sinedie
Beginner
794 Views
Thanks Andrey for the response.

I compile using icc (ver. icc (ICC) 11.1 20090630). gcc is ver. 4.1.2 20080704 (Red Hat 4.1.2-48)

The examples given still run on the same system with TBB 2.2. when I source tbbvars.sh from the relavant directory.

As of INCLUDE:
[bash]$ echo $INCLUDE 
/opt/intel/Compiler/11.1/046/ipp/em64t/include:/opt/intel/Compiler/11.1/046/mkl/include[/bash]
This does not seem to point to any TBB at all! But with the hint I checked the INSTALL_DIR, and it was wrong.

By default TBB 3.0 is loaded. The env variables are:
[bash]$ echo $TBB30_INSTALL_DIR
/opt/intel/tbb30_018oss/bin/intel64/cc4.1.0_libc2.4_kernel2.6.16.21
$ echo $TBB_ARCH_PLATFORM
em64t/cc4.1.0_libc2.4_kernel2.6.16.21
[/bash]
So made the INSTALL_DIR to /opt/intel/tbb30_018oss. It still gave some errors.

I checked all the env variables with tbb using 'grep -i'. I found that CPATH, LD_LIBRARY_PATH and LIBRARY_PATH have the relavant directories begin with proper TBB (2.2) directories. OTOH, with TBB 3.0 these directories appear at the last. I change the order of the directories to make it similar as in 2.2 but it didn't make any difference.

Continuing with your hint, I tried the following with puzzling behavior:
[cpp]$ icc -I/opt/intel/tbb30_018oss/include -ltbb parallel_invoke.cpp 
/opt/intel/tbb30_018oss/include/tbb/parallel_invoke.h(48): error: no instance of function "FObject::operator()" matches the argument list and object (the object has cv-qualifiers that prevent a match)
object type is: const FObject
my_function();
^
detected during:
instantiation of "tbb::task *tbb::internal::function_invoker::execute() [with function=FObject]" at line 42
implicit generation of "tbb::internal::function_invoker::~function_invoker() [with function=FObject]" at line 42
instantiation of class "tbb::internal::function_invoker [with function=FObject]" at line 42
instantiation of "tbb::internal::function_invoker::function_invoker(const function &) [with function=FObject]" at line 132
instantiation of "void tbb::internal::parallel_invoke_helper::run_and_finish(const F0 &) [with F0=FObject]" at line 165
instantiation of "void tbb::parallel_invoke(const F0 &, const F1 &, tbb::task_group_context &) [with F0=FObject, F1=void ()]" at line 293
instantiation of "void tbb::parallel_invoke(const F0 &, const F1 &) [with F0=FObject, F1=void ()]" at line 29 of "parallel_invoke.cpp"

compilation aborted for parallel_invoke.cpp (code 2)

$ icc -I/opt/intel/tbb22_20090809oss/include/ -ltbb parallel_invoke.cpp
$ ./a.out
Hello World!
Yeah!
$
[/cpp]
The problem is with include, but I still can't figure out how to fix it! :(

I tried compiling from source code, no luck. BTW, parallel_for with lamda works now with correct INSTALL_DIR. concurrent_bounded_queue and parallel_invoke fail. :(

Any more clues?
0 Kudos
Alexey-Kukanov
Employee
794 Views
For parallel_invoke, the likely reason is a change we did in 2.2 Update 2:
- parallel_invoke and parallel_for_each now take function objects by const reference, not by value.
Due to that, you should declare the function call operator as const.
0 Kudos
sinedie
Beginner
794 Views
It doesn't seem to work

[cpp]#include 
#include 
#include 

#define N 10

using namespace std;
using namespace tbb;

class FObject {
        public:
                void operator ()() const
                {
                        cout << "Hello World!" << endl;
                }
};

void Say()
{
        cout << "Yeah!" << endl;
}

int main()
{
        task_scheduler_init init(4);

        FObject f1;
        FObject f2;

        parallel_invoke( f1, f2);

        return 0;
}

[/cpp]
Error:
[bash]/tmp/ccOiTjCa.o: In function `tbb::internal::parallel_invoke_cleaner::~parallel_invoke_cleaner()':
pi.cpp:(.text._ZN3tbb8internal23parallel_invoke_cleanerD1Ev[tbb::internal::parallel_invoke_cleaner::~parallel_invoke_cleaner()]+0x17): undefined reference to `tbb::interface5::internal::task_base::destroy(tbb::task&)'
collect2: ld returned 1 exit status
[/bash]
0 Kudos
Alexey-Kukanov
Employee
795 Views
The new error is different - as far as I can tell, the linker can not find a symbol that exists in TBB 3.0 but not in earlier versions. So it seems an old version of TBB is used, which confirms that the environment is screwed up.

I think the issue might be because the OS distribution mighthave installed an old version of TBB into system directories, like /usr/include and /usr/lib, and the tools search these directories even before any paths specified via INCLUDE, LIB, etc. One way to check where TBB binaries are taken from is to create a simplest TBB test that only uses e.g. task_scheduler_init which (in theory) should build without a problem, and then check dependencies with ldd; it should tell which libtbb.so is taken to resolve the dependency.
0 Kudos
sinedie
Beginner
794 Views
Thanks Alexey! That was the problem. I initially removed older tbb from intel 11.1, denied permission to look into TBB 2.2 directories. I verified that there are no libtbbs elsewhere, and complied. It worked! Then removed all tbbs but tbb30_018oss. Now everything works fine.

Thanks a lot again. :)
-S
0 Kudos
Reply