Multithreading and Multiplayer

Started by
9 comments, last by wijnand 17 years, 2 months ago
Heya guys, As some of you might know (I hope!) a few friends and I are making a small DirectX engine named Vyper. Since I have been thinking of a space sim where I want minimally 400-600 fighters on the screen and 10 Capital ships I want to ensure that the engine as a basis is very strong. Because most high end machines are now slowly but surely getting Dual Core I thought Multithreading was a solution the the problem. But the question ofcourse is, how do you make multithreading work? Our engine uses the WIN32 api so making threads with the WIN32 APi would make sense I assume? My biggest question ofcourse is, would this make the program more efficient, and is it hard to make it work out If its a 10% increase in speed but it means 200% more time to get it working, its beter to pan it. Furthermore my attention is focused on Multiplayer, and basically I realized that DirectPlay got canned, but what other API that is either Microsoft supported can I use? I was thinking of Winsock, but the prospect of having to write the entire call stack and server would be daunting to say the least. I found some articles, but most of them are really C++ and using Winsock, I assume there is no other possibility to do it with ?:) Thank you for the time :d
Advertisement
Multithreading is definitely an interesting topic and is fun to learn. It's very challenging for games and is most definitely not a magic bullet. It's very easy to make your program slower with more threads, for instance.

The core of the problem is that a game is by nature often a serial process: i.e. you must update physics before AI and such. Multithreading will only help you in those cases where order of operations is not important (unrelated systems, 2 systems that are read only, etc).

There's also a suite of horrible bugs that are unique to multi-threading: 2 threads can simultaneously write to the same piece of data and invalidate everything (it won't crash but your data will be wrong), you can deadlock (permament freeze) waiting for a mutex, you can have bugs that only happen 1 out of 1000 runs of the game, memory stomps that write to random places in memory, etc.

It's somewhat safer in console development only because the target platform will almost always run the code at exactly the same speed. On PCs you'll find that certain multithreading bugs only have bad effects on specific machines with specific hardware configurations. So testing to find the bugs means all kinds of craziness: random pauses/yields in your code to try out different thread timings, etc.

You probably want to play with multi-threading as an academic exercise for a couple weeks/months before you even begin to start putting it into a game. And the game should be designed form the beginning to support multi-threading; trying to multi-thread an existing engine is a lesson in severe pain.

-me

[Edited by - Palidine on February 13, 2007 3:50:29 PM]
As to Winsock, its really not that tough. I started with DirectPlay, for somereason, and switched to WinSock soon after that.

Well, I have never worked with IOCP (I've tried many times, and failed because I just wasnt a 'good' programmer) and thats probably what you'd want your server to be.

As to more on the subject, you can go to the networking forums, or read a tutorial here thats entitled "Winsock2 for games" I believe to get yuou started.


Edit: I have worked with Raknet a very tiny bit, buit I hear it is a good alternative, though I'm not sure if it uses Winsock at its core and just wraps it up nicely fdor you :D
I'm not entirely sure what you mean by microsoft supported, but I have used SDL_Net with Net 2 (modified as it had, surprisingly, some basic bugs in it :/) with success. Raknet I hear is very good as well. My choice for SDL_Net was partially because it works natively with SDL which I use and partially because it's dirt simple to get working (as far as these things go)... Is it the best, probably not. Net 2 helps a bit.

net2

I'm not sure I can wholeheartedly reccomend it, however.

And yes, threads can be a bitch, especially when things go wrong. Threads and multiplayer can be even more of a bitch because no longer are you working within a single instance of your game, but you are now working within multiple instances of your game which all run multiple threads which means big scheduling nightmares if things go bad... It's like four orders of magnitude more difficult to debug than your standard single threaded application.
_______________________"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk
Multithreading isn't magic- you have to be able to identify which two processes you're separating. That said, it's also not always necessary. Plenty of games move very quickly without multithreading, and the poly count of the ships you're drawing is going to have a much much bigger effect on speed than anything else, when there are that many of them.
One example of good use of multi-threading is to have your players menus done by one thread, while the enemy AI is handled in another thread. This allows the AI to make complex searches without hindering the player's ability to take actions.

There are plenty of things that can be done with multi-threading, but it can't fix slow or bad algoritims.

*Edit* Also when rendering lots of game objects, multi-threading the rendering isnt llikely going to help alot. You could try doing multi passes instead of rendering it all in one large pass, like render ship geometry one pass, then lighting on a second or something.
Thank you for all the excellent feedback, this is def what I was hoping for ;) So technically it seems Multithreading is a joke. I was thinking of having the Phsyics, AI and such on one core and the other stuff on the other. The reason is I am using newtonian Physics and I was the AI to not be using scripts cause its so well uhmm boring; )

So I am safe to say then that its quite pointless to do multithreading ? It just made sense seeing as you ahve 2 processors and one of them is barely used and seeing as how its the new rave it would have been fun to figure things out ;)

Thank you for the link on Winsock, I might spend some time on working on Multiplayer for now, it does sound lieka fun challenge. But dunno we have aso many things to add and remove. I am sure some of you have seen Battlestar Galactica but basically I am expecting to have swarms of swarms of fighters going against the player + NpC's. Maybe it would be efficient to have one core handle the thread with loading, and the rest being done by the other but thats the only way i thin k it would make possitivly sense to do it.



The main problem with multithreading is that it can act non-deterministic, since your threads are effectively scheduled out of your control by the OS. Hence one of the fun things in debugging a multithreaded app is that things get a tendency to go wrong 'sometimes'. A bug might not show up for days or even weeks and then suddenly come crashing at you with some nice memory corruption. I just noticed I'm repeating Paladine's words, but I guess I just had to vent this frustration [smile]

Multithreading is not pointless however; in your setup it might pay off to have one thread take care of the networking, while another takes care of physics or something simple as view-culling for example. Playing and loading audio also is a good candidate to run in a seperate thread. As long as you can isolate tasks to keep threads busy by themselves for a fair amount of time (minimizing the time a thread needs to wait on the results of another one), threading can give you a substantial performance boost. Using 2 cores instead of one won't magically double your performance, but if done right (and if your game is CPU heavy), a performance boost of 50% is reasonable.

Some random things to keep in mind with multithreading:

  • First and foremost, determine if your game is CPU limited. Multithreading won't help you out if your game's performance is limited by GPU. Next up, profile your game and determine if you can isolate seperate tasks that use a fair amount of your available CPU cycles (> 10% for example). Running too small tasks in seperate threads might actually degrade your performance because of the overhead in setting up threading.


  • Get yourself a dual core machine to develop on. Multithreading works by allocating time slices for each thread on the available processors. For hyperthreaded or plain single core processors, this process 'fakes' multithreading so multiple tasks seem to be running at once BUT it is physically impossible for two threads to really be executed simultaneously. This makes multithreading less dangerous on single core machines, but developing on one will hide any potential bugs that might crop up on dual core machines.


  • Try to avoid accessing your graphics device from more than one thread; that'll save you a lot of headaches.


  • Go and download the MS GameFest presentations (specifically the System Programming Track), which contains some very nice information on designing and coding multithreaded applications. At least they explain various issues better than I can [wink]


Hope this late reply still helps somewhat :)
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!
Since there was some discussion on performance, is there any use in making each class a .DLL for instance all the music in one .DLL called Audio.DLL and DirectX in one .DLL? right now the entire project is from one .exe but I am not entirely sure if moving things to a .DLL would help the project except for quick patches instead of downloads :)

Moving things to additional assemblies can help with organizing things better, but it's only really useful when you want to encapsulate some generic functionality for future use or, as you proposed, to reduce the size of any patches. Don't go too far in splitting things up into DLL's though, since that's probably just way overkill and every DLL raises a potential versioning issue.

I'm currently working roughly along the lines of an Engine.dll, Game.dll and some RunGame.Exe. The Engine.dll contains all the core components, like graphics, sound etc. The code in Game.dll uses the engine components to actually do something useful and the exe is a small assembly that takes care of the initialization and kicks off the functionality in the Game DLL. I found this works better than splitting all engine components into seperate DLL's, since there are typically a lot of dependencies between those (in my project at least).

As for performance, I don't think putting stuff in seperate DLL's will have any impact on performance at all. There may be some overhead in loading the DLL's, but that should be rather marginal.

Hope this answers your question :)
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!

This topic is closed to new replies.

Advertisement