Jeff Andrews wrote a great article about multithreaded game engines over on Whatif.intel.com. These are the concepts that the Smoke (n-way threaded game framework) demo was built on. One of the readers, Josh, brought up a good comment (check out the comments at the bottom of the article). One of the questions in his comment really got me thinking about lock step versus free step. Which is better? Which is easier? Which does Smoke use?
The last question is the easiest: Smoke uses lock step. Jeff goes into some good detail in section 2.1 about these two execution modes. Lock step just means all systems update at the same rate. For each frame, all systems update and sync. If a system takes longer to run, the other systems have to wait for it to finish. This is the biggest complaint against lock step. In free step, all systems run at separate frequencies… they update and sync based on events.
Lock step does have its advantages. It’s easier to understand and code. It’s definitely easier to debug (you can check for sanity at each sync). As Josh points out, lock mode doesn't suffer from the possibly increased frame latency of free step. But lock step can waste resources if other systems are waiting around… or does it?
First attempts at threading games mostly involved functional decomposition; just put each system (graphics, IO, physics, etc) on a separate thread. If a system finishes updating and has to wait for another system, that system’s thread would sleep. This is wasting resources because that thread could be doing more work… this is the major fault of lock step. However, Smoke uses a job pool and worker threads to support functional and data decomposition. So… if a system finishes its work, that thread can work on jobs for other systems! Now we are not wasting resources on lock step ^_^ Score! There are a few exceptions, if a system doesn’t divide its work properly and takes a long period of time to finish… then the worker threads could end up unemployed.
I have want to rework Smoke to run in free step mode. But I am comfortable with lock step. It’s easy for me to understand and explain… and I can easily map out the latency between the systems. I wonder if anyone will take up the challenge and get Smoke working in a free step mode… I’d love to hear if anyone out there gives it a try ^_^ I’d also like to hear more about peoples’ experience on free or lock step. Which do you like? Is free step worth the possible headaches (especially with a large team of developers)?
While running free sounds nice. I think I’ll keep my projects locked down for the near future.
For more complete information about compiler optimizations, see our Optimization Notice.