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

Number of workers

velvia
Beginner
650 Views

Hi,

I am using TBB for multithreading in a program where each workers needs to have access to a different ressource (Think of an object that can be read and mutated by the worker). To do that, I am creating a pool of resources in a std::vector

std::size_t nb_workers{4}; // That's what I want to change
std::vector<Resource> resource(nb_workers, original_resource);
std::vector<bool> resource_used(nb_workers, false);
tbb::queuing_mutex resource_mutex{};

tbb::parallel_for(
    tbb::blocked_range<std::size_t>{0, n},
    [&](const tbb::blocked_range<std::size_t>& range) {
      // find a k such that resource is not used
      // and tell that it is used (setting resource_used = true)

      // do the work

      // release the resource k (setting resource_used = false)
    });

In order to work, nb_workers needs to be equal (or >=) to the number of workers threads used by TBB. I found a way to set the number of workers, but not a way to query it. So how do we get the number of worker threads?

Am I guaranteed that if I have n worker threads, there can't be more than n instances of the lambda running at the same time?

Best regards,

Francois

0 Kudos
4 Replies
RafSchietekat
Valued Contributor III
650 Views

That looks like a job for Thread-Local Storage, instead. Have a look at tbb::enumerable_thread_specific.

0 Kudos
velvia
Beginner
650 Views

Unfortunately, the problem seems unsolvable with tbb::enumerable_thread_specific.

In the previous code, the type "Resource" encapsulates a working directory for the computation. We should have:

directory_0

directory_1

directory_2

directory_3

on a system that can launch 4 working threads. What I want is that each task is assigned a directory where it can work. So every task should know something that could be considered as the "thread number" it is working on.

0 Kudos
RafSchietekat
Valued Contributor III
650 Views

If you've taken care to configure task_scheduler_init early enough in the lifetime of the application thread starting the work, then it will have an arena where at most that many threads can be active at the same time. However, they won't necessarily be the same set of threads all the time, so you'll have to get and return a handle to a resource without reference to thread identity.

Take care not to keep using the same resource across possible stealing opportunities: recursive parallelism is great for performance, but in this case you have to observe the boundaries of the "sequential basic blocks", so to say.

(2016-01-05 Added) Apparently you can get a bounded index after all by calling tbb::task_arena::current_thread_index(), which should be usable to identify a resource within a "sequential basic block", again so to say. Since threads can dart in and out of arenas (well, they tend to linger), different threads may be associated with each index over the lifetime of the arena. I don't see a way to interrogate an arena about how many threads it uses, though; as stated above, you just have to be sure to use task_scheduler_init early enough in the main thread or in a new application thread, before any TBB scheduler-related calls, and remember what value you used.

(2016-01-13 Edited) Fixed typo.

0 Kudos
velvia
Beginner
650 Views

Hi Raf,

We decided to set the number of threads at run time with task_scheduler_init and save the value for future usage. It works fine this way.

Thanks for your help.

0 Kudos
Reply