#Is it worth it to run this job in parallel?

1 messages · Page 1 of 1 (latest)

raven knoll
#

Wondering is it worth running this job in parallel, as there are only about 10 entities with the BiomeData component. Are there any advantages or disadvantages? ```cs
public partial struct BiomeEntityJob : IJobEntity
{
[ReadOnly]
public Color BlockColour;

    public NativeReference<Entity> BiomeEntity;

    void Execute(ref BiomeData Biome, Entity entity)
    {
        if (math.distance(((float4)(Vector4)Biome.ColourSpawn).xyz, ((float4)(Vector4)BlockColour).xyz) <= Biome.MaxDistance/100)
        {
            BiomeEntity.Value = entity;
        }
    }
}
stray sun
#

I am guessing that the scheduling overhead would be more than the actual work for 10 entities here. You could also just use idiomatic foreach inside a bursted ISystem (which I would guess would be faster). Something like:

foreach (var (biome, biomeEntity) in Query<RefRO<BiomeData>, RefRW<BiomeEntity>>())
{
  if (math.distance( ((float4(Vector4)biome.ValueRO.ColourSpawn).xyz, ((float4)(Vector4)BlockColour).xyz) <= biome.ValueRO.MaxDistance/100)
  {
    biomeEntity.ValueRW.Value = entity;
  }
}
#

That way you can just capture BlockColour in your foreach statement as well (instead of copying it into a job struct).

strong cairn
#

It's best to profile to help make the right choice as there can be a bit of nuance.

While we always trying to drive down job system overhead, there will always be some.

Jobs are copied so there is a cost there (Note IJobEntity are converted into to IJobChunks which use a JobWrapper which will increase the size of the job to a bit bigger than just your defined jobdata)

Job threads can be asleep. If this is the job to wake the worker thread then you'll pay a wake up cost that varies but can be ~10us.

However if your job has a dependency, then as long as scheduling of this job isn't a long-time after the dependency was scheduled, then the odds are workers are awake and will pick up the job very quickly. (alternatively if you have lots of jobs, you tend to keep workers awake longer so that helps avoid the wake up cost as well)

The main comparison point to look at is how long your job runs if run directly on the main thread (e.g. using the idiomatic foreach as mentioned above or you can call RunByRef() instead of Schedule (RunByRef will avoid the copy of the job data)) vs the creation of the job struct + Schedule call. If running single threaded is smaller than the schedule then the job is too small. You can measure this by using the profile marker API.

Another bit to keep in mind is if the number of entities will ever change. Jobs will keep the main thread with a fixed cost (scheduling the job) where as the main thread will get slower and slower if jobs are converted to run directly on the main thread

silver token
#

Do we actually have that job overhead with IJobEntity even when we run them on mainthread? Is idomatic foreach faster than a Job on mainthread? My current way of doing things is writing jobs for everything and then deciding after the fact whether i .Run or .Schedule it.

strong cairn
#

Yes. .Run/RunByRef will still run job safety checks, setup temp memory scopes, and do an internal copy of some job data, so it will add overhead compared to idiomatic foreach which tries to generate the contents of your job's Execute() inline in your system's Update

#

My current way of doing things is writing jobs for everything and then deciding after the fact whether i .Run or .Schedule it.
This is a fine approach and is the only way you're going to get performance that scales to the hardware.

#

The main bit is to ensure your jobs are not too small such that overhead takes over the advantage of deferring the work. And for that you'll need to profile a bit to see what fits best.

But if your approach is to jobify your code first, you're off to a good start and you can profile and convert to jobs to run on the main thread when you notice performance problems due to job size being too small

near oar
#

this just gave me a thought, it would be possible to have the best of both worlds, just have an If(calculateentitycount()) query so that when the number is below a certain threshold it runs in a standard foreach on the main thread but when it goes over the threshold it divertes to Ijobentity() multithreaded version

golden mantle
#

The cost of calculating entities might well be higher than the cost of scheduling the job

near oar
#

oh really interesting, I didn't realize it was that costly

golden mantle
#

Or job scheduling isn't /that/ bad? 🤔

near oar
#

I guess there "may" be a point where it does make sense but its a matter of will the number of entities fluctuate often enough to make it worth it