Sign in to follow this  

To multithread or not to multithread

This topic is 4266 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

What are your preferences for multithreading when coming up with a design? Do you like sticking chunks of game tasks into seperate threads (e.g. a thread for rendering, which does nothing but read the state and render), or do you prefer to do everything in one thread (well, I guess a lot of stuff happens in other threads anyway, like kicking off background music or something, but I'm talking more about design). I haven't really played around with multithreading, but am wondering what your experiences are with it, and whether it affected performance in a noticeable manner. Also, I remember reading a long time ago that threading in Linux is kind of crappy, due to the poorly-implemented thread context switching (to the point where it's easier to switch between actual processes). Is that still true?

Share this post


Link to post
Share on other sites
Multithread when you have a blocking function that takes a long time to complete. A blocking function is one that stops anything else from processing while it is taking place. Things that do this are networking, file reads, ect.

theTroll

Share this post


Link to post
Share on other sites
Quote:
Original post by Replicon
Also, I remember reading a long time ago that threading in Linux is kind of crappy, due to the poorly-implemented thread context switching (to the point where it's easier to switch between actual processes). Is that still true?


Well, from what I've read in Linux there is no difference between a "thread" and a "process" from the kernels point of view, they are both just "tasks".
A thread is a task that simply shares memory with another, its parent. This allows for various degrees of task cooperation, like having tasksshare only certain data , like only open files or only memory.

Share this post


Link to post
Share on other sites
Don't mean to scare you out of trying something new and interesting, as that is how we all learn to do things that haven't been done [or learn to do them better], but with regard to multithreading, be aware that a good multithreaded interdependant program components [like making rendering seperate from game logic seperate from physics] is something like dancing ballet through a minefeild. It can be done gracefully, and when it is done perfectly, it's just like preforming the same task outside of the minefield. But one miss step, and stuff goes from perfect to really bad, really fast. In all honesty, stuff like networking, and extra-file management [like loading new meshes before they appear on screen, or getting the next map transition loaded from the file] can work pretty good. Those processes can be made completely seperate, in a sense, in that the relationship of information exchange is never two way, always one way [info coming in, OR info going out, no active conversation-like information exchange, no shared data]. Trying to seperate things like physics and rendering, creates huge problems very fast with data that is accessed for different reasons by different components, and more importantly, modified by different components. You'll have to spend a lot of your extra programming time trying to find ways of making the systems not step all over eachother, and it's very messy and complicated.

If you want to try it, more power to ya! Maybe you'll come up with the graceful way of doing it, but in all honesty, it's pretty rough. At the very least it'll be a learning experience though....

Share this post


Link to post
Share on other sites
iv never ran into a problem in game code that would justify the intoducing sycronization issues of multithreadting, also note that having too many mutexed critical section will quicky cost you any preformacne you might have gained by multithreadting

Share this post


Link to post
Share on other sites
Quote:
Original post by Kaze
iv never ran into a problem in game code that would justify the intoducing sycronization issues of multithreadting, also note that having too many mutexed critical section will quicky cost you any preformacne you might have gained by multithreadting


And with the dissent, I have run into problems that justify it.

Make your decision now though. Somewhat like multiplayer/networking, multithreaded design has requirements that are difficult to impossible to add on later if the system was not designed with its use in mind.

Share this post


Link to post
Share on other sites
It's all in how you implement it. Multithreading is a disaster if you get it wrong.
I've seen far more cases of BAD multithreading than Good. It's not pretty.

My advice: start small with networking and file reading. Work yourself up to rendering and physics after you've gotten a handle on things.

And for gosh sakes, don't make 500 mutexes for less than 5 threads. It's a bad idea. TRUST ME!!

Share this post


Link to post
Share on other sites
I think a rendering thread is a good idea, it means you can control render framerate (which is what gives the illusion of smoothness) while doing 'slow' stuff like precaching textures for the next part of the game in the background. Rendering shouldn't need to update any other parts of the game data so is a natural separate thread. This probably includes sounds too – 'rendering to the ears'.

Physics is good to take into a separate thread too (for the same control reasons), but can be hard to separate from the main game data – it needs to see and update models, entities and maybe textures (if you place decals of explosion marks etc) which will also be being looked at by resource loaders etc.

Resource loaders should be in a separate thread because some of what they do is blocking and slow (loading files, particularly off CD or network, decompressing data etc). If it has to wake up your hard disk, slow could mean up to 5s! So unless you load everything at the start of the level, your game will freeze for a moment while the function completes. Again this is a relatively easy one to make separate, as it has sole control over the resources and can set a flag when it's done loading one, before which no other component is allowed to touch it.

Quote:
having too many mutexed critical section will quicky cost you any preformacne you might have gained by multithreadting

This is absolutely true. Multithreading only works if you have the design right and aren't getting held up on synchronised sections. You can protect some area which might, once in a blue moon, have two modules trying to access them, but most data should either be (a) only written to from one thread, or (b) it doesn't actually matter if occasionally a write gets dropped.

Share this post


Link to post
Share on other sites
Quote:
Original post by Replicon
What are your preferences for multithreading when coming up with a design?

I try to keep tasks separate, so that they can be put into separate threads if I decide so. I never (well, hardly ever) decide "hey, I wanna use some threads! Where can I fit them in?"

Share this post


Link to post
Share on other sites
Quote:
Original post by Spoonbender
Quote:
Original post by Replicon
What are your preferences for multithreading when coming up with a design?

I try to keep tasks separate, so that they can be put into separate threads if I decide so. I never (well, hardly ever) decide "hey, I wanna use some threads! Where can I fit them in?"


That's my attitude as well. I don't seek out reasons to use the technology, but rather seek out technology to suit my purposes. Rendering does sound like a good thing to separate, but then, even if you have more control over the framerate, if something slows down your main thread, you'll just display the same frame over and over with a higher frame rate :-). You can do interpolation both ways too.

Share this post


Link to post
Share on other sites
Regardless of how you feel about multithreading, multi-core CPUs are on the way, so sometime in the near future any game that wants to run at maximum speed will need to be multithreaded. It will no longer be sufficient to "Multithread when you have a blocking function that takes a long time to complete."

I think that in the future, multithreading will be transparent to the code (with sufficient language support). Just like we have virtual memory now, we will have virtual processing in the future. In the meantime, thread allocation will have to be part of the design.

Share this post


Link to post
Share on other sites
if mutiple core CPU's every become the standard rendering api's will probably be made to support multithreading so its not that big of a deal
(they alrady use CPU +GPU so adding another CPU thread cant be that hard)

Share this post


Link to post
Share on other sites
Quote:
Original post by JohnBolton
I think that in the future, multithreading will be transparent to the code (with sufficient language support). Just like we have virtual memory now, we will have virtual processing in the future. In the meantime, thread allocation will have to be part of the design.


I don't think that support from language would replace proper design. I know a few years old language that is doing this already (and requires quad core processor with a special support to work flawlessly, it also tends to span the program into 100+ threads that could pretty much mess out with windoze non milisecond timmer.), however a lot of programmers would have a big problems with preemptive unsynchronizable multithreading.

Experience and playing with simple multithreaded test programs matter more than language support.

Share this post


Link to post
Share on other sites
In my opinion this is what is wrong with a lot of programmers today. The amount of memory and machines processing power have lead to sloppy programming. Why do you have to make atomic functions when the machine is so fast. Why pack your data when you have so much memory. It has lead to programmers taking the easy way to do things, not having them do the best thing. A good design and good programing will fix a lot of problems in the future, better hardware will never fix a bad program.

theTroll

Share this post


Link to post
Share on other sites
Something that I'm experimenting with in my engine is a task scheduler. On startup the scheduler spawns a set of 'Virtual Processors'(on windows they are threads), based on the number processors that are available(this doesn't work yet). Each virtual processor has a memory cache that only it can modify.

The goal is to have each task copy memory that it needs to work on into the virtual cache, perform the task, and copy it back. This way we only have to use mutexes and/or critical sections on the cache read/write. By wrapping the cache read/write the only syncing issues that the programmers need to worry about is copying the data in/out of the cache.

I don't really know what sort of impact this method will have performance wise, but the design appears to be very similar to programming for the cell processor (don't really know since I haven't programmed one).

Share this post


Link to post
Share on other sites
If you're going to multithread your system, do it for pedantic reasons - not in hopes of performance gains. As it stands right now, the return on multithreading just isn't there. It will significantly increase the complexity of debugging, and designing, your code. You will see zero performance gain on the vast majority of PCs, and there is actually a potential for a performance decrease on the minority of machines that can actually stand to take advantage of the multithreading; eg - check out the potential for cache thrashing issues with shared cache systems, such as hyperthreading enabled pentium chips.

Multiprocessor capable programs are definitely the future, but right now you're still looking at minimal benefits with high costs. I expect the 'next-gen' consoles will be a large stepping stone away from developer implemented multiprocessor capability.

Share this post


Link to post
Share on other sites
Quote:
Original post by jkleinecke
Something that I'm experimenting with in my engine is a task scheduler. On startup the scheduler spawns a set of 'Virtual Processors'(on windows they are threads), based on the number processors that are available(this doesn't work yet). Each virtual processor has a memory cache that only it can modify.

The goal is to have each task copy memory that it needs to work on into the virtual cache, perform the task, and copy it back. This way we only have to use mutexes and/or critical sections on the cache read/write. By wrapping the cache read/write the only syncing issues that the programmers need to worry about is copying the data in/out of the cache.

I don't really know what sort of impact this method will have performance wise, but the design appears to be very similar to programming for the cell processor (don't really know since I haven't programmed one).


Sorry to barge in the conversation like this, but ...I really liked the way you describe your system. I am kind of trying to implement something like this myself, but so far, I haven't really done much except planning. My previous attempt, which I didnt plan at all, failed miserably.

Anyways, my question is, could you possibly share some of your knowledge of how to implement this kind of a system? Code is welcome, but it ISNT the reason why I am asking this, just some general help would be fine as well).

Thanks,
Anton A.

Share this post


Link to post
Share on other sites

This topic is 4266 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this