Threads: What? Why? How? How exactly? Why so many?

(Using boost::threads)

Why threads? Because:
  1. They help us benefit from dual-/multi- -core/-processor hardware, and...
  2. It is simply more correct and elegant to code non-synchronously those things which do not need to be synchronous, and viceversa. Makes sense?. It even raises the bar in terms of code quality, –forcing one to hunt unnecessary dependencies with that much extra care.
What parts of the engine should be on separate threads? How do you break the thing up?

What you don’t want is to have cores running the same code on subsets of the data. That’s the dumbest use of multiple cores. Take Physics and AI, for example: they impose cross-data dependencies (things bump into each other; AI’s see one another) causing each thread to often need to access data that other threads are using... And the code caches of the cores are mostly wasted, all cache-ing the same code; –not to speak of the wasteful misuse of branch prediction and return caches.

The two telling signs of good threading breakup is when no code AND no data are being shared by any two threads.

The other metric is load balance, of course. And to achieve good load balance, where each thread runs different pieces of the code, is by fine-tuning; and the only way to fine-tune is by having as many thread-candidates as possible to begin with.

Thus, the title of this section should be be read as “Thread Candidates”, more so than “Threads”. For each of them, the code includes #if/#else/#endif’s to easily switch these items into threads, or back into non-threads. The ultimate goal would be to have 4 well-balanced threads, by experimentally combining thread-candidates. That’s why so many...

Any other hints of good thread candidates?

Sure. Hardware. Physics might, in some machines, run on a PhysX card or some co-processor. Co-processors are asynchronous animals. Makes sense to wrap asynchronous hardware in asynchronous software. Same goes for AI, sound, network; even file-loading...

And not only hardware... User input is asynchronous too.

About half the thread candidates, as of this writing, are wrappers on asynchronous externals. They are marked by “(Wraps <whatever>)” in the comment lines.

What about single-core users?

That’s why we have a “main thread” that is real-time priority, yet does very little and then Sleep()’s...

  1. Its first mission is to get the other threads started.
  2. Its second mission is to monitor the running time of the other threads, and make necessary adjustments so that each frame is finished on time for video card upload.
 
ref/why_threads.txt · Last modified: 2006/10/06 15:57 by chuck_starchaser