views:

67

answers:

3

Let's say i have a Domain Model that im trying to make compatible with multithreading. The prototype domain is a game domain that consists of Space, SpaceObject, and Location objects. A SpaceObject has the Move method and Asteroid and Ship extend this object with specific properties for the object (Ship has a name and Asteroid has a color)

Let's say i want to make the Move method for each object run in a seperate thread. That would be stupid because with 10000 objects, i would have 10000 threads. What would be the best way to seperate the workload between cores/threads?

I'm trying to learn the basics of concurrency, and building a small game to prototype a lot of concepts.

What i've already done, is build a domain, and a threading model with a timer that launches events based on intervals. If the event occurs i want to update my entire model with the new locations of any SpaceObject. But i don't know how and when to launch new threads with workloads when the event occurs.

Some people at work told me that u can't update your core domain multithreaded, because you have to synch everything. But in that case i can't run my game on a dual quadcore server, because it would only use 1 CPU for the hardest tasks.

Anyone know what to do here?

Specification in reaction to Deltreme:

You are absolutly right, and your method will work in most cases. BUT, The threads have to update the location of the spaceobject in the Space class.

Let's say i have 2 SpaceObjects next to eachother, they are moving towards eachother. 1 Object is in thread A, the other is in thread B. Once i update the objects the threads have to write to the Space together to write the new values in the Tile (an individual part of Space). That individual call cannot be done in different threads at once, cause the Space object would burst...

What could happen is a collision, and i could write an Event that occurs if their are 2 ships @ 1 tile. That's not the problem.

I'm thinking that in the case of 10000 ships, the CPU would primarily be switching between threads and not running them all togheter. So in the interest of performance, i want to be able to to "everything" simultaniously

A: 

I assume you create snapshots: at Situation A each SpaceObject is located at some Location, and after each SpaceObject has Moved to another Location, you get to Situation B.

With 10000 objects, the transition between Situation A and B is 10000 Move calls. Move() sounds like a rather fast method, ie. using current Location and direction to create a new Location.

In that case, you could create 10 threads (or use the ThreadPool) and assign say 50 SpaceObjects to it, for which it will then calculate the new Locations. If a thread is done, and there are still SpaceObjects that need to be Moved, you assign another 50 to that thread.

deltreme
See my updated question
Thijs Cramer
+1  A: 

You can use System.Threading.ThreadPool or the upcoming Task Parallel Library to automatically manage your thread counts according to the number of cores available.

One possible approach to the concurrency problem is to lock only other SpaceObjects that your current SpaceObject could interact with. This would provide adequate performance in most cases, but processing large interactions would be done by a single thread in the worst case. How much do you need to lock ultimately depends on your simulation parameters. If objects can't completely pass through each other within a single tick of the timer, you can get away with just checking for overlapping objects. For fast-moving objects you would need to detect intersecting movement vectors.

Hirvox
Thanks, thats helpfull, it would mean that i can optimize 0% in the worst case, and 100% in the best case scneario's. Do you know of any way to improve these odds more?
Thijs Cramer
A: 

As Hirvox says, the ThreadPool is a good choice. I would avoid thinking in terms of a thread per SpaceObject, but rather a think of it as a big queue of SpaceObjects that all need to update their position on an interval, and then use threads to do the Move calculation the move as you dequeue the objects; this is well-suited for a ThreadPool. It may not be an actual queue but could instead be a sorted dictionary, but you get the idea.

When you're done with the Move calculations, then process any collisions using a similar approach. One way to handle fast movers is to work on a very short interval, updating fast movers every interval, medium movers every other interval or so, and slow movers every tenth interval.

Just for fun, look into using the video card for your calculations - the higher-end GPUs are optimized for gobs of simultaneous calculations.

ebpower