I am thinking about adding load balancing to my AI. What i want is to be able to specify an update rate and how many chunks may be updated per frame. I have some plan on what mechanisms I want to use for that but still have some open questions:
Chunk Components:
I can track when a Chunk was last updated inside Chunk Components. Before scheduling my jobs I could filter out a certain number of Chunks that were not updated in a while and pass them into the job to iterate over. Problem: Iterating over Chunks would happen outside of Jobs on the main thread (I have quite alot of Systems that would need to do that and also quite alot of chunks because my entities are hugeā¦). Doing it inside the Job would mean scheduling alot of unnecassary Jobs and then early out of them (Partial solution: ChangeFilters?).
ChangedFilters :
In the data gather phase i could trigger writes to specific chunks. This write access would then trigger all subsequent AI calculation systems for those chunks but ignore the rest for where no new data was gathered.
Problem: When do i actually trigger Version Changes? Can i somehow Filter and Update my chunks based on a Chunk Component (as in point 1) without triggering the Version Change for chunks where i only peek if i need to update them?
At the moment i also cannot use the Chunk Version since some other Gameplay Systems cause the entity to change its chunk so i am currently stuck with the Component Version as far as i can tell.
Are there better/ easier ways to implement load balancing? Am i on the correct path? Anyone has any experience with it?
It really depends on what you mean by ānot updated for a whileā is that 1,2 or 5 frames, or something like 10 seconds
How important is it to update not too late?
How much time and complexity would filtering/housekeeping/tracking cost
How heavy is the update, is the load in calculations or moving memory around because as you say āentities are hugeā
on heavy calculation with small data i would mod the index (index % 5 = 1) to update all every 5 frames, on large data small calculations best to process whole chunks and balance them, can you reorganize your structure to void the need for filtering? always best to not need to do anything. ask your self as many questions as you can think of about your situation and i think your plan will follow on its own. the question is now too general to give a good answer as to what your loadbalancer would ideally look like.
I agree my question is very general. I havenāt mentioned any implementation details because what i really want to do is get a general way of load balancing going that i and hopefully others can reuse for other systems as well. I should have mentioned that because this of course will affect the design.
For now in my AI I ideally want an update rate around 0.2 seconds to have Human like reaction times and some fake āHysteresisā but there will also be other Agents deciding about group behaviour that need to run much less often (every 1-2 seconds?).
It should update when the specified time passed and it is still under the chunklimit per frame i set. For now i plan to update 1 chunk per frame. So if a second chunk would need an update based on time passed it is deferred to the next frame. This way i would cause the chunks to spread out over time into diffrent frames on their own.
This depends on what ways i use to implement the load balancing and is one of the main questions i have in this thread. Which method can i best use to reduce housekeeping? How can i reduce housekeeping to the least amount of Systems and run the changed chunks through the rest of them too with Changed Filters?
Memory is not moved around by the AI calculations but the agents are moved around in memory by completely diffrent gameplay Systems. I will optimize that in my case later but if this is to become a general solution i think it is reasonable to assume that entities change chunks.
I canāt say much about how heavy the calculations are / how many Systems are running per Agent. The AI is authored by the gamedesigner in a graph and i donāt want to limit his creativity. At the moment its about 20 Systems for each agent type but this can easily double. So what i can definately say is that i donāt want to housekeep in every single System every frame on all chunks. Maybe UpdateGroups could help and get the chunks which are then passed to every single System inside of them?
I want to balance load on a chunk level because that should by far be the most efficient way to go. Right now i donāt see a way to do that without filtering but maybe i am missing something?
i wasnt very familiar with changedfilter but it seems to update changed state if you only even look at the data so i guess its unusable for you as it will flag changed way to often.
i would just mod the index for the often ran task, for the grouped task i would add a tag or component and query that every n seconds (mod n tags, so on time 0.5 use wait05, on time 2.5, use the same tag called wait05, and so on until wait20, let ecs group everything) if its complex and not really possible to calculate load i would take worst case and balance it this way up to acceptable timings when everything is worst case.
Offcoarse this probably wont help you as i really dont understand your project enough and also are new to unity/ecs but what i meant by avoiding filtering is that when you have entities updating chunks you could add data to force grouping in ecs (at the cost of structural changes) and use those groups as something like a filter. It depends for you on what is most expensive and if its even possible in the current structure.
I think i read somewhere that there are some obscure ways to declare read and write access on an IComponentData without it already triggering the ChangedVersion to update but i canāt find it anymore.
I guess i could schedule a readonly Job that gives me an array of chunks that need to be updated. For all of these i can then run my gather phase Systems with write access which then triggers my calculation phase Systems via ChangedFilters⦠Should work but it feels like it should be easier.
I really would like to avoid structural changes and reducing chunk utilization for a general purpose load balancing system. If you are fine with splitting your entities up into groups with for example a SharedComponentData you could then filter for a groupIndex inside the SCD and only update one group each frame. But that means you most likely have more chunks and you need to manage grouping the entities.
yes that sounds a little like my situation, that illustrates how difficult it is to really help with this as a loadbalancer isnt the compilicated part but the interchange of your environment with it is and anyone outside of it will think in his own terms.
Is there something like a general purpose load balancer? i dont think so, every loadbalancer balances equal typed loads having it be different might complicate it too much to benifit from it as it would need to much information to balance correctly on diverging load types.