Search Unity

How to run logic outside of ecs after ecs is done (including jobs) ?

Discussion in 'Entity Component System' started by meanmonkey, Nov 14, 2018.

  1. meanmonkey

    meanmonkey

    Joined:
    Nov 13, 2014
    Posts:
    148
    I want to run logic outside of ecs after all (parallelFor)jobs are completed in ecs. So commandbuffers won't help me in this case.

    My first idea was using UpdateGroups: I create a ComponentSystem (mainthread) which runs OnUpdate() when all other (Job)ComponentSystems are done. Does this guarantee the completion of all (ParallelFor)Jobs in all JobComponentSystems belonging to the regarding UpdateGroup too ?

    If the answer is no, is there any way to run something on the mainthread when the ECS has completed all jobs ? LateUpdate maybe ?
     
    Last edited: Nov 14, 2018
  2. fholm

    fholm

    Joined:
    Aug 20, 2011
    Posts:
    2,052
    I don't have any help to offer here, but I'm looking for something like this also, specifically how to wait for all jobs to be completed for a certain frame, so i then can do some processing on the final data that was produced. I'm also using a custom update loop in my case.

    Also some clarification on how the jobs related to the frame update loop itself for example, like if all jobs are gurantueed to be completed when the frame is done, etc.

    My workflow is something like:

    0) FrameStart
    1) Do a bunch of stuff outside of the ecs
    2) Pull data into the ecs, perform transformations on it with loads of parallell jobs
    3) Wait for all jobs from 2) to be done and do further stuff on the ready data set.
     
    meanmonkey likes this.
  3. meanmonkey

    meanmonkey

    Joined:
    Nov 13, 2014
    Posts:
    148
    Exactly my usecase. How are you pulling data into the ecs? My idea is via a static class, which contains a concurrent queue. This queue forwards object references (from another worker thread) containing native arrays for batch processing in JobComponentSystem / IParallelJob. When the job is done I want to flag the object containing the native arrays as done so the other worker thread can use it again (multiple objects are spawned in a fixed size so the worker thread can run without blocking)
     
  4. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    meanmonkey likes this.
  5. fholm

    fholm

    Joined:
    Aug 20, 2011
    Posts:
    2,052
    Okey, but how do i wait for say all systems running jobs to complete? say in a fixed tick/timestep simulation.
     
  6. meanmonkey

    meanmonkey

    Joined:
    Nov 13, 2014
    Posts:
    148
    If I can't get a guaranteed entry point after ecs has completed all mainthread- and multithread jobs in a frame, I may have found a workaround for my specific usecase (and maybe yours too, @fholm):

    In my via static class / concurrent queue passed object (containing the nativearray data to be processed), I flag it with a frame counter at JobComponentSystem pickup (with object locking, which is fast for a single value). In the other worker thread outside of ecs, I check the flag and if its an old framecount, I know ecs is done, as it guarantees completion each frame. what you guys think ?
     
  7. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    meanmonkey likes this.
  8. meanmonkey

    meanmonkey

    Joined:
    Nov 13, 2014
    Posts:
    148
    This is very interesting, but I knew that I can set the update order for systems.

    Its suitable for ComponentSystems which run only in the mainthread, where update == done

    But I'm interested in the completion of JobComponentSystems, which run multiple threads, where update == jobs are scheduled and done == ?

    As I don't have a grip onto the job.complete() like for manual jobs, I want to have a guaranteed entry point where all jobs in a frame are completed.

    This is why I was asking in my original post, if the update order is also a completion guarantee
     
  9. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    If you execute some system after other threaded system, that means is guaranteed.
    Jobs will run sequentially all the time. There is no gap, like in case of OOP FixedUpdate, which for example updates once every roughly 20ms. There is no sense of frame as such in ECS.

    So one way to ensure you execute, after targeted system is done, is using UpdateAfter. That means its threads finished as well. This is useful for deterministic systems, where order is important.

    Hence using bootstrap, you can define how often you want to run system. Then execute other system after.

    You can also control system execution with component tag.
     
    meanmonkey likes this.
  10. meanmonkey

    meanmonkey

    Joined:
    Nov 13, 2014
    Posts:
    148
    Sounds good thanks
     
  11. meanmonkey

    meanmonkey

    Joined:
    Nov 13, 2014
    Posts:
    148
    Antypodish likes this.
  12. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Yep I have been tracking it too.
    I just hope, this is what you need.
     
    meanmonkey likes this.
  13. meanmonkey

    meanmonkey

    Joined:
    Nov 13, 2014
    Posts:
    148
    It will come in handy for sure :D