3
\$\begingroup\$

So I've been playing around and developing in C++ for a couple years now and have built a very simple C++ game engine for learning purposes. I now want to try and develop a simple 2d, stick figure fighting game for the windows platform. Up until now I have only been focusing on single core development (to keep things simple while learning). I would like to try and develop a game from start to finish and maybe try and release it on some version of a steam website. I know I always learn more when setting higher goals and trying to create a project from start to finish. I will be utilizing some third party libraries such as SDL (or some equivalent) but want main control over engine systems and overall architecture.

Since my game will be a simple 2D fighter on a specific platform (windows) with a goal of 30+ fps is it necessary to try and multi-thread some tasks? Would I be able to accomplish everything I would need to by utilizing just one core? I ask because I know multi-threaded programming is a huge topic and I would have to spend a lot of time researching and learning before actually developing anything substantial.

Edit: This topic is not related to the above duplicate since I'm not asking where I should look for multi-threaded resources, but if I should even consider multi-threading in the first place for my simple game. Want a basic idea of how much can be done with a single core game.

\$\endgroup\$
8
\$\begingroup\$

Generally it's best not to over-engineer, solving problems you may not really have.

If you want to make a "simple 2D fighter," well, remember we had those on the NES and even earlier.

Even a single core on today's machines is vastly more capable than the systems on which you first learned to love fighting games, I'd wager.

So, have you encountered any trouble that suggests to you that your game might need additional threads to keep up on modern hardware?

If not, it might not be a problem you need to solve just now.

Focus on making an enjoyable game first, and if your early profiling suggests performance problems, use that information to ask a specific question about how to overcome those particular issues.

\$\endgroup\$
  • \$\begingroup\$ Ya, that's generally what I would do. I guess in this particular instance I'm trying to figure this out now (as best I can) as me realizing multi-core processing is needed later on in development would result in major architecture redesign. Though let me ask you, assuming I create a resonably architectured game with low dependecies (through an ECS/data oriented design), how difficult is it generally to go from a single core architecture to a multi-core one? Do multithreaded programs generally have vastly different program structure? \$\endgroup\$ – Jason Mar 24 '17 at 3:45
  • \$\begingroup\$ It sounds to me like you're curious about multi-thread development and looking for validation. You don't need our permission. If it's a skill you want to develop, go for it — you don't need to justify it as a developmental necessity for it to be worthwhile. Make games the way you want to make them. :) \$\endgroup\$ – DMGregory Mar 24 '17 at 3:47
  • \$\begingroup\$ Haha, I am. Just not sure if nows the time I want to go for the up-front learning cost of multi-threaded programs but we'll see. Thanks for your input \$\endgroup\$ – Jason Mar 24 '17 at 3:49
4
\$\begingroup\$

Rule number one of multithreading: Don't even think about it, unless you really need to use multiple CPU cores for performance reasons*. Multithreading opens up a whole can of worms of obscure and impossible to reproduce bugs:

  • Race conditions! Because you have no control over the thread scheduling of the OS, you have no control over the order in which things happen. You might assume that a certain task takes much longer to complete than another and build on that assumption. But in one of a million executions that assumption is wrong, and an obscure bug happens which is impossible to reproduce.
  • Synchronization issues! When one thread modifies data while another thread is in the process of reading it, the thread reads a mixed state of old and new data. This can lead to really obscure bugs which are - again - almost impossible to reproduce.
  • Deadlocks! The two problems above can be avoided by certain synchronization and locking techniques which are available in most programming languages. Unfortunately these features take a lot of knowledge and experience to use correctly. When you use them incorrectly, you will quickly run into deadlocks: Two threads both blocking their data structure and both waiting for the other thread to release theirs. This will lead to an infinite loop and cause both threads to freeze.

Also, keep in mind that creating threads isn't cheap. Spawning a thread and switching between thread contexts are expensive operations for the operating system. So using too much multithreading can even reduce performance. You should only use multiple cores when you have tasks which take a long time to complete and don't need to communicate much with other tasks while they are being completed.

*) Exception from this rule: Waiting for I/O of files, network or user input. But in that case you shouldn't write your own multithreading code. Use asynchronous APIs with callbacks provided by your platform or a library when you can. These use multithreading "under the hood", but hide the nasty details from you.

\$\endgroup\$
  • \$\begingroup\$ To your first point: Not sure if you saw my comment above but in your experience, given a reasonably designed and decoupled system, is it difficult to switch from a single core to multicore design midway? Can I just implement some async calls around some performance bottlenecks here and there? \$\endgroup\$ – Jason Mar 24 '17 at 11:28
  • \$\begingroup\$ @Jason It's hard to predict in advance what your performance bottlenecks will be and if parallelization is even able to fix them. Not every problem is trivially parallelizable (see last paragraph of answer). \$\endgroup\$ – Philipp Mar 24 '17 at 11:41
  • 2
    \$\begingroup\$ @Jason it is very hard to make sure that shared state is mutated consistently in the presence of asyncronicity. It is much easier to either not share, or not mutate. Whether you consider that to be part of "a reasonably designed system" depends on your definition of "reasonable design" \$\endgroup\$ – Caleth Mar 24 '17 at 11:44
  • \$\begingroup\$ @Jason Along the lines of what Caleth said, I've worked on software which will never be multithreaded, even though they need the performance of multiple cores. It was perfectly well architected, just architected in a way which made it virtually impossible to take the jump to multithreading. It all depends on the specifics of your particular architecture. \$\endgroup\$ – Cort Ammon - Reinstate Monica Mar 24 '17 at 18:10
  • \$\begingroup\$ If you want to do multithreaded development I highly recommend you not start learning your first program intended for delivery to customers. Start with a few smaller programs to learn how multithreaded programming works first. \$\endgroup\$ – Cort Ammon - Reinstate Monica Mar 24 '17 at 18:12
0
\$\begingroup\$

The question you need to ask yourself is: "are you developing a game, or are you developing an engine?" (Doesn't have to be a binary answer, but you should definitely be aware of your place on the spectrum).

If you're developing a game, then the answer is no. If your game is fairly straightforward, then more threads will only get in the way of the game development with no real added benefit.

If you're building an engine, then the answer is yes. You may not need threads for strictly performance reasons, but adding parallel capabilities into your engine will make it flexible if you want to add features that may require it (networking, costly calculations, file I/O, etc). You don't have to go crazy and thread everything, but always take a step back and say "Could these things run at the same time with minimal effort?" The game will only suffer in the sense that you'll have to spend more effort into feature implementation rather than game play code.

Either way, don't be discourage from giving it a try. Threaded game engines aren't necessarily complex. It all depends on you want to multithread / how granular your threaded data is.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the straight forward answer as well as the encouragement ;-) \$\endgroup\$ – Jason Mar 24 '17 at 19:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.