- Home /
Alternative for semaphores in Unity?
I want to parallelize some code so it runs faster on multiple processors, like this (pseudocode in C++):
semaphore sem;
thread_safe_type result;
int main(char **args)
{
sem = new sem();
job();
printf("result: %d", result);
delete sem;
return 0;
}
int job()
{
for (int i = 0; i < 10; i++)
run_thread(task());
p(sem);
return result;
}
void task()
{
result.dostuff(); // do some stuff to "result"
v(sem);
}
Essentially I have some code that needs to be run on all entities within the 30ms frame. I thought I could speed up execution if I ran them in parallel. Coroutines can do something like that, but there is no "semaphore", and I can't do a "yield return" outside of a coroutine.
Hmm.. what to do?
Answer by Owen-Reynolds · Sep 24, 2012 at 02:24 PM
AFAIK, coroutines don't run in parallel. The dispatcher runs one until it finishes or yields, another ... . So you never have to worry about race conditions like two guys saying: `n=cows; n++; cows=n;`. But, breaking into coroutines "just because" won't gain any speed.
You can safely use bools and ints as informal semaphores and mutex variables. A Wait can safely be done with `while(soundPlaying) yield; soundPlaying=true; ... soundPlaying=false;` (which would have a race condition in parallel.)
The main advantage of coroutines is ease of reading (like "over the next 20 frames, decrease alpha".) And when you want to wait 2 seconds, yield 2.0 (really sleep) runs faster than `if(Time.time>doStuffTime)` each frame (but mostly for readability, there too.)
Answer by whydoidoit · Sep 24, 2012 at 02:29 PM
To add to Owen's answer - you can use .NET threads and thread locking operations in Unity - you need to import the System.Threading namespace. Be aware that only the main thread can access any Unity objects - other threads can do calculations and use other .NET methods (like talking to servers etc). The simplest method of locking in .NET is to use the C# lock keyword which provides a critical section:
public MyClass something;
lock(something)
{
//Critical section code goes here
}
Coroutines are not threads - they work exactly as Owen describes - non-pre emptive main thread routines basically.
Say W., ... I've often wondered. As I understand it, one can write a plugin that runs natively on iOS (or $$anonymous$$ac I guess). (I've never had any reason to do this, other than trivial plugins like the usual "use camera" etc.)
So, as I understand it you can write a normal XCode, cocoa, Objective-C thingy and it runs as a plug in from Unity. For example, you need to do a lot of math processing, so you do it that way. Now, can that plugin itself - the "offloaded calculation part" - utilize multi-processors (I love that term - sounds like a superhero. Here comes $$anonymous$$ulti!-Processor!) as much as it wants, just as normal, when working in iOS (or $$anonymous$$ac)? (Thus, basically these days using GCD etc etc.)
Or is that kind of forbidden in some way by the general purpose "no threads w/ Unity" jazz? .. perhaps it will collapse to one thread anyway, or something? (I've no idea.)
Similaty indeed ultimately a Unity app is just a big old thingy launched in an openGL window with an iOS framework app, could you in fact make an iOS (or $$anonymous$$ac) app - picture an engineering app or something - that uses all the cores in the usual way (w/ carefully written parallel code), but also calls the chubby Unity section as usual .. or indeed again would that fail in some way because of a Unity ban on threadism?
I've always wondered about those two, err, parallel ideas??
I'm no expert on plugins - but there is no reason I can think of that would stop anything spooling off multiple threads and therefore taking advantage of the fact that there may be multiple processors (or just because you really can't think of a good way of getting two things to happen in a parallel fashion).
You just can't access anything in Unity from anything that isn't the main thread - I understand that "before my time" you could actually access them and the consequences were usually pretty unpleasant - you just can't do it now - it raises an exception. There are of course lots of things you could do - like calculate mesh vertex positions, run AI logic that touches only your own classes etc. Things like the A* Pathfinding Project do that to improve the performance.
That all said, if you've got a single threaded processor like a 3GS or iPhone 4 then it will be slower due to the need to switch the context. Threads aren't a "very good idea" really. Brilliant for talking to a server and getting some response which is generally a "hard thing to do sequentially" (though coroutines help in Unity and await helps in C#4) so long as the thread spends most of its time asleep or not doing much in case that second processor isn't there or is already busy.
Gotchya. Thanks for that.
Yeah I was thinking of situations where you might actually usefully do parallel processing, for some calculation.
You know, I was also wondering if it would actually speed the Unity game's execution?
I simply don't know ... does the Unity engine utilise multi-cores where they are available? on desktop or ipad3 ?
Is the Unity engine itself very parallel?
I figured if the answer to that is No, and, if you wrote the plugin part in a very GCD manner, it might encourage the overall situation to be more parallel ..... if that makes sense.
(Indeed - if the Unity engine is highly-not-parallel, it would be fantastically advantageous, I guess, to offload anything, at all, to a plugin, because (I assume) that would lead to much more use of the extra cores.)
(I have read that the current Unity editor/compiler/etc per se on your $$anonymous$$ac, nowadays is pretty threaded for performance. But I have no clue about how the engine itself works ... when "Ski Safari" is playing on your iPad3 is it highly-not-parallel, or did the Unity dudes try to make it thready where possible? I just don't know, at all.)
I guess one key question here of which I am totally clueless, when the Unity engine is running one's game on a multicore device, is it very parallel? Or is it very-not-parallel?
Come to think of it that's a very basic question not to know! Heh! Cheers
Your answer
Follow this Question
Related Questions
Confused about using Update vs. Coroutines 2 Answers
WaitUntil Combined With sqrMagnitude is not working? 1 Answer
Wierd issue with Coroutines? 2 Answers
C# Coroutine help 1 Answer
Threading in Unity 6 Answers