9

I'm often tempted to break the game I'm working on to try a parallel-tasks based architecture, but that don't seem a big requirement for my project so I avoid this for the moment. I'm planning to just try it in a toy project first, to "play with the concept."

Now, what I'm asking is, as lot of (non AAA) games do not require really really high performance, it feels like using a task-based engine isn't worth bothering until... what cases?

At the moment, I'm only guessing that it's necessary when you really need to exploit maximum performance of the (multi-core) hardware. Is there other cases where it's a good idea to use task-based engine? Or maybe, for new projects, it's always good to start with a task-based engine?

Klaim
  • 2,624
  • 1
  • 26
  • 37

3 Answers3

15

If your game is going to be remotely hardware intensive then you need threads to cope with all modern hardware; future CPUs coming out in the next year or two are starting to make 4 cores the minimum and up to 16 cores common for enthusiast/performance markets. If you're doing any multi-threading at all, definitely do a task-oriented architecture as any other threading model is inherently broken for forward-looking game engines.

Now keep in mind that by "tasks" I mean "jobs" and not "separate threads for different engine subsystems." You absolutely completely do not want to do something like having one graphics thread, one physics thread, one AI thread, etc. That doesn't scale beyond a tiny handful of cores and it doesn't actually gain you any real parallelism anyway. Physics shouldn't run more than one update per AI update (you want your AI to be able to react to physics events), and graphics has almost nothing new to render if physics hasn't run, so each subsystem naturally runs in a sequenced order. You don't even get any benefits out of having physics update the next iteration of the simulation while graphics is running the current iteration because there is so much data shared between the two that you either need lots of duplicated data structures (and the costs of copying from one to the other) or you end up with bad lock contention in shared data structure synchronization code.

What you want is to do is this. Create a thread spool. Run your game loop with the classic sequence of subsystem updates. However, for each subsystem, separate the workload into distinct separable batches, and distribute those to the thread pool. Wait for all jobs to complete before running the next state of the game update loop. Some subsystems may have multiple substages; e.g., graphics may issue a series of jobs to do culling and then a second series of jobs to do render queue creation. This approach avoids the synchronization problem of the first approach, scales to much larger numbers of cores, and frankly is just easier to code, debug, and maintain.

Sean Middleditch
  • 41,807
  • 4
  • 89
  • 132
  • Thanks for the advises on how to build this kind of engine but I'm already well documented so it wasn't necessary. It's more the "when is it worth it" question that I ask. I think it's still a good thing to point those informations for those whot don't know so don't remove them :) – Klaim Jun 07 '11 at 10:09
  • Sounds very reasonable – Den Jun 28 '13 at 11:04
  • Much like Apple, once you get used to jobs there's no going back =) This is a good architecture suggestion for any new engine. – Patrick Hughes Jun 09 '17 at 18:31
  • @SeanMiddleditch Aren't you just changing the granularity of threading that way? Instead of just a thread per system (which is indeed not that scalable, some systems are much more power hungry than others and there can also be many more systems that available cores) you're doing potentially multiple threads per system. So you are fine-tuning the granularity of data each thread acts upon. Not sure how this will play out, but I have nothing better to add either. Do you still hold this opinion after 7 years? Thanks. – KeyC0de Aug 30 '18 at 11:15
  • 1
    @Nik-Lz: no, because "multiple threads per system" implies that you know what the threads-per-system should be. Should you have 2 threads for rendering and 3 for physics? How many for AI? Wouldn't that all depend on the specific scene and even where in the scene the player is looking and what's going on in the moment? A job system easily dynamically scales to the immediate needs rather than binning a whole thread to a subsystem that may not need it right now. – Sean Middleditch Sep 03 '18 at 16:37
7

Threading is used in two situations:

  1. When you have heavy work to do but need user responsiveness to be maintained.
  2. When you need the power of more than one processing core on your favourite platform/minimum requirement.

If you can reasonably expect either or both of these things to be necessary, then go for it. Else, don't. Of course, nobody is going to stop you from threading for fun because you can, or to poke around and investigate it, but in terms of doing threadng for the benefits of actually gaining a multi-threaded application, then the two use cases above are pretty much it.

DeadMG
  • 5,518
  • 3
  • 27
  • 40
  • 2
    +1 for responsiveness: one of the requirements for my main project is to have no loading screen, continuous experience for maximum immersion. That's a good point. – Klaim Jun 07 '11 at 12:02
  • 1
    +1 exactly why I used multiple threads in a puzzle game: heavy work (checking millions of combinations) without freezing the UI. – ashes999 Jun 08 '11 at 11:02
  • "no loading screen, continuous experience" - you'll have to build your entire architecture around this idea, it's a break from the "load one level and play in it, then load another level" design that most small engines use. – Patrick Hughes Jun 09 '17 at 18:29
0

there are two uses in multithreading, one is to enhance your program performace and the other is to let the program run when there is a large process in progress. for example when you are trying to load some data it's bothering if your program hangs up, so you may use another thread for loading and keep the main Thread free to continue main loop. enhancing performance using threads is on the other hand somthing really hard. since usually you do every thing in a linear process and that is something in contrast with parallel processing. and you always have to use your main thread for graphical device updates that makes it even harder to split tasks between threads.

Ali1S232
  • 8,687
  • 2
  • 40
  • 59
  • 1
    Threading isn't hard. :) It's just something that many people never learn to do properly, so they think it's hard due to inexperience. Especially in games many of the algorithms and core data structures are quite easy to handle with multiple threads. Physics updates for instance can be broken into islands of objects, and each farmed out to a different thread for integration and resolution. Likewise, culling of objects for graphics is pretty much completely free of read-write data access contention. – Sean Middleditch Jun 07 '11 at 09:51
  • @seanmiddleditch I didn't say using threads itself is a hard thing but managing to use threads effectively and balanceing them to share same load is something dificault. – Ali1S232 Jun 07 '11 at 10:03