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

Add main() thread to thread pool

tgoodhart
Beginner
990 Views
Is it possible to use the main() thread as part of the TBB internal thread pool? GDB suggests that calling "tbb::internal::rml::thread_routine" may cause this to happen, although it seems there is some setup involved in adding the thread to the scheduler before this will work.
0 Kudos
7 Replies
nagy
New Contributor I
990 Views
TBB starts always one worker thread less than you have physical threads. When you call wait on a task in the main thread then the main thread is also used as a worker thread, thus it'seffectivelythe same as the main thread being a part of the internal workers.
0 Kudos
renorm
Beginner
990 Views
The same happens when you use parallel patterns such as parallel_for.
0 Kudos
tgoodhart
Beginner
990 Views
Unfortunately in this case there are not necessary any active tasks. Specifically, I have an I/O thread enqueing tasks. Ideally what I'd like to do is the following:

main()
{
Start scheduler (create initial thread pool)
Create I/O thread.
Do some work.
Use main thread for thread pool.
}

There are historic treasons why things ended up this way. Right now the best solution I have is to refactor in order to use the main thread for I/O. Letting the main thread fizzle would be difficult given the number of things allocated on the stack that would need to be wrapped in smart pointers.
0 Kudos
nagy
New Contributor I
990 Views
Associate every enqueued task with an empty parent task and then wait on that in the main thread, at "Use main thread for thread pool."
Take a look at how my second implementation in this thread is done.http://software.intel.com/en-us/forums/showthread.php?t=76572&o=d&s=lr
0 Kudos
Anton_Pegushin
New Contributor II
990 Views
Hi, it looks like what you're looking for is TBB's task_group API. The way to use this mechanism is to create a task_group object first, then use it to spawn tasks that can potentially run in parallel, after that master thread can execute something specific (and add other tasks to the same task_group in the process). To make sure all the tasks were completed, and in the case they weren't, to join the worker threads pool, master thread calls task_group.wait(), when it's done executing some specific functionality.
0 Kudos
tgoodhart
Beginner
990 Views
My appologies for not being as detailed as I clearly should have been from the beginning. Unfortunately I don't have direct access to any tasks running, so I wouldn't have anything on which to wait. My I/O thread is indirectly enquing tasks for the scheduler by running/rerunning a tbb::pipeline in it's own thread after a sufficient amount of data has been buffered. One solution would be for the main thread to loop over the pipeline, and block on some condition variable until the I/O thread has pushed data. However, if I'm going to block the main thread on a condition variable, I was hoping it would be possible to add the thread to the scheduler, and have it block on the internal condition variables of the scheduler. From reading the code it seems pipeline tasks are spawned as their own root under the hood. It did not appear that it was possible to access these tasks, nor to attach them to a task_group, at least not through any documented API. Thanks for your help.
0 Kudos
Anton_Pegushin
New Contributor II
990 Views
Hi, I would not say the problem you're trying to solve became clearer to me after this explanation :). Could you please provide some pseudo-code or better yet the skeleton of the real code, and explain what you're trying to achieve by adding external I/O thread and making main thread loop over pipeline - is it optimal subscription you're looking for or something different?
0 Kudos
Reply