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

How to use thread local storage

michaelnikelsky1
Beginner
559 Views
Hi,

I am needing some per thread scratchmemory where I can store some temporary values. This scratchmemory needs to be fairly large (several MB or so), so I dont want to allocate that on the stack.

I guess this is what thread local storage is for but I have some trouble understanding how I can use the TBB combinable classes for it and which exactly I would need.

Are there any examples on how to use it? Assuming I have a main thread that executes several tasks, how and when do I allocate the memory? How do I access the memory? Do I need memory per Task-Type or can I have something like a global scratchmemory my different tasks can access to store temporary values?

Any help would be welcome
Michael
0 Kudos
5 Replies
jimdempseyatthecove
Honored Contributor III
559 Views
Michael,

This is one way to do it.

struct YourStruct_t
{
... // things you want thread private
};

__declspec( thread )
YourStruct_t* pYourStruct = NULL;

// called by each thread sometime before first use
void YourThreadInit()
{
if(!pYourStruct) pYourStruct = new YourStruct_tl
}

Note, you can have individual items with __declspec( thread ). I prefer to use an encapsulation within a stucture.
** generally you want to deferr the ctor until running in thread context **

Jim Dempsey
0 Kudos
michaelnikelsky1
Beginner
559 Views
Hi,

I need to do this with the TBB so I have essentially no info about threads, just tasks. Or can I just call

void YourThreadInit()
{
if(!pYourStruct) pYourStruct = new YourStruct_tl
}

inside a task?

Michael
0 Kudos
jimdempseyatthecove
Honored Contributor III
559 Views
Yes, you simply call that within your task.

__declspec( thread )
YourStruct_t pYourStruct = NULL;

Creates a thread private pointer named pYourStruct and initialized to NULL.
Then whenever your code dereferences the pYourStruct, it generates some additional code to obtain it from a thread private area. You can see this code in a dissassembly window.

Each thread will have a private copy of the pointer (and everything else you decorate with __declspec( thread )).
Each thread that uses this poiner must initialize the pointer and any corrisponding allocations within the struct.

You can use this technique with OpenMP theads, PThreads, Cilk++ threads, etc...

***
g++ uses a different syntax to mark threads private

#if defined(__GNUC__)
#define __TLS__ __thread
#else
#define __TLS__ __declspec( thread )
#endif
...
__TLS__ YourStruct_t* pYourStruct = NULL;

Jim Dempsey
0 Kudos
Alexey-Kukanov
Employee
559 Views
TBB Reference contains an example how to use enumerable_thread_specific template class. combinable template class can be used in a similar manner.

MSDN contains a page with an example of using Concurrency::combinable: http://msdn.microsoft.com/en-us/library/dd728079.aspx. Since TBB implementation is compatible, it should work with TBB as well.
0 Kudos
michaelnikelsky1
Beginner
559 Views
Thanks to you both, I will try that.
0 Kudos
Reply