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

Question ScheduleParallel() vs Schedule() vs Run() overhead cost

Discussion in 'Entity Component System' started by l33t_P4j33t, Jan 6, 2022.

  1. l33t_P4j33t

    l33t_P4j33t

    Joined:
    Jul 29, 2019
    Posts:
    232
    I have allot of fairly simple systems that act on single entities (rpcs mostly, and single frame events when the player interacts with items)
    how should it be run: .ScheduleParallel(), Schedule(), or Run()?
    (assuming .run updates in late simulation so as to not block the main thread)

    best practices seems to say to always use schedule parallel, but the cost seems many times higher in the editor.
    don't know how i would go about testing that in build, as there is no way to change schedule mode at runtime and compare the fps



    turning off safety checks does not actually do anything it seems.
    UNITY_ENABLE_SAFETY_CHECKS define is still defined
     

    Attached Files:

  2. desertGhost_

    desertGhost_

    Joined:
    Apr 12, 2018
    Posts:
    258
    I use Run on anything that is both light in computations and light in the number of entities. In fact, since much of my game code deals with less than 50 entity instances, I use run in most systems. There is an inherent cost to scheduling jobs that can make it not worth to run them on few entities. Hopely, ISystem will alleviate that.

    I would also like to know, when running IJobChunks is it better to use Run or RunWithoutJobs?
     
  3. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,068
    AFAIK Parallelism is one of the main features of the data-driven design.
    I think the systems design needs to be somewhere similar to GPU programming by maximizing parallelism and minimizing task execution time.
    so having 10 systems running in parallel for ~ 0.4ms each will always be better than 10 systems running synchronously for ~ 0.2ms each.
     
  4. l33t_P4j33t

    l33t_P4j33t

    Joined:
    Jul 29, 2019
    Posts:
    232
    another question:
    if you know that the system will only run on 1 entity, would .schedule be better than schedule parallel, since either way 1 thread would work on 1 entity?
    assuming schedule is cheaper than schedule parallel
     
    Last edited: Jan 6, 2022
  5. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,068
    in this case I wouldn't think much about the entities, I would be more focused on the amount of work.
    the real question is, is the amount of work huge enough to be spread across many worker threads?
     
  6. Rupture13

    Rupture13

    Joined:
    Apr 12, 2016
    Posts:
    129
    A job operates on one chunk of entities rather than on one entity. So even if you have 100 entities that all fit in the same chunk and execute some parallel job on those, only one thread will work on it.

    The question still stands, though. If there's no difference in the amount of threads working on the job (due to there only being one chunk to work on), does ScheduleParallel have extra overhead?
     
    StickyKevin and Opeth001 like this.
  7. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    677
    Run() will not only run in the main thread as it will also block the main thread until all operations related to the target components are finished to avoid race conditions

    So, if you want to keep using full power of parallelism, use Schedule/ScheduleParallel instead. SchedurelParallel is heavier, so I would prefer Schedule for when the number of chunks is known to be low.

    I recall having a feature request somewhere about having something like a ScheduleSingleOrParallel API to decide to use either Schedule or ScheduleParallel based on the entity/chunk count, but can't remember if Unity team said anything about it.
     
  8. l33t_P4j33t

    l33t_P4j33t

    Joined:
    Jul 29, 2019
    Posts:
    232
    Ok.
    I've done some testing.
    all of the schedule / schedule parallel Entities.Foreach invariably call ScheduleInternal.
    so I did this hack to change the function arguments to make a schedule parallel into a schedule / run:

    and the results are:..
    no difference
    judging by the timings in the entity debugger
    they ran just as poorly as when in parallel, but sped up when unchecking use-multiple-threads

    I did a test to make sure.

    sure enough, the debugger goes from spitting out bunch of different numbers corresponding to the threads to just one, when activating the hack.

    funnily enough, the system outputted different numbers for client and server.
    i guess that explains why you get errors when doing api calls from a job that has burst disabled and with.run()

    .run on a job doesn't guarantee that it'll be the main main thread

    So then I made two separate builds, one with schedule parallel and one with a couple heavy-use systems having their job ending replaced manually from ScheduleParallel() to .Run();

    and again:
    no difference, judging by the fps counter

    in conclusion:
    -unless I've done something wrong, it appears ScheduleParallel has absolutely no cost when in build.
    -unchecking Use Job Threads speeds up some systems not because they suddenly run on one thread, but because safety gets turned off

    so as the guide says, always schedule parallel

    would be interested to hear if anyone else has different results
     

    Attached Files:

  9. slims

    slims

    Joined:
    Dec 31, 2013
    Posts:
    86
    You probably don't need to use ECS if this is the case.
     
  10. desertGhost_

    desertGhost_

    Joined:
    Apr 12, 2018
    Posts:
    258
    Please note that when I said 50 entity instances, I was not referring to any child entities or entities that make up the world (colliders, renderers, etc), but only the entities that represent the top level entity of a player / bot in a multiplayer shooter.

    The code in our systems is perfectly suited for parallelism, but with the current overhead of scheduling a job, it is simply faster to use run, then schedule jobs. We are still getting a speed up over using monobehaviour code when using DOTS largely due to the code being bursted. The superiority of the Unity Physics for query logic, the ability to easily parallelize specific performance intensive tasks, and the performance of data oriented, bursted code makes DOTS worth it to use even on a smaller set of entities.
     
    DevViktoria and Opeth001 like this.