Multi-threading discussion (split from A18 features thread)

Started by FrodoOf9Fingers, October 04, 2017, 04:42:21 PM

Previous topic - Next topic

FrodoOf9Fingers

Multi-threading is being worked on by a modder, but we'll have to wait and see if it pans out. The main question is whether the game will run better after all of the non-thread safe elements of the game are modded.

CannibarRechter

> Multi-threading is being worked on by a modder, but we'll have to wait and see if it pans out.

I wouldn't hold my breath. That level of surgery; I'm trying to fathom how it could be trusted with direct, real modification of the original core.
CR All Mods and Tools Download Link
CR Total Texture Overhaul : Gives RimWorld a Natural Feel
CR Moddable: make RimWorld more moddable.
CR CompFX: display dynamic effects over RimWorld objects

Kiame

Quote from: CannibarRechter on October 05, 2017, 12:44:34 PM
> Multi-threading is being worked on by a modder, but we'll have to wait and see if it pans out.

I wouldn't hold my breath. That level of surgery; I'm trying to fathom how it could be trusted with direct, real modification of the original core.

This^

The game's logic relies on linear execution. Heck, most mods that have an assembly.dll (ie have C# code) will probably break too. I know without a doubt some of my mods would break as they assume linear execution.

The easiest path of multi-threading i can think of is each pawn is updated on a set number of pawns. Once all pawns are updated the threads are suspended until the scene is rendered -- the could continue to update the pawns but it's questionable if there's any benefit there. This can become at the time of rendering too. I'm not sure about unity or the modifications the Prison Architect team/Ludeon have made to the engine whether it's thread safe and (if it is) if it uses lock-less threading support. If not that's going to cause a ton of thread-waiting. In the long run multi-threading may not buy anything at all.

Another possibility is to launch a new thread when a UI element is created to run it - though if the UI element changes the state to anything in the other thread, watch out as most of the game's code does not do null checking and assumes certain objects are always assigned to/in a certain state without actually verifying that they are before using them ;)

Can think of the choice between single- or multi-threading as the foundation to a new building. Once it's laid there's no changing it. If it must change it can be hacked together. It may work but it would have been a whole let better to have started off the other way in the first place -- it may have actually taken less time/money to have started over than to redo in the long run.

FrodoOf9Fingers

Quote from: Kiame on October 05, 2017, 04:14:36 PM
Quote from: CannibarRechter on October 05, 2017, 12:44:34 PM
> Multi-threading is being worked on by a modder, but we'll have to wait and see if it pans out.

I wouldn't hold my breath. That level of surgery; I'm trying to fathom how it could be trusted with direct, real modification of the original core.

This^

The game's logic relies on linear execution. Heck, most mods that have an assembly.dll (ie have C# code) will probably break too. I know without a doubt some of my mods would break as they assume linear execution.

The easiest path of multi-threading i can think of is each pawn is updated on a set number of pawns. Once all pawns are updated the threads are suspended until the scene is rendered -- the could continue to update the pawns but it's questionable if there's any benefit there. This can become at the time of rendering too. I'm not sure about unity or the modifications the Prison Architect team/Ludeon have made to the engine whether it's thread safe and (if it is) if it uses lock-less threading support. If not that's going to cause a ton of thread-waiting. In the long run multi-threading may not buy anything at all.

Another possibility is to launch a new thread when a UI element is created to run it - though if the UI element changes the state to anything in the other thread, watch out as most of the game's code does not do null checking and assumes certain objects are always assigned to/in a certain state without actually verifying that they are before using them ;)

Can think of the choice between single- or multi-threading as the foundation to a new building. Once it's laid there's no changing it. If it must change it can be hacked together. It may work but it would have been a whole let better to have started off the other way in the first place -- it may have actually taken less time/money to have started over than to redo in the long run.

I'm actually the one working on it. It's really not that hard to get threading going, as Tynan did a good job with error recovery. The main issue I'm dealing with at the moment is going through all of the different non-thread safe elements and making them thread safe. I'm also somewhat bottlenecked waiting for the next version of Harmony (It'll be able to handle reverse patching correctly then).

No need to worry about scenes or anything. The main lag is the update loop, not the graphics, and the graphics always waits on the update loop to finish (with some exceptions I believe, steam gysers do some weird things in thier tick with sounds that I've yet to diagnose). There's a loop that goes through every element in the game that has work to do in a "tick". I've simply made that work be put on separate threads.

Methinks a lot of people try to complicate multi-threading a bunch. The game is already multi-threaded, between updates and the UI, as is normal for anything with a UI.

FrodoOf9Fingers

I should add that I'm still completing my degree, and so progress is dependant on the amount of homework I have to complete in addition to my day job.

Kiame

Quote from: FrodoOf9Fingers on October 05, 2017, 04:58:49 PM
Methinks a lot of people try to complicate multi-threading a bunch. The game is already multi-threaded, between updates and the UI, as is normal for anything with a UI.

I just know some of the headaches i've run into with multithreading. I've really not done too deep of a dive with the rimworld code so if it's cleaner than I'm portraying it that's great. I do wish you the best of luck in your efforts!

Side question: Is Harmony still getting updates? I haven't seen any updates in months though I haven't done much searching either  ;)

FrodoOf9Fingers

He hasn't released a new version as of late, but he has been active on the github project and I believe he is preparing to release a new version. So a new version, barring unforeseen hurdles, should be out sooner or later. For now, I can keep working... by completely destroying the ability for other modders to touch the functions that I am touching ;p

FrodoOf9Fingers


CannibarRechter

> (It'll be able to handle reverse patching correctly then).

What is "reverse" patching in Harmony? I haven't seen a discussion of it.
CR All Mods and Tools Download Link
CR Total Texture Overhaul : Gives RimWorld a Natural Feel
CR Moddable: make RimWorld more moddable.
CR CompFX: display dynamic effects over RimWorld objects

Bozobub

Quote from: Kiame on October 05, 2017, 04:14:36 PMThe game's logic relies on linear execution.
And?  So does your computer's internal logic, yet the processing stream is split up into threads across 1-8+ cores.  Those individual threads are ALSO broken down and processed in more than one CPU pipeline at once, per thread ;).  I'm not trying to imply multiprocessing/parallel processing is easy, mind you, but your argument above simply doesn't work.
Thanks, belgord!

BlackSmokeDMax

Quote from: Kiame on October 05, 2017, 04:14:36 PMI'm not sure about unity or the modifications the Prison Architect team/Ludeon have made to the engine whether it's thread safe and (if it is) if it uses lock-less threading support. If not that's going to cause a ton of thread-waiting. In the long run multi-threading may not buy anything at all.

Not super relevant, but just so you know, PA doesn't use Unity, the PA devs (Introversion Software) wrote their own custom engine. (in C++ I believe)

Kiame

Quote from: Bozobub on October 06, 2017, 11:09:41 AM
Quote from: Kiame on October 05, 2017, 04:14:36 PMThe game's logic relies on linear execution.
And?  So does your computer's internal logic, yet the processing stream is split up into threads across 1-8+ cores.  Those individual threads are ALSO broken down and processed in more than one CPU pipeline at once, per thread ;).  I'm not trying to imply multiprocessing/parallel processing is easy, mind you, but your argument above simply doesn't work.

I think you misunderstand what I'm implying. If in the flow of execution it is assumed - in the high level code (C# in this case) - that one event (a method call/variable set) happens prior to another even that relies on the prior event happening that's a case of linear execution. Digging through the RW code I've seen cases of this; thus my comment. This does not mean making RW parallel is impossible, it just makes it harder. (Again i'll say I have not done a thorough analysis of the RW code, just enough to get my mods to work  ;) so if my assertion is incorrect then I am wrong)

Just to be clear, the CPU does not create new threads (i'm not sure if that's what you were implying in your comment). The executing program is in charge of create/destroying threads. Also threads are not run on multiple cores unless you're talking about hyperthreading which is not true multi-core multi-threading and is just an Intel branded idea from the 70's in which the resources of a cpu-core can be utilized by executing multiple threads (from either the same or different programs) so that a core's resources are more fully utilized.

You may have also been talking about predictions that take place while executing a thread which allow the CPU to guess about what will happen in the thread allowing for more of the chip to be active and get instructions done faster. If the prediction is correct then the process is faster. If the prediction is wrong the pipeline is flushed and it starts over. When writing in C# there is no consideration to this part as that's the compiler's/OS's problem (yes there are some optimizations that can be made at the higher level to facilitate some of this but by in large this can be ignored)

Kiame

Quote from: FrodoOf9Fingers on October 05, 2017, 07:35:20 PM
Heh, I guess we derailed too much :P

I should have known better, i just really like the idea of multithreading  :P

Just curious, since we have a thread for this now, where's the multi-threading happening? My initial go at this would be to have the rendering engine be one thread and the backend/updating part broken down into multiple consumer threads with some type of load balancing (round robin probably assuming everything takes about the same amount of time to update)

SpaceDorf

*watching*

Carry on, I like where this discussion is going and wish you the best of luck.
Maxim 1   : Pillage, then burn
Maxim 37 : There is no overkill. There is only open fire and reload.
Rule 34 of Rimworld :There is a mod for that.
Avatar Made by Chickenplucker

FrodoOf9Fingers

Quote from: CannibarRechter on October 06, 2017, 08:06:16 AM
> (It'll be able to handle reverse patching correctly then).

What is "reverse" patching in Harmony? I haven't seen a discussion of it.

Reverse patching is where you want to patch your own method with the code of the original method, and then change the code of the original method to call the new function. Currently, I have to copy the original function's code during code time (as in when I'm writting the mod) rather than runtime, so I break compatibility with other mods and my code will break if the original code changes with a new version of Rimworld.

I copy the function so I can run it inside of a new environment: there are a few objects that run algorithms that use member variables to store algorithm state, and only 1 instance of those objects is created (such as pathfinder, only 1 per map is created). To create thread safety, either I lock up the instance (which is bleh), or I create new instances of the object and send calls to an instance manager that holds those instances.

I'm not the best at communicating sometimes, hope it helps. I was introduced to the term here: https://github.com/pardeike/Harmony/issues/41