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

Avoid local() calls for enumerable_thread_specific variables

Lin__Weiyang
Beginner
539 Views

I have code structures like the codes below:

class Foo;

static const int big_n = 100000;
tbb::enumerable_thread_specific<Foo> foo_ets;

void func1()
{
    auto& foo = foo_ets.local();
    foo.do();
}

void func2()
{
    for (int i = 0; i < big_n; i++)
        func1();
}

void func()
{
    tbb_parallel_for(0, big_n, [](int i)
    {
        func2();
    });
}

 

Now I want to avoid local() function calls by passing parameters hierarchically:

void func1(class Foo& foo)
{
    foo.do();
}

void func2(class Foo& foo)
{
    for (int i = 0; i < big_n; i++)
        func1(foo);
}

void func()
{
    tbb_parallel_for(0, big_n, [](int i)
    {
        auto& foo = foo_ets.local();
        func2(foo);
    });
}

 

Is there a simpler way of doing this? I have many places with local() function calls if I do not pass Foo as a parameter, but the code would be messy if I do. I have been looking for possible usage of an array with size equal to the number of threads, and use thread-id to access the thread local variable, but it seems tbb does not provide that (in contrast to omp_get_thread_num() in OpenMP).

0 Kudos
1 Reply
Alexey-Kukanov
Employee
539 Views

You can use tbb::this_task_arena::max_concurrency() and tbb::this_task_arena::current_thread_index() to implement OpenMP-style custom thread local storage. The first function gives the upper limit for the number of working threads, and the second one gives an index of the current thread within that limit.

Updated: Actually, it would be interesting to know why using foo_ets.local() wherever needed seems inconvenient to you.

0 Kudos
Reply