Search Unity

Clarification required: Won't jobs stack when queued in Update()?

Discussion in 'Data Oriented Technology Stack' started by Freaking-Pingo, Feb 25, 2018.

  1. Freaking-Pingo

    Freaking-Pingo

    Joined:
    Aug 1, 2012
    Posts:
    304
    Hi all, I require some clarification on the C# Job system.

    I tried the Job System Cookbook example and looked at the AccelerationParallelFor.cs example:
    The following code can be found in that script:

    Code (CSharp):
    1.     public void Update()
    2.     {
    3.         m_AccelJob = new AccelerationJob()
    4.         {
    5.             deltaTime = Time.deltaTime,
    6.             velocity = m_Velocities,
    7.             acceleration = m_Acceleration,
    8.             accelerationMod = m_AccelerationMod
    9.         };
    10.  
    11.         m_Job = new PositionUpdateJob()
    12.         {
    13.             deltaTime = Time.deltaTime,
    14.             velocity = m_Velocities,
    15.         };
    16.  
    17.         m_AccelJobHandle = m_AccelJob.Schedule(m_ObjectCount, 64);
    18.         m_PositionJobHandle = m_Job.Schedule(m_TransformsAccessArray, m_AccelJobHandle);
    19.     }
    Here is something I don't understand, if you queue up jobs in Update() aren't you in the risk of endlessly stacking jobs if the jobs are processed slower than Update can queue them? Am I in the wrong here or is there something I am missing? I haven't seen an example yet where there have been implemented any safeguards to prevent this.
     
  2. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    4,025
    In LateUpdate(), the job is forced to complete:
    Code (CSharp):
    1. public void LateUpdate()
    2. {
    3.     m_PositionJobHandle.Complete();
    4. }
     
  3. Freaking-Pingo

    Freaking-Pingo

    Joined:
    Aug 1, 2012
    Posts:
    304
    Baah! Thank you, that makes some sense to me then.
     
  4. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    4,671
    Additionally the default is that jobs are only in a local queue, they are not scheduled automatically you need to call
    JobHandle.ScheduleBatchedJobs(); (Note: JobHandle.Complete(); does so implicitly)

    In Entity Component System this happens after each system has run automatically, but for MonoBehaviour you need to do it manually. It is best to call JobHandle.ScheduleBatchedJobs(); after a set of jobs have been scheduled (This reduces the amount of semaphore signal traffic on the job queue) So in your sample code above the appropriate thing to do is to call:
    JobHandle.ScheduleBatchedJobs(); at the end of the Update() method.

    In LateUpdate or next frame, depending on what you are trying to do:
    You use JobHandle.Complete(); to ensure the job has completed.
     
    Freaking-Pingo and Krajca like this.
  5. OswaldHurlem

    OswaldHurlem

    Joined:
    Jan 6, 2017
    Posts:
    40
    I'm curious what you mean when you say "jobs are only in a local queue"... what is the queue local to?
     
  6. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    4,671
    The local queue is on the main thread. It's like a staging buffer of things that will be pushed into the job queue, when its pushed into the job queue, we wake up worker threads if they are asleep.