Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# Game multithreading XNA , +
Hello , I am developing now some experimental game engine for 3D games (via XNA) and i was thinking of splitting the physics and rendering processes to separate threads in C# .
 
So , i was reading in some article at StackOverflow that Multi-Threading isn't always effective and may even hurt the overall performance .
 
I thought it would be OK because rendering have nothing critical to sync with the physics or game logic which may cause the program to crash at running time . So i wanted to leave the physics in the main thread and give the rendering process to another thread and then it will affect less the physics and the AI calculations .
 
I think this idea is great at all , because the Rendering may be slower regardless the logic in the game so the next logical step should be calculated whatever if the rendering is delays or not . And in overall the rendering is so heavy process as all the other logical processes together .
 
Questions :
1) So , is it good idea to perform here multithreading at all ?
2) If the rendering is slower than the logic calculation , Will it cause mouse lags ?
3) Is it good idea to split the game logic to many threads ? like AI , Physics , Sound etc ?
Posted 17-Feb-13 9:22am
Edited 17-Feb-13 10:57am
v2

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

It really depends on your UI library and what you call rendering. In WPF, for example, rendering is already a thread separate from UI thread. I don't think this is a correctly posed question. In all cases, you should separate the game scenario from UI. Then you just have to render the scene in the form of data, and this hardly can be a thread different from "scenario" thread. But the UI rendering (GDI, DirectX, whatever) is nearly inevitable comes in a different thread, but what is it, UI thread or yet another thread, depends on the technology.
 
[EDIT #1]
 
First of, all the format of the forum does not allow to consider this problem seriously, especially when you try to do some generalizations. I would say, generalization is especially dangerous here.
 
Consider you are playing tennis with a wall. It's good to have a thread representing the ball. The UI thread will give you the events which you can use to change the motion due to collisions with a racket. When you introduce "play against a computer", its good to have a thread representing your opponent player. At the same time, if this is football, perhaps you will need a thread representing a whole team of players.
 
Nothing is so straightforward as you probably trying to imagine. However, I would try to list some architectural notions you should not mix up with a thread.
 
  • Thread should not be coupled with a layer in a multilayer architectures (and practically all architectures should be multilayer). A thread can execute the code of several layers; and a layer can host several threads.
  •  
  • Thread should not be coupled with a functional unit. A thread can execute the code of several functional units; and a functional unit can host several threads. In particular, a thread should not be associated or couples with some algorithm.
  •  
  • Thread should not be couples with a compilation unit, such as a .NET assembly. Same as above.
 
It is very important to understand that threads should not be considered as a performance tool. In particular, if you try to use parallel processing with a number of threads which is significantly more then the number of CPU cores, you will loose in performance, due to apparent overhead.
 
The thread, by its nature, is rather a representation of something consisting of a sequence of relatively independent state changes, something which "lives its own life". It can be a ball, for example. It is very important to understand that a thread represents a "source of causality". In gaming, when you have anything where you need to model the concept of free will, you need to implement it in a separate thread. An example would be an enemy of a player. Many enemies: could be one thread for all. It really depends an a number of factors.
 
[EDIT #2]
 
The second problem is performance and timing. If you have a real-time OS, you would have to guarantee too much of timing to comply with your timing scenario. Despite of suitability for real-time strategy games, XNA is not a real-time OS. Therefore, you should not rely on performing all calculations between the frames, or even showing all frame in time. Timer approach is less reliable then threading in principle. Did you ever tried to take into account such situation: your handler called by a timer tick event is not completed execution when the next event is invoked?
 
The solution is using just a thread or using combined processing: the physics, scene data, and so one is recalculated in a periodic thread. To make the behavior of this data time-accurate, you will need to inquire the real time value from the OS. In this case, your algorithm is not so sensitive to the delays: for example, the position of a ball is calculated correctly even if it is performed in non-uniform moments of time; so the motion looks subjectively smooth…
 
I really feel that I'm going beyond the normal forum format. Again, discussion of all aspects is really not suitable for the Quick Questions & Answers forum…
 
—SA
  Permalink  
v3
Comments
David Diamond at 17-Feb-13 15:55pm
   
Not only the UI , but all the drawing in the game , the 3D field and objects , 2D spritebatch and 3D Shaders .I am using XNA technology with C# . I simply want to put the "Draw"() method into another thread to avoid it's delays on the "Update"() method which is the method of the game logic .
Both methods are called each frame (60 times in second , And sometimes the Draw methods takes more than 16 ms , And this cause the Update method to be delayed until the draw method is finished after more than one frame , And i don't want the drawing to delay the AI and the Physics ..
Sergey Alexandrovich Kryukov at 17-Feb-13 18:36pm
   
I added some thought to my answer, please see [EDIT] sections.
—SA
David Diamond at 17-Feb-13 20:05pm
   
OK Thanks Sergey . I think i will not use multithreading at all . The engine is already very well optimized and multithreading isn't a way to optimize the performance of gaming , and that's not what i thought it is after reading it . so its kinda unnecessary for my project .
Sergey Alexandrovich Kryukov at 17-Feb-13 20:31pm
   
Wow! I did not expect it. I don't think you are right. I tried to explain what multithreading is. It is not directly related to performance but rather expresses the relatively independent sequences of state transitions. A thread is natural for a game. If you are using some kind of ersatz, maintainability of the project suffers, to say the least. I wonder, do you have at least one game developed?
Anyway, it's a pity that we wasted so much time...
—SA
David Diamond at 18-Feb-13 0:40am
   
Sometimes i can't get what you'r saying even with Google translate :
"but rather expresses the relatively independent sequences of state transitions" . I think the only place i can use it , is the loading screen that the UI needs to update parallel with the loading process ... And yes i had many game projects and game engines , but in most of them did not used Multi-Threading for the game itself so i still don't find any reason why to use it because games without it worked well .
 
If you want to say that the game objects needs\can use multithreading , Then i just must say No , There is huge mechanism and order behind it and i can't explain everything , multithreading simply isn't suitable for game instance in my engine . The only way i thought to use it is only to move the Draw() method to another thread because it's order/delay isn't so important .
Sergey Alexandrovich Kryukov at 18-Feb-13 0:46am
   
This is not so easy to explain... and I tried to conduct the idea that the games are very different, you can design threading model in different ways.
—SA
David Diamond at 18-Feb-13 1:00am
   
I have edited the first post , Well you are responding very fast :D
 
Nope , I still don't see any use of it for game but only loading screens and other places when the UI may freeze until heavy process is finished . About the game objects I've added some more in my edited comment .
 
Edit :
LoL , i just noticed now that the Draw() method is heavy in the GPU and not in the CPU so there is no reason actually to move it to another thread anyway in the CPU , Because the main thread isn't waiting for the GPU to finish it's job until moving to the next process ... lol .
 
Multithreading is useful only for CPU process so there is no point to move particles or 3D mesh drawing to different thread .
Sergey Alexandrovich Kryukov at 18-Feb-13 1:19am
   
You are still thinking of threads as the performance tool. This is wrong...
—SA
BupeChombaDerrick at 18-Feb-13 3:56am
   
Don't know much about threading, but I think I get Sergey's point, threads just run independent of one another, so even if one thread crushed, it wouldn't affect the other running threads. And if a processor is multicore, then seperate threads can run on separate cores, but if the number of threads exceeds the number of cores then the threads become overheads rather than improving performance of the program, so in some cases threading can improve performance while in others it can hurt performance, especially if more than the necessary number of threads are running. I'am right? :-)
Sergey Alexandrovich Kryukov at 18-Feb-13 10:04am
   
Thread crushing have nothing to do with the use of threads. You can use exception handling to recover from crushing even for one thread, depending on what you do. No, I did not even consider crushes. Not even close. Frankly, it does not make much sense. Yes, you can make a scenario where you discard a thread using for communication. If connection is lost, you use another thread. But practically, even this makes little sense, because you can recover and use the same thread.
 
By the way, on top of stack of each thread, you should catch all exceptions... it a thread is a loop, you can wrap it all in another outer loop which will execute it all over after all exceptions...
—SA
David Diamond at 18-Feb-13 19:50pm
   
If i am discarding a thread that i have created for some scene , Then all it's resources that was loaded during the thread was alive , are lost in the memory ? (textures models sounds etc ..)
Sergey Alexandrovich Kryukov at 18-Feb-13 20:03pm
   
No. Managed memory is reclaimed by the Garbage Collector (GC). It is done by the criterion called reachability:
http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29
GC does it using its own scenario, and hence, not immediately; you have no control over the moment of time of the destruction. Reachability guarantees that the results of reclaiming of memory is consistent and safe.
 
Reclaiming of unmanaged resources is put on the developer. Usually, it is done via the support of the interface IDisposable.
 
The problem is that closing and re-creation of threads is time-consuming. I personally use some robust approached to thread reuse (exception handling is part of it, another part is thread wrappers), not related to thread pool...
 
For thread wrappers, please see:
http://www.codeproject.com/Answers/155852/How-to-pass-ref-parameter-to-the-thread#answer2
http://www.codeproject.com/Answers/223412/change-paramters-of-thread-producer-after-it-start#answer1
http://www.codeproject.com/Answers/485734/MultiThreadingplusinplusC-23#answer4
http://www.codeproject.com/Answers/191391/Passing-arguments-to-a-threaded-LongRunningProcess#answer2
 
—SA
BupeChombaDerrick at 19-Feb-13 1:10am
   
I must say I have learnt a lot about threads just from this answer, thanks Sergey for the inform, it might come in handy. A vote +5.
David Diamond at 19-Feb-13 4:49am
   
Sergey , You gave here great explanation . Thank you very much for the time you spent for me , 5\5 .
Sergey Alexandrovich Kryukov at 19-Feb-13 11:52am
   
You are very welcome.
Good luck, call again.
Thank you,
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 325
1 DamithSL 300
2 Sergey Alexandrovich Kryukov 289
3 CPallini 235
4 Maciej Los 215
0 OriginalGriff 5,455
1 DamithSL 4,422
2 Maciej Los 3,860
3 Kornfeld Eliyahu Peter 3,480
4 Sergey Alexandrovich Kryukov 3,010


Advertise | Privacy | Mobile
Web04 | 2.8.141216.1 | Last Updated 17 Feb 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100