Sunday, 23 August 2009

ParallelTasks, Multithreading on Xbox

I think I'll start off by releasing a project I've been working on the past few weeks.

I'm sure you have all by now had a look at the new Parallel Extensions (ParallelFX) coming with .net4.0 and VS2010. At its core, it's a multi threaded work scheduler, in a similar vein to the ThreadPool, however extended with a rich API and much better scaling as the number of cores is increased.

I would have loved to simply use this library on all my projects, but unfortuneately it does not seem that they will release this for the Compact Framework on the Xbox360. So no multi-threaded Xna games :(. Even if they do port it, their system creates many many allocations, which can be catastrophic with the CF non generational garbage collector.

Fortunately, I love writing parallel code, so I had a go at writing my own (albeit cut down) version of it.
I'm going to upload it along with all the source code, and I can only hope if anyone else decides to work on a similar project in the future, they may learn something here.

I had a few requirements:

  1. Must support task parallelism.  The user must be able to tell the system to go off and do a unit of work, and come back later to check that it has been done.
  2. Must support data parallelism. I wanted the user to be able to do loops where each iteration may occur in parallel with others, so that they could do very fine grained parallelism where potentially every piece of data could be executed on another thread.
  3. Must compile on the Compact Framework. The whole point of this is so I can use it on the Xbox. This turned out to present many problems, as there are quite a few synchronisation primitives missing, such as Monitor.Pulse..
  4. Must cause minimal heap allocations. It's no good if each task scheduled allocates new objects. The xbox does not have a generational garbage collector, and allocating while the game is running can cause terrible framerate hickups each time the GC kicks in.

The scheduler works around executing IWork items as fast as it can across all available cores. In return for scheduling an item, you get given a Task struct. This struct will contain methods for waiting for a task to complete, as well as properties to check on the status of a task. New heap allocations are not made for each work scheduled.

You can schedule tasks from the static factory methods in the Parallel class, a la ParallelFX. There are methods to start new IWork items, as well as overloads which accept delegates, and a couple methods for executing loops in parallel.


// schedule a new task to do the work Foo
var task = Parallel.Start(Foo);

// Loop over a collection and do some processing on each item, in parallel
Parallel.For(0, items.Count, item => item.Bar());

// Wait on the task, so we can continue knowing that it has finished from this point on
task.Wait();


Here are the xna game library projects. I might a bit about how some of it works in future posts. Hope it's useful to someone.

No comments:

Post a Comment