Search Unity

[ECS design problem] Concurrently processing independent consistent strict subsets of IComponentData

Discussion in 'Entity Component System' started by Mr-Mechanical, Aug 2, 2018.

  1. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    507
    In normal use cases, you'd use IJobParallelFor to process entities concurrently on multiple cores. However, I know IJobParallelFor does not allow explicit control of how entities are split when processed (only hinting). Is there a way to process consistent strict subsets of entities on multiple threads (explicitly control batching somehow)? I cannot currently do this with IJob because multiple jobs cannot access the same IComponentData simultaneously:

    //note this example does not work but shows what I want to do with ECS

    Code (CSharp):
    1. LOD1: IJob {
    2.          Data data;
    3.          public void Execute()
    4.          {
    5.                 //process this same subset every frame
    6.                  for(int i = 0; i < data.stuff.Length; i++) {
    7.                           stuff = DoSomething();
    8.                  }
    9.          }
    10. }
    11.  
    12. LOD2: IJob {
    13.          Data data;
    14.          public void Execute()
    15.          {
    16.                 //process this same subset every frame
    17.                  for(int i = 0; i < data.stuff.Length; i++) {
    18.                           stuff = DoSomethingElse();
    19.                  }
    20.          }
    21. }
    22. //---------------------------------------OnUpdate-----------------------------------------
    23. //Schedule multiple different independent subsets of "data" using LOD1 and LOD2 concurrently
    24.  

    ^This code is not possible with ECS. How would I achieve an equivalent behavior?
     
    Last edited: Aug 6, 2018
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Code (CSharp):
    1. I cannot currently do this with IJob because multiple jobs cannot access the same IComponentData simultaneously:
    They can if it's reading only, mark it as [ReadOnly]

    If you're writing you'll have to double buffer or something.
     
  3. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    507
    Sounds cool. How do you double buffer?
     
  4. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
    Not only. You can manually disable safety restriction, just use [NativeDisableContainerSafetyRestriction] attribute for job input data declaration.
     
    Mr-Mechanical likes this.
  5. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
    Also you can use IJobParallelForBatch in some cases.
    Code (CSharp):
    1.  
    2. private struct TestJob : IJobParallelForBatch
    3.         {
    4.             public NativeArray<int> Data;
    5.  
    6.             public void Execute(int startIndex, int count)
    7.             {
    8.                 var end = startIndex + count;
    9.                 for (var i = startIndex; i < end; i++)
    10.                 {
    11.                     int val = Data[i];
    12.                 }
    13.             }
    14.         }
    15.  
    16.         protected override void OnUpdate()
    17.         {
    18.             NativeArray<int> data = new NativeArray<int>(50, Allocator.TempJob);
    19.             for (int i = 0; i < data.Length; i++)
    20.             {
    21.                 data[i] = i;
    22.             }
    23.  
    24.             TestJob job = new TestJob()
    25.             {
    26.                 Data = data
    27.             };
    28.  
    29.             job.ScheduleBatch(50, 10).Complete();
    30.         }
     
    Last edited: Aug 2, 2018
    Mr-Mechanical likes this.
  6. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    507
    Thanks for helping me out. Can you explain IJobParallelForBatch? I couldn't find much documentation.
     
  7. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    507
    "Entities with the same SharedComponentData are grouped together in the same chunks. The index to the SharedComponentData is stored once per chunk, not per Entity. As a result SharedComponentData have zero memory overhead on a per Entity basis." - Unity ECS Documentation
    https://github.com/Unity-Technologi...master/Documentation/content/ecs_in_detail.md

    I was wondering if you can *reliably* rely on entities with the same ISharedComponentData to be batched together (when using IJobParallelForBatch). Is this rule strictly reinforced?