Community
cancel
Showing results for 
Search instead for 
Did you mean: 
FredP
Beginner
54 Views

Using TBB with embedded scripting languages

Hello there!

I'm using TBB in a simulator, and have a task graph set up nicely to process the updates.
What I'm now trying to do s allow some user customisation of the behaviour in some of the components, which will influence exactly how the update works. To do this, I was looking at Lua (www.lua.org) to allow scripts to be injected.
For me, this poses a few questions, because I'll have an unknown number of objects within the task graph trying to run Luascriptsat unknown times. From a programming perspective, the simplest solution would be to launch a new Lua interpreter/state in each task where it is necessary, run the update and then move on.
However, I'm a bit concerned at 200K a pop that this would mean using a lot of memory and might also not be a good use of processor time, endlessly recreating and destroying interpreters. I could hold an interpreter permanently for each object to reduce the processing time, but there would still be a big memory overhead.
Or I could try a central repository of lua interpreters/states to grab from, but then I'm worried I'll lose performance from excessive locking.
So I wondered if anyone had any thoughts as to the best way to approach this problem, so that I can make the best use of TBB without killing my system. It's not that I don't think my solutions will work, it's just that I'm worried about that I'll end up undoing a lot of the benefit I'm getting from TBB in doing it...
Thanks in advance.

Fred
0 Kudos
7 Replies
RafSchietekat
Black Belt
54 Views

Cache them in thread-local storage.
jimdempseyatthecove
Black Belt
54 Views

Fred,

To expand on Raf's suggestion...

>>From a programming perspective, the simplest solution would be to launch a new Lua interpreter/state in each task where it is necessary, run the update and then move on

Assuming a single application can launch multiple Lua interpreters (e.g. application receives a handle or pointer to interpreter context .AND. multiple instances of interpreter within same application are thread safe). Then declare a thread local storage variable(s) to hold the interpreter handle/pointer and potential pointer to context (entries initialized to NULL). Then when any TBB task is about to call the Lua interpreter, the thread executing the TBB taskchecks its thread private Lua context variable(s) and if NULL it inits a new Lua context (and updates the thread private variables for the new Lua context for use on subsequent calls). Upon return from the Lua call, the TBB thread (thread executing Task making the Lua call) keeps the Lua context for subsequent calls.

Using this technique, you will create at most one Lua context per software thread, typically one thread per logical processor, rather than one context per object.

The only drawback is if your application shuts down TBB, that these Lua contexts will not automatically be shut down. i.e. applications that loop:(TBB init, run TBB tasks, TBB exit) would exhibit the creation of unnecessary Lua context. A typical application will not be constructed that way. If your app loops in this unusual way, then you will have to add code to resolve this issue.

>>Or I could try a central repository of lua interpreters/states to grab from, but then I'm worried I'll lose performance from excessive locking

The thread local storage of lua context is your "central repository". The overhead is

__declspec(thread) Lua_context_t* myLuaContext = NULL;
...
void YourTaskCallingLua()
{
if(!myLuaContext)
Init_myLuaContext();
...
myLuaContext->interptrt(LuaScript, args);
...
}

(not having Lua here, you will have to rework the Lua_context_t and init function)

Jim Dempsey
RafSchietekat
Black Belt
54 Views

"The only drawback is if your application shuts down TBB, that these Lua contexts will not automatically be shut down. i.e. applications that loop:(TBB init, run TBB tasks, TBB exit) would exhibit the creation of unnecessary Lua context."
Use TBB's TLS classes for easy control of their lifetimes?
Alexey_K_Intel3
Employee
54 Views

Alternatively you can cache the interpreter objects in concurrent_queue. When you need an interpreter, try_pop() from the queue. If unsuccessful, create one. When done with the interpreter, push() to the queue. Negative sides (comparing to TLS) are: somewhat bigger overhead to get an interpreter, and possibly more cache misses (since interpreters are shared by threads). Positive sides are simpler lifetime management (the app can destroy all interpreters when they become unnecessary), and not using TLS keys (can be important if the app needs a lot of those).
jimdempseyatthecove
Black Belt
54 Views

Alexey,

Use the concurrent_queue to contain the list of interpreters to shut down. And use TLS pointer/context for thread rememberance. IOW sketch code:

void SomeTask()
{
if(!p_InterpInTLS)
{
p_InterpInTLS = GetNewInterpreterContext();
DeleteMeLater.pushback(p_InterpInTLS);
}
p_InterpInTLS->DoWork(arg);
}

Where the concurrent_queue (DeleteMeLater) is queried upon exit from the TBB session.

Jim
FredP
Beginner
54 Views

Thank you for this and for all responses. I think Lua uses a single interpreter to process functions, but you can hold as many lua_State variables as you like to describe the current state of the variable. Presumably what I'll need to do is follow some of these ideas, but make sure I return the lua_State to some default state before releasing it back to the store?
Fred
jimdempseyatthecove
Black Belt
54 Views

Quoting FredP
Thank you for this and for all responses. I think Lua uses a single interpreter to process functions, but you can hold as many lua_State variables as you like to describe the current state of the variable. Presumably what I'll need to do is follow some of these ideas, but make sure I return the lua_State to some default state before releasing it back to the store?
Fred



You will have to assure that the single Lua can run concurrent contexts (i.e. frommultiple threads concurrently within the same process/application). The disscussion to date was from your assertion that it could.

If not, then you will have to serialize the Lua calls. (or run from seperate thread from TBB pool).

There is a distinct difference between saving/restoring different context states and passing what ammounts to be a context pointer to the state. The former will not permit concurrent access, the latter will.

Jim Dempsey
Reply