The XBox 360 uses a 3.2 GHz PowerPC CPU with 3 hyper-threading-capable cores, so you get 6 hardware threads which can run in parallel. This is not the same as a six-core-CPU because the hyper-threading units share most of the hardware circuits - if only one thread is running on a core, it can process 2 instructions per cycle, but if two threads are running on a core, each thread can only process 1 instruction per cycle. Using all 6 cores is still faster than using just 3 of them.

The XNA Framework uses hardware threads 0 (first core, first hyper-threading unit) and 2 (second core, first hyper-threading unit), so XNA games can use threads 1, 3, 4 and 5 for a total of 4 threads at the same time. Your Main() is called in hardware thread 1 (first core, second hyper-threading unit).

|       0      |       1      |       2      |       3      |       4      |       5      |
|              |              |              |              |              |              |
|      XNA     | User, Main() |      XNA     |     User     |     User     |     User     |
| Core 1, HT 1 | Core 1, HT 2 | Core 2, HT 1 | Core 2, HT 2 | Core 3, HT 1 | Core 3, HT 2 |

Threads are not automatically assigned to different cores and even the ThreadPool class will execute of its work items in threads running on hardware thread 1. The only way to execute a thread on a different hardware thread is to manually move it there using the Thread.SetProcessorAffinity() method which only exists when your game is compiled for the XBox 360.

The AffineThreadPool creates one thread for each of the XBox 360's free cores, so any tasks you schedule there will truly run in parallel on the XBox 360. On a desktop PC, it tries to mimic this behavior as close as possible by also creating one thread for each hardware thread in the system (eg. 4 on a quad-core CPU, 8 if said CPU has hyper-threading). Each thread is assigned a preferred core (basically a suggestion for the OS thread scheduler - using hard affinity is not a good idea on the PC, read this).


Using the AffineThreadPool is very simple because it has the same public interface as .NET's own ThreadPool class. Just call the static QueueUserWorkItem() method on the AffineThreadPool instead of the normal ThreadPool class, no further changes necessary.

// Schedule one 'Hello World' on each available hardware thread
for(int index = 0; index < AffineThreadPool.Processors; ++index) {
    delegate(object state) { Console.WriteLine("Hello World") }

// Wait until the hello worlds have been printed.
// (don't do this at home. Use proper thread synchronization!)


Compared to the normal ThreadPool, the AffineThreadPool has a very limited number of threads available, so you shouldn't use it for tasks that might block or sleep because it would become congested very quickly. It is encouraged to use the normal ThreadPool for threaded tasks that might block, like loading resources from the hard drive, waiting for another thread to finish, sending data to the GPU and so on.

The AffineThreadPool should be used if you have a processing-intensive task that can be parallelized, such as updating a large data set. Partition the task into AffineThreadPool.Processors sections and queue a user work item in the AffineThreadPool that processes each section. This way, you will make optimal use of the available processing power on the XBox 360.

Last edited Oct 6, 2009 at 11:11 AM by Cygon, version 8


No comments yet.