using Misaki.HighPerformance.Jobs; using System.Numerics; namespace Misaki.HighPerformance.Mathematics.SPMD; /// /// A job interface for Single Program Multiple Data (SPMD) execution, allowing for efficient parallel processing of data across multiple lanes. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. public interface IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { void Execute(TLane0 indices, TLane0 mask, ref readonly JobExecutionContext ctx) where TLane0 : unmanaged, ISPMDLane; } internal struct SPMDJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); innerJob.Execute>(indices, mask, in ctx); } } internal struct SPMDScalerJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { innerJob.Execute>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } /// /// A job interface for Single Program Multiple Data (SPMD) execution, allowing for efficient parallel processing of data across multiple lanes. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. public interface IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { void Execute(TLane0 indices, TLane0 mask, ref readonly JobExecutionContext ctx) where TLane0 : unmanaged, ISPMDLane where TLane1 : unmanaged, ISPMDLane; } internal struct SPMDJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); innerJob.Execute, WideLane>(indices, mask, in ctx); } } internal struct SPMDScalerJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { innerJob.Execute, ScalarLane>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } /// /// A job interface for Single Program Multiple Data (SPMD) execution, allowing for efficient parallel processing of data across multiple lanes. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. public interface IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { void Execute(TLane0 indices, TLane0 mask, ref readonly JobExecutionContext ctx) where TLane0 : unmanaged, ISPMDLane where TLane1 : unmanaged, ISPMDLane where TLane2 : unmanaged, ISPMDLane; } internal struct SPMDJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); innerJob.Execute, WideLane, WideLane>(indices, mask, in ctx); } } internal struct SPMDScalerJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { innerJob.Execute, ScalarLane, ScalarLane>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } /// /// A job interface for Single Program Multiple Data (SPMD) execution, allowing for efficient parallel processing of data across multiple lanes. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. public interface IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { void Execute(TLane0 indices, TLane0 mask, ref readonly JobExecutionContext ctx) where TLane0 : unmanaged, ISPMDLane where TLane1 : unmanaged, ISPMDLane where TLane2 : unmanaged, ISPMDLane where TLane3 : unmanaged, ISPMDLane; } internal struct SPMDJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); innerJob.Execute, WideLane, WideLane, WideLane>(indices, mask, in ctx); } } internal struct SPMDScalerJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { innerJob.Execute, ScalarLane, ScalarLane, ScalarLane>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } /// /// A job interface for Single Program Multiple Data (SPMD) execution, allowing for efficient parallel processing of data across multiple lanes. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. public interface IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { void Execute(TLane0 indices, TLane0 mask, ref readonly JobExecutionContext ctx) where TLane0 : unmanaged, ISPMDLane where TLane1 : unmanaged, ISPMDLane where TLane2 : unmanaged, ISPMDLane where TLane3 : unmanaged, ISPMDLane where TLane4 : unmanaged, ISPMDLane; } internal struct SPMDJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); innerJob.Execute, WideLane, WideLane, WideLane, WideLane>(indices, mask, in ctx); } } internal struct SPMDScalerJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { innerJob.Execute, ScalarLane, ScalarLane, ScalarLane, ScalarLane>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } /// /// A job interface for Single Program Multiple Data (SPMD) execution, allowing for efficient parallel processing of data across multiple lanes. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. public interface IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { void Execute(TLane0 indices, TLane0 mask, ref readonly JobExecutionContext ctx) where TLane0 : unmanaged, ISPMDLane where TLane1 : unmanaged, ISPMDLane where TLane2 : unmanaged, ISPMDLane where TLane3 : unmanaged, ISPMDLane where TLane4 : unmanaged, ISPMDLane where TLane5 : unmanaged, ISPMDLane; } internal struct SPMDJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); innerJob.Execute, WideLane, WideLane, WideLane, WideLane, WideLane>(indices, mask, in ctx); } } internal struct SPMDScalerJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { innerJob.Execute, ScalarLane, ScalarLane, ScalarLane, ScalarLane, ScalarLane>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } /// /// A job interface for Single Program Multiple Data (SPMD) execution, allowing for efficient parallel processing of data across multiple lanes. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. public interface IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber6 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { void Execute(TLane0 indices, TLane0 mask, ref readonly JobExecutionContext ctx) where TLane0 : unmanaged, ISPMDLane where TLane1 : unmanaged, ISPMDLane where TLane2 : unmanaged, ISPMDLane where TLane3 : unmanaged, ISPMDLane where TLane4 : unmanaged, ISPMDLane where TLane5 : unmanaged, ISPMDLane where TLane6 : unmanaged, ISPMDLane; } internal struct SPMDJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber6 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); innerJob.Execute, WideLane, WideLane, WideLane, WideLane, WideLane, WideLane>(indices, mask, in ctx); } } internal struct SPMDScalerJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber6 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { innerJob.Execute, ScalarLane, ScalarLane, ScalarLane, ScalarLane, ScalarLane, ScalarLane>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } /// /// A job interface for Single Program Multiple Data (SPMD) execution, allowing for efficient parallel processing of data across multiple lanes. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. public interface IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber6 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber7 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { void Execute(TLane0 indices, TLane0 mask, ref readonly JobExecutionContext ctx) where TLane0 : unmanaged, ISPMDLane where TLane1 : unmanaged, ISPMDLane where TLane2 : unmanaged, ISPMDLane where TLane3 : unmanaged, ISPMDLane where TLane4 : unmanaged, ISPMDLane where TLane5 : unmanaged, ISPMDLane where TLane6 : unmanaged, ISPMDLane where TLane7 : unmanaged, ISPMDLane; } internal struct SPMDJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber6 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber7 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); innerJob.Execute, WideLane, WideLane, WideLane, WideLane, WideLane, WideLane, WideLane>(indices, mask, in ctx); } } internal struct SPMDScalerJobWrapper : IJobParallelFor where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber6 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber7 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public T innerJob; public int totalIteration; public void Execute(int loopIndex, ref readonly JobExecutionContext ctx) { innerJob.Execute, ScalarLane, ScalarLane, ScalarLane, ScalarLane, ScalarLane, ScalarLane, ScalarLane>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } public static class IJobParallelForSPMDExtensions { /// /// Run the SPMD job with the specified total count and job execution context directly on the calling thread. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The SPMD job to run. /// The total number of iterations to execute across all lanes. /// The job execution context providing information about the current execution environment. public static void Run(this T job, int totalIteration, ref readonly JobExecutionContext ctx) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; for (var loopIndex = 0; loopIndex < iterations; loopIndex++) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); job.Execute>(indices, mask, in ctx); } } else { for (var loopIndex = 0; loopIndex < totalIteration; loopIndex++) { job.Execute>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } } /// /// Schedule the SPMD job for parallel execution across multiple threads, with the specified total count, batch size, and job execution context. /// /// The first numeric type used in the SPMD job. /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The job scheduler to use for scheduling the job. /// The SPMD job to schedule. /// The total number of iterations to execute across all lanes. /// The number of iterations to execute in each batch for parallel execution. /// Whether to prefer scheduling the job on the local thread for better cache locality. /// The priority of the job. /// Any job handles that this job depends on, which must complete before this job can start. public static JobHandle ScheduleParallelSPDM(this JobScheduler jobScheduler, ref T job, int totalIteration, int batchSize, bool preferLocal, JobPriority priority, params ReadOnlySpan dependencies) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var warper = new SPMDJobWrapper { innerJob = job, totalIteration = totalIteration, }; var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; return jobScheduler.ScheduleParallelFor(ref warper, iterations, batchSize, preferLocal, priority, dependencies); } else { var warper = new SPMDScalerJobWrapper { innerJob = job, totalIteration = totalIteration, }; return jobScheduler.ScheduleParallelFor(ref warper, totalIteration, batchSize, preferLocal, priority, dependencies); } } /// /// Run the SPMD job with the specified total count and job execution context directly on the calling thread. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The SPMD job to run. /// The total number of iterations to execute across all lanes. /// The job execution context providing information about the current execution environment. public static void Run(this T job, int totalIteration, ref readonly JobExecutionContext ctx) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; for (var loopIndex = 0; loopIndex < iterations; loopIndex++) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); job.Execute, WideLane>(indices, mask, in ctx); } } else { for (var loopIndex = 0; loopIndex < totalIteration; loopIndex++) { job.Execute, ScalarLane>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } } /// /// Schedule the SPMD job for parallel execution across multiple threads, with the specified total count, batch size, and job execution context. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The job scheduler to use for scheduling the job. /// The SPMD job to schedule. /// The total number of iterations to execute across all lanes. /// The number of iterations to execute in each batch for parallel execution. /// Whether to prefer scheduling the job on the local thread for better cache locality. /// The priority of the job. /// Any job handles that this job depends on, which must complete before this job can start. public static JobHandle ScheduleParallelSPDM(this JobScheduler jobScheduler, ref T job, int totalIteration, int batchSize, bool preferLocal, JobPriority priority, params ReadOnlySpan dependencies) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var warper = new SPMDJobWrapper { innerJob = job, totalIteration = totalIteration, }; var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; return jobScheduler.ScheduleParallelFor(ref warper, iterations, batchSize, preferLocal, priority, dependencies); } else { var warper = new SPMDScalerJobWrapper { innerJob = job, totalIteration = totalIteration, }; return jobScheduler.ScheduleParallelFor(ref warper, totalIteration, batchSize, preferLocal, priority, dependencies); } } /// /// Run the SPMD job with the specified total count and job execution context directly on the calling thread. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The SPMD job to run. /// The total number of iterations to execute across all lanes. /// The job execution context providing information about the current execution environment. public static void Run(this T job, int totalIteration, ref readonly JobExecutionContext ctx) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; for (var loopIndex = 0; loopIndex < iterations; loopIndex++) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); job.Execute, WideLane, WideLane>(indices, mask, in ctx); } } else { for (var loopIndex = 0; loopIndex < totalIteration; loopIndex++) { job.Execute, ScalarLane, ScalarLane>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } } /// /// Schedule the SPMD job for parallel execution across multiple threads, with the specified total count, batch size, and job execution context. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The job scheduler to use for scheduling the job. /// The SPMD job to schedule. /// The total number of iterations to execute across all lanes. /// The number of iterations to execute in each batch for parallel execution. /// Whether to prefer scheduling the job on the local thread for better cache locality. /// The priority of the job. /// Any job handles that this job depends on, which must complete before this job can start. public static JobHandle ScheduleParallelSPDM(this JobScheduler jobScheduler, ref T job, int totalIteration, int batchSize, bool preferLocal, JobPriority priority, params ReadOnlySpan dependencies) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var warper = new SPMDJobWrapper { innerJob = job, totalIteration = totalIteration, }; var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; return jobScheduler.ScheduleParallelFor(ref warper, iterations, batchSize, preferLocal, priority, dependencies); } else { var warper = new SPMDScalerJobWrapper { innerJob = job, totalIteration = totalIteration, }; return jobScheduler.ScheduleParallelFor(ref warper, totalIteration, batchSize, preferLocal, priority, dependencies); } } /// /// Run the SPMD job with the specified total count and job execution context directly on the calling thread. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The SPMD job to run. /// The total number of iterations to execute across all lanes. /// The job execution context providing information about the current execution environment. public static void Run(this T job, int totalIteration, ref readonly JobExecutionContext ctx) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; for (var loopIndex = 0; loopIndex < iterations; loopIndex++) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); job.Execute, WideLane, WideLane, WideLane>(indices, mask, in ctx); } } else { for (var loopIndex = 0; loopIndex < totalIteration; loopIndex++) { job.Execute, ScalarLane, ScalarLane, ScalarLane>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } } /// /// Schedule the SPMD job for parallel execution across multiple threads, with the specified total count, batch size, and job execution context. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The job scheduler to use for scheduling the job. /// The SPMD job to schedule. /// The total number of iterations to execute across all lanes. /// The number of iterations to execute in each batch for parallel execution. /// Whether to prefer scheduling the job on the local thread for better cache locality. /// The priority of the job. /// Any job handles that this job depends on, which must complete before this job can start. public static JobHandle ScheduleParallelSPDM(this JobScheduler jobScheduler, ref T job, int totalIteration, int batchSize, bool preferLocal, JobPriority priority, params ReadOnlySpan dependencies) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var warper = new SPMDJobWrapper { innerJob = job, totalIteration = totalIteration, }; var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; return jobScheduler.ScheduleParallelFor(ref warper, iterations, batchSize, preferLocal, priority, dependencies); } else { var warper = new SPMDScalerJobWrapper { innerJob = job, totalIteration = totalIteration, }; return jobScheduler.ScheduleParallelFor(ref warper, totalIteration, batchSize, preferLocal, priority, dependencies); } } /// /// Run the SPMD job with the specified total count and job execution context directly on the calling thread. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The SPMD job to run. /// The total number of iterations to execute across all lanes. /// The job execution context providing information about the current execution environment. public static void Run(this T job, int totalIteration, ref readonly JobExecutionContext ctx) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; for (var loopIndex = 0; loopIndex < iterations; loopIndex++) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); job.Execute, WideLane, WideLane, WideLane, WideLane>(indices, mask, in ctx); } } else { for (var loopIndex = 0; loopIndex < totalIteration; loopIndex++) { job.Execute, ScalarLane, ScalarLane, ScalarLane, ScalarLane>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } } /// /// Schedule the SPMD job for parallel execution across multiple threads, with the specified total count, batch size, and job execution context. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The job scheduler to use for scheduling the job. /// The SPMD job to schedule. /// The total number of iterations to execute across all lanes. /// The number of iterations to execute in each batch for parallel execution. /// Whether to prefer scheduling the job on the local thread for better cache locality. /// The priority of the job. /// Any job handles that this job depends on, which must complete before this job can start. public static JobHandle ScheduleParallelSPDM(this JobScheduler jobScheduler, ref T job, int totalIteration, int batchSize, bool preferLocal, JobPriority priority, params ReadOnlySpan dependencies) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var warper = new SPMDJobWrapper { innerJob = job, totalIteration = totalIteration, }; var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; return jobScheduler.ScheduleParallelFor(ref warper, iterations, batchSize, preferLocal, priority, dependencies); } else { var warper = new SPMDScalerJobWrapper { innerJob = job, totalIteration = totalIteration, }; return jobScheduler.ScheduleParallelFor(ref warper, totalIteration, batchSize, preferLocal, priority, dependencies); } } /// /// Run the SPMD job with the specified total count and job execution context directly on the calling thread. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The SPMD job to run. /// The total number of iterations to execute across all lanes. /// The job execution context providing information about the current execution environment. public static void Run(this T job, int totalIteration, ref readonly JobExecutionContext ctx) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; for (var loopIndex = 0; loopIndex < iterations; loopIndex++) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); job.Execute, WideLane, WideLane, WideLane, WideLane, WideLane>(indices, mask, in ctx); } } else { for (var loopIndex = 0; loopIndex < totalIteration; loopIndex++) { job.Execute, ScalarLane, ScalarLane, ScalarLane, ScalarLane, ScalarLane>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } } /// /// Schedule the SPMD job for parallel execution across multiple threads, with the specified total count, batch size, and job execution context. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The job scheduler to use for scheduling the job. /// The SPMD job to schedule. /// The total number of iterations to execute across all lanes. /// The number of iterations to execute in each batch for parallel execution. /// Whether to prefer scheduling the job on the local thread for better cache locality. /// The priority of the job. /// Any job handles that this job depends on, which must complete before this job can start. public static JobHandle ScheduleParallelSPDM(this JobScheduler jobScheduler, ref T job, int totalIteration, int batchSize, bool preferLocal, JobPriority priority, params ReadOnlySpan dependencies) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var warper = new SPMDJobWrapper { innerJob = job, totalIteration = totalIteration, }; var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; return jobScheduler.ScheduleParallelFor(ref warper, iterations, batchSize, preferLocal, priority, dependencies); } else { var warper = new SPMDScalerJobWrapper { innerJob = job, totalIteration = totalIteration, }; return jobScheduler.ScheduleParallelFor(ref warper, totalIteration, batchSize, preferLocal, priority, dependencies); } } /// /// Run the SPMD job with the specified total count and job execution context directly on the calling thread. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The SPMD job to run. /// The total number of iterations to execute across all lanes. /// The job execution context providing information about the current execution environment. public static void Run(this T job, int totalIteration, ref readonly JobExecutionContext ctx) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber6 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; for (var loopIndex = 0; loopIndex < iterations; loopIndex++) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); job.Execute, WideLane, WideLane, WideLane, WideLane, WideLane, WideLane>(indices, mask, in ctx); } } else { for (var loopIndex = 0; loopIndex < totalIteration; loopIndex++) { job.Execute, ScalarLane, ScalarLane, ScalarLane, ScalarLane, ScalarLane, ScalarLane>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } } /// /// Schedule the SPMD job for parallel execution across multiple threads, with the specified total count, batch size, and job execution context. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The job scheduler to use for scheduling the job. /// The SPMD job to schedule. /// The total number of iterations to execute across all lanes. /// The number of iterations to execute in each batch for parallel execution. /// Whether to prefer scheduling the job on the local thread for better cache locality. /// The priority of the job. /// Any job handles that this job depends on, which must complete before this job can start. public static JobHandle ScheduleParallelSPDM(this JobScheduler jobScheduler, ref T job, int totalIteration, int batchSize, bool preferLocal, JobPriority priority, params ReadOnlySpan dependencies) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber6 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var warper = new SPMDJobWrapper { innerJob = job, totalIteration = totalIteration, }; var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; return jobScheduler.ScheduleParallelFor(ref warper, iterations, batchSize, preferLocal, priority, dependencies); } else { var warper = new SPMDScalerJobWrapper { innerJob = job, totalIteration = totalIteration, }; return jobScheduler.ScheduleParallelFor(ref warper, totalIteration, batchSize, preferLocal, priority, dependencies); } } /// /// Run the SPMD job with the specified total count and job execution context directly on the calling thread. /// /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The SPMD job to run. /// The total number of iterations to execute across all lanes. /// The job execution context providing information about the current execution environment. public static void Run(this T job, int totalIteration, ref readonly JobExecutionContext ctx) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber6 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber7 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; for (var loopIndex = 0; loopIndex < iterations; loopIndex++) { var baseIndex = loopIndex * WideLane.LaneWidth; var indices = WideLane.Sequence(TNumber0.CreateTruncating(baseIndex), TNumber0.One); var mask = indices < TNumber0.CreateTruncating(totalIteration); job.Execute, WideLane, WideLane, WideLane, WideLane, WideLane, WideLane, WideLane>(indices, mask, in ctx); } } else { for (var loopIndex = 0; loopIndex < totalIteration; loopIndex++) { job.Execute, ScalarLane, ScalarLane, ScalarLane, ScalarLane, ScalarLane, ScalarLane, ScalarLane>(TNumber0.CreateTruncating(loopIndex), ScalarLane.AllBitsSet, in ctx); } } } /// /// Schedule the SPMD job for parallel execution across multiple threads, with the specified total count, batch size, and job execution context. /// /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// The first numeric type used in the SPMD job. /// /// Always use TNumber0 as the primary type for determining lane width and job scheduling, even if it's not used in the job execution. /// /// The job scheduler to use for scheduling the job. /// The SPMD job to schedule. /// The total number of iterations to execute across all lanes. /// The number of iterations to execute in each batch for parallel execution. /// Whether to prefer scheduling the job on the local thread for better cache locality. /// The priority of the job. /// Any job handles that this job depends on, which must complete before this job can start. public static JobHandle ScheduleParallelSPDM(this JobScheduler jobScheduler, ref T job, int totalIteration, int batchSize, bool preferLocal, JobPriority priority, params ReadOnlySpan dependencies) where T : IJobSPMD where TNumber0 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber1 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber2 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber3 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber4 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber5 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber6 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators where TNumber7 : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { if (WideLane.IsSupported) { var warper = new SPMDJobWrapper { innerJob = job, totalIteration = totalIteration, }; var iterations = (totalIteration + WideLane.LaneWidth - 1) / WideLane.LaneWidth; return jobScheduler.ScheduleParallelFor(ref warper, iterations, batchSize, preferLocal, priority, dependencies); } else { var warper = new SPMDScalerJobWrapper { innerJob = job, totalIteration = totalIteration, }; return jobScheduler.ScheduleParallelFor(ref warper, totalIteration, batchSize, preferLocal, priority, dependencies); } } }