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

questions about task scheduler

I'm learning how to use tbb (version 2.1), and I have a few questions
I didn't understand when are threads created. does it happen whenI call task_scheduler_init? or when I create a root task?
when do I need to call task_scheduler_init? once in the program?
and what exactly is the difference between logical and physical threads?

0 Kudos
2 Replies
New Contributor I
Dude, all of these has been explained several times on the Forum; you can also consult the Reference Manual or simply the source code.

i) Physical threads are created (e.g. by a pthread_create() call) when creating the task_scheduler_init.
ii) Task_sheduler_init should be called before any other operations involving TBB, like parallel_for or parallel_do. I think in TBB 2.2 it's called automatically, but it's better to call it manually anyway.
iii) Physical threads are kernel threads. The word "physical" is just to distinguish them from tasks they execute. Oh, well, there is also something like green threads (see e.g. Wikipedia), but it's rathar a Java/C# stuff.

Black Belt
This is what is meant in the TBB world: "The threads you would create with a threading package are logical threads, which map onto the physical threads of the hardware." So if you have a server with two quad core CPUs each with two hyperthreads, you have 2 times 4 times 2 is 16 physical threads. You can run any number of logical threads on them, but TBB specifically tries to keep those numbers approximately equal, to avoid oversubscription.

I don't know exactly when TBB creates worker threads (maybe it's lazy about doing so, and it shouldn't matter), but their lifetimes are governed by the continued simultaneous existence of at least one task_scheduler_init object (these work like references to a shared infrastructure that includes a thread pool), so you should have at least one long-lived task_scheduler_init somewhere in your program, e.g., in main(). Once created, idle worker threads are blocked inside the scheduler, although one of them prefers to spin instead. A task_scheduler_init, despite its name, is not a function that you call, it's a class that you instantiate any number of times, as long as you don't let that number drop to zero unless you really mean it. It used to be that each thread not created as a worker thread by TBB itself had to have an explicit task_scheduler_init to be able to call a TBB algorithm, now I'm not sure whether you need only one long-lived instance or even none at all (?).

But I think that #1 at least has ii) mostly right. :-)