- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I've started to explore TBB 2.1.
The following code doesn't work (no output generated), although strace -f shows a new thread is created. What's wrong here? Is stdout not shared with the parent process or something?
AJ
#include
#include
#include
class Tester
{
public:
void operator()()
{
std::cout<< "Hello" << std::endl;
}
};
int main(int argc, char** argv)
{
// Is this neeed?
tbb::task_scheduler_init scheduler;
tbb::tbb_thread(Tester());
}
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The technology and syntax may get newer but the old problems just don't go away.
What do you think might be the lifetime of the Tester thread object? How might it compare with the lifetime of main?
I found I had to make two changes to get this code to work. The first was to make the main last long enough to see any results: I added a sleep(10) statement after the tbb_thread call. But that wasn't enough. Now the program hung around for 10 seconds NOT saying "Hello"
It took a second change: lengthening the lifetime of the Tester object by giving it some scope. I rewrote main thusly:
int main(int argc, char ** argv)
{
Tester t;
tbb::tbb_thread my_t(t);
sleep(10);
}
This works just fine on my test. And since tbb_thread, the wrapper, is orthogonal to the TBB task pool, no task_scheduler_init object is required.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here's the final code that works:
#include
#include
class Tester
{
public:
void operator()()
{
std::cout<< "Hello" << std::endl;
}
};
int main(int argc, char** argv)
{
Tester t;
tbb::tbb_thread my_thread(t);
my_thread.join();
return 0;
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I write a piece of code like this:
#include
#include "tbb/concurrent_queue.h"
#include
using namespace std;
class Test2
{
tbb::concurrent_queue
public:
Test2(tbb::concurrent_queue
m_queue(queue)
{
}
void operator()()
{
while(true)
{
int i;
if (m_queue.pop_if_present(i))
{
std::cout << i << endl;
}
else
{
tbb::this_tbb_thread::sleep(tbb::tick_count::interval_t(1.0));
}
}
}
};
void CreatThread(tbb::concurrent_queue
{
Test2 t(queue);
tbb::tbb_thread my_thread(t);
}
int main()
{
tbb::concurrent_queue
for( int i=0; i<10; ++i )
queue.push(i);
CreatThread(queue);
int count = 20;
while(count--)
{
queue.push(count);
Sleep(1000);
}
return 0;
}
It seems that when the main thread terminates, the tbb_thread will terminated. I just want to know when the tbb_thread object my_thread destruct. IMP, the object destructed when the function CreatThread ended. The constructor of tbb_thread will copy a Test2 object t'from t, and start a thread to execute the t'(). Here the object t' is newed object. Is that true?
If it is true, how to make the tbb_thread terminate? And also, when the copied object t' destruct?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The tbb_thread class resembles as closely as possible the std::thread proposal for C++200x standard. And there is no means to cancel/terminate a thread proposed there, thus no way to do that for tbb_thread as well. And this is good in fact; read Herb Sutter's "Interrupt Politely" article to learn why terminating a thread is usually bad idea.
Your code should be extended with a global flag that the thread polls instead of the current endless loop; i.e. replace while(true) with while(!end_flag). Then in main() you should set end_flag:
while(count--)
{
queue.push(count);
Sleep(1000);
}
end_flag = true;
return 0;
}
As your my_thread object was destroyed in CreatThread, the thread got detached and the main thread has no mean to control it. If you want to be sure the thread ended, you should keep the thread object and call join() for it before returning from main().
The copied t' object is destroyed at the end of thread execution, provided that the thread was not interrupted.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
(Added) Sorry, I just had to vent some aggression. Still, Alexey should have been a bit more assertive about that need to use join(). Perhaps more interesting is the question what need there still is for using tbb_thread in user code, and, if there is, a proposal for a standard way to juggle an arbitrary number of threads and join them all atexit().
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
But what is tbb_thread doing in TBB as a non-internal object without added value (just a stand-in for the future std::thread)? For example, in Java, a Thread by default is not isDaemon(), and a program will continue executing while any non-daemon threads remain. The only basic feature I see Thread lacking is a direct implementation of the preferred pattern to stop a thread, requiring the use of an external variable instead.
And isn't TBB all about not using raw threads? Just publishing tbb_thread seems enough validation for some people to want to use it. Shouldn't anyone wanting to use legacy multithreading code also be required to use legacy means to do so? Who is really afraid of: "CAUTION: Threads are heavy weight on most systems, and running too many threads on a system can seriously degrade performance. Consider using a task based solution instead if practical." (buried somewhere at the end of the introduction in the reference)?
Where I see a remaining need for raw threads is to get around worker thread unavailability, but that should be solved another way, for example:
/* somewhere inside execute() */ {
tbb::task::scoped_disruption anonymous;
// with default constructor argument tbb::task::self()
/* something that may block */ {
...
}
}
This would be differentiatable to provide hints about expected total duration and likelihood and granularity of the disruption, so that the scheduler can do something smart about reusing that hardware thread, possibly based on gathered statistics, so maybe the disruption should be identified somehow for use in a hash table (a macro could pass __FILE__ and __LINE__). scoped_disruption might decide that the arguments are not significant enough to offset the cost of the associated administration, and maybe task affinity could be leveraged to schedule a group of tasks locally to avoid administration bottlenecks.
These were 3 questions (why no added value, why there at all, what else).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for your detailed explaination.
I have another question that is there any way to set the priority of the tbb_thread. I mean the tbb_thread maybe have the lower priority than the main thread as the example I posted above. The tbb_thread would not grab the time costing from the main thread to some extent. How to implement that?
Thanks. :)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Raf_Schietekat:But what is tbb_thread doing in TBB as a non-internal object without added value (just a stand-in for the future std::thread)? <...>
And isn't TBB all about not using raw threads? <...>
Where I see a remaining need for raw threads is to get around worker thread unavailability, but that should be solved another way <...>
These were 3 questions (why no added value, why there at all, what else).
All are good questions.
Since TBB 1.0, we had got constant feedback from customers like "TBB is great, but how to use it in a GUI application?" and similar. A recent blog from Arch Robison "Tasks for Doing and Threads for Waiting"also explains where threads might be more useful. Our customers wanted a more complete cross-platform solution, andthat answers "why at all".
We considered (and still do!)adding support for blocking operations into the tasks. But there were no good, non-contradictorydesign suggested to be implemented in TBB 2.1 timeframe. At some moment, we recognized that we were discussing a form of thread wrappers, and desided that there is no sense to invent the bicycle with yet another interface. We quickly reacheda consensus that implementing the C++ proposal for threads makes most sense at the moment. The closer it follows the future standard, the easier users could switch to std::thread once it is available. That answers "why no added value".
And as I said, we continue thinking about how to add support for blocking operations to the tasking model. We thought of the scoped object approach you outlined above, but did not elaborate it in enough detail. So "what else" is an open question, and you are welcome with ideas.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
xdj159,
The std::thread proposal does not describe any way of playing with priority, thus tbb_thread doesn't have it either. You use system-specific API for that.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I write a piece of code like this:
#include
#include "tbb/concurrent_queue.h"
#include
using namespace std;
class Test2
{
tbb::concurrent_queue
public:
Test2(tbb::concurrent_queue
m_queue(queue)
{
}
void operator()()
{
while(true)
{
int i;
if (m_queue.pop_if_present(i))
{
std::cout << i << endl;
}
else
{
tbb::this_tbb_thread::sleep(tbb::tick_count::interval_t(1.0));
}
}
}
};
void CreatThread(tbb::concurrent_queue
{
Test2 t(queue);
tbb::tbb_thread my_thread(t);
}
int main()
{
tbb::concurrent_queue
for( int i=0; i<10; ++i )
queue.push(i);
CreatThread(queue);
int count = 20;
while(count--)
{
queue.push(count);
Sleep(1000);
}
return 0;
}
It seems that when the main thread terminates, the tbb_thread will terminated. I just want to know when the tbb_thread object my_thread destruct. IMP, the object destructed when the function CreatThread ended. The constructor of tbb_thread will copy a Test2 object t'from t, and start a thread to execute the t'(). Here the object t' is newed object. Is that true?
If it is true, how to make the tbb_thread terminate? And also, when the copied object t' destruct?
If one slightly modifies the code for the Test2 class as follows:
Test2(tbb::concurrent_queue
m_queue(queue)
{
std::cout << "Test2: ctor" << endl;
}
~Test2(void)
{
std::cout << "Test2: dtor" << endl;
}
Then build and run the program you will notice that when the tbb::tbb_thread my_thread(t) statement is executed in CreatThread, the destructor for Test2 is invoked twice, but the constructor is only ever invoked once.
Why is this?
I'm trying to figure out the proper use the tbb_thread class, but this behavior does not appear to be correct.
Jim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yep...the implicitly defined copy constructor was being invoked twice during the construction and spawning of the tbb_thread, corresponding to the number of invocations of the destructor.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
tbb_thread::id get_id() but i can't use it there are always compilation errors.
And another question How to wait for thread ? I want to wait for all threads to finish they work.
Default created threads are joinable or i must set this myself?
Because when i use tbb::tbb_thread join(mythread) my application finishes work immidiately ( it's not waiting for other threads )?
Please help
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
test_tbb_thread.cpp is a good source of usage examples. Say, in
for (int i=0; i
// skip
for (int i=0; i
we1stgetting ids, and then waiting for the threads to finish. Yes, threads are joinable by default.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm sorry to spoil this discussion - I tried to send a private message, but aparently you don't accept them.
I have a question - you claim that tbb tasks can be faster than threads.
What do you mean, exactly ?
Tasks, AFAIK are implemented on top of OS-specific threads. So, literally they cannot be faster than them. But possibly some mechanizms are implemented in TBB in a more efficient way than default API for other libraries. And here goes my question - where have you noticed it ?
Thanks a lot for any information/comment and best regards
Bartlomiej Kubica
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
test_tbb_thread.cpp is a good source of usage examples. Say, in
for (int i=0; i
// skip
for (int i=0; i
we1stgetting ids, and then waiting for the threads to finish. Yes, threads are joinable by default.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page