Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Running different systems in parallel writing to the same ComponentData?!

Discussion in 'Entity Component System' started by Opeth001, Jan 9, 2019.

  1. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,068
    Hi guys,
    Im trying to create a game using pure ECS as my main approache and few hybred systems to handle some physics related logics like ( bullets hit detection ...).

    But yesterday i was thinking about my Logic and found that in some cases using
    JobComponentSystem will block other systems from running in parallel cause they are writing to same ComponentData but in diffrent entities.
    Eg:
    Let's Say i have 2 different systems ZombiesHealthSystem and PlayersHealthSystem both zombies and players architypes have a healthComponent.

    ZombiesHealthSystem will Subtract Components existing in players architype and vice versa. So in this case there is no way for Race conditions within jobs but the systems will run synchronously anyway.
    ( Let's Say i need players and zombies to have the same healthComponent type for some other shared systems )

    So is there any way to prevent systems from running synchronously even if they are writing to the same Components ?
     
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,983
    I have been wondering about this too. While I haven't run into this issue yet, my game is shaping up where I will only have a 1 or 2 chunks per IJobProcessComponentData that need to all update the position component after an intense physics simulation.

    I haven't tested it yet, but my suspicion is that if I were to schedule all the jobs in the same system and give them all the same InputDeps and not chain the dependencies, it will work as long as the chunks are different. This is because the automatic dependency management between systems works on types, but the actual inputDeps are jobs that are dependent on NativeContainers.

    If this works, it unfortunately still does not do me much good as for my game I do not know all the job types at compile time and would need to collect all the subtractive components at runtime on level load. Currently the only way to add a subtractive filter to an IJobProcessComponentData is through an attribute.
     
  3. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    The code executed within the JobComponentSystem should be very very quick, basically just setting up jobs. All your logic should be within Jobs. These jobs can run at the same time as other systems are executing.

    i.e.

    ZombiesHealthSystem runs, sets up ZombiesHealthJob
    PlayersHealthSystem runs, sets up PlayersHealthJob but while this is being setup, ZombiesHealthJob is executing at the same time.

    Would look somethingl ike this

    Code (CSharp):
    1. MainThread: | ZombiesHealthSystem | PlayersHealthSystem | EndFrameBarrier |
    2. Thread 1:              |  ZombiesHealthJob  |  PlayersHealthJob |
    3. Thread 2:              |  ZombiesHealthJob  |  PlayersHealthJob |
    4. Thread 3:              |  ZombiesHealthJob  |  PlayersHealthJob |
     
    Nyanpas likes this.
  4. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,068
    @DreamingImLatios : yes it's the solution i found too, using only one system writing to the component and use multiple ComponentGroup to query the entities needed then scheduling them all without dependencies.

    Until I got another idea which is the cleanest way i found for the moment .
    Add a different ComponentData for each System that needs the write permission to the HealthComponent instead of using it directly then groupe my systems using UpdateInGroup and create another system which will run juste After the grouped systems using the EntityArchetypeQuery to query all the different ComponentData added and finaly juste copy their values to the original HealthComponent.
    Using this way ill let my jobs run in perfect parallel way with without putting them all inside a single system which make me fill going against ECS principles.
     
    Last edited: Jan 9, 2019
  5. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,068
    @tertle the systems will still working synchronously and this is what il trying to avoid.
    And im not that sure about the systems will query the entities before jobs from other systems completes, because the reason they cant run in parallel is that After modifying a component all the related chuncks will be invalidated.
     
  6. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    That's just not true.

    upload_2019-1-9_19-48-4.png

    You can see PlayerHealthSystem finishes executing long before ZombieHealthJob finishes executing and PlayersHealthJob chains straight away even though it was scheduled before ZombieHealthJob finished, using the same chunks.

    No sync point is forced.
     
  7. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    And here they are running in parallel

    upload_2019-1-9_19-53-35.png

    Even though they were scheduled from different systems.
     
  8. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,068
    Are u using JobComponentSystem Types?

    I got this from their github docs.
    JobComponentSystem
    Automatic job dependency management
    Managing dependencies is hard. This is why in JobComponentSystem we are doing it automatically for you. The rules are simple: jobs from different systems can read from IComponentData of the same type in parallel. If one of the jobs is writing to the data then they can't run in parallel and will be scheduled with a dependency between the jobs.
     
  9. Hanoke

    Hanoke

    Joined:
    Oct 30, 2016
    Posts:
    6
    Hello, I have the same problem. I have got 2 jobs write to rotation component. But both of them have completely different entity queries, they will work on completely different chunks. I tried to combine dependencies of both jobs yet, unity says "you can not do that because the first job writes to rotationType(ComponentTypeHandle) like the second job". I tried to split the system into two systems but they do not run in parallel. The second job waits for the first job's work to be done. Is it normal? Does not jobhandle take care jobs that works on different chunks but with same component?
     
  10. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,068
    Unfortunately not!
    But you can still use a single system with with 2 queries and 2 different jobs.
    Dependencies between jobs it not handled automatically by the entities package but by jobhandles passed trough systems. Which means inside the same system you can play around it and schedule 2 different jobs without handling dependencies between them. If an error is throwed declare your jobs as unsafe.
     
  11. Hanoke

    Hanoke

    Joined:
    Oct 30, 2016
    Posts:
    6
    As you said, I have got a single system with two different queries and two different jobs. As far as I understood(please correct me if I am wrong), Dependency property has all the prior read and write dependencies for this specific system. By passing it through two jobs, the jobsystem basically says the ComponentTypeHandle is a NativeContainer (like NativeArray), and both of your jobs read the same Dependency and try to write to the same NativeContainer(rotationType in this case).
    The thing I do not understand is: if there are two systems for each job for the same scenario, first system's write access to rotation component makes the second system to wait. But in that case, ALL the systems that writes to rotation component can never run in parallel even if they work on completely different chunks(no race condition). Is it correct? Thank you.
     
    Last edited: Aug 16, 2020
    Opeth001 likes this.
  12. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,068
    What you say is 100% correct.
    Unity is not handling dependencies by archetypes or chunks but based on component types.
     
    Hanoke likes this.