Files
Misaki 155d7b0fbd SPMD API overhaul: gather/scatter, job & packaging updates
- ISPMDLane: add MaskGather, MaskStore, Scatter, MaskScatter; update MaskLoad/Gather signatures for hardware parity
- WideLane/ScalarLane: implement new methods with HW/fallback logic
- MathV: gather/mask-gather now delegate to lane methods
- Vector2/3/4: add CompressStore, Scatter, MaskScatter
- SPMD jobs/tests/README: migrate to new APIs for correctness
- Use Unsafe.BitCast instead of Unsafe.As/AsRef
- Add SPMDUtility for gather index extraction
- Job system: add ICustomJob<TSelf>, ScheduleCustom overload
- FreeList concurrency obsolete; always thread-safe
- NuGet: include LICENSE/README, set license/readme in .csproj
- Docs: update SPMD usage, clarify safety notes
- Minor: doc fixes, CompressStore test improvements
2026-05-04 13:56:49 +09:00

167 lines
6.5 KiB
C#

using System.Runtime.InteropServices;
namespace Misaki.HighPerformance.Jobs;
/// <summary>
/// Represents a job that performs a single unit of work.
/// </summary>
public interface IJob
{
/// <summary>
/// Executes the job logic.
/// </summary>
/// <param name="ctx">The context of the job execution, providing access to thread-specific information and job scheduling capabilities.</param>
void Execute(ref readonly JobExecutionContext ctx);
}
/// <summary>
/// Represents a job that performs the same operation for a set of items, executed in parallel.
/// </summary>
public interface IJobParallelFor
{
/// <summary>
/// Executes the job for a single item at the given index.
/// </summary>
/// <param name="loopIndex">The index of the item to process.</param>
/// <param name="ctx">The context of the job execution, providing access to thread-specific information and job scheduling capabilities.</param>
void Execute(int loopIndex, ref readonly JobExecutionContext ctx);
}
/// <summary>
/// Represents a job that performs the same operation for a set of items, executed in parallel.
/// </summary>
public interface IJobParallel
{
/// <summary>
/// Executes an operation over a specified range, optionally associating the execution with a particular thread index.
/// </summary>
/// <param name="startIndex">The zero-based index at which to begin the operation.</param>
/// <param name="endIndex">The zero-based index at which to end the operation.</param>
/// <param name="ctx">The context of the job execution, providing access to thread-specific information and job scheduling capabilities.</param>
void Execute(int startIndex, int endIndex, ref readonly JobExecutionContext ctx);
}
/// <summary>
/// Represents a custom job with user-defined execution and cleanup logic, allowing for more flexible job definitions beyond the standard interfaces.
/// </summary>
/// <typeparam name="TSelf"></typeparam>
public interface ICustomJob<TSelf>
{
/// <summary>
/// Executes the job logic, providing access to the job's own state, the job ranges for parallel execution, and the job execution context for thread-specific information and scheduling capabilities.
/// </summary>
/// <param name="job">The job instance to execute.</param>
/// <param name="jobRanges">The ranges of items to process.</param>
/// <param name="ctx">The context of the job execution.</param>
static abstract void Execute(ref TSelf job, ref JobRanges jobRanges, ref readonly JobExecutionContext ctx);
/// <summary>
/// Frees any resources associated with the job after execution, allowing for cleanup of unmanaged resources or other necessary finalization steps.
/// </summary>
/// <param name="job">The job instance to clean up.</param>
static abstract void Free(ref TSelf job);
}
internal unsafe struct CombinedDependenciesJob : IJob
{
public JobHandle* dependencies;
public int dependencyCount;
public readonly void Execute(ref readonly JobExecutionContext ctx)
{
var span = new Span<JobHandle>(dependencies, dependencyCount);
ctx.JobScheduler.WaitAll(span);
NativeMemory.Free(dependencies);
}
}
public static class IJobExtensions
{
/// <summary>
/// Runs the job in the calling thread, blocking until the job is complete.
/// </summary>
/// <typeparam name="T">The type of the job.</typeparam>
/// <param name="job">The job to run.</param>
/// <param name="ctx">The job execution context.</param>
public static void Run<T>(this T job, ref readonly JobExecutionContext ctx)
where T : IJob
{
job.Execute(in ctx);
}
/// <summary>
/// Runs the job by reference in the calling thread, blocking until the job is complete.
/// </summary>
/// <typeparam name="T">The type of the job.</typeparam>
/// <param name="job">The job to run.</param>
/// <param name="ctx">The job execution context.</param>
public static void RunRef<T>(this ref T job, ref readonly JobExecutionContext ctx)
where T : struct, IJob
{
job.Execute(in ctx);
}
}
public static class IJobParallelForExtensions
{
/// <summary>
/// Runs the job in the calling thread, blocking until the job is complete.
/// </summary>
/// <typeparam name="T">The type of the job.</typeparam>
/// <param name="job">The job to run.</param>
/// <param name="totalIterations">The total number of iterations.</param>
/// <param name="ctx">The job execution context.</param>
public static void Run<T>(this T job, int totalIterations, ref readonly JobExecutionContext ctx)
where T : IJobParallelFor
{
for (var i = 0; i < totalIterations; i++)
{
job.Execute(i, in ctx);
}
}
/// <summary>
/// Runs the job by reference in the calling thread, blocking until the job is complete.
/// </summary>
/// <typeparam name="T">The type of the job.</typeparam>
/// <param name="job">The job to run.</param>
/// <param name="totalIterations">The total number of iterations.</param>
/// <param name="ctx">The job execution context.</param>
public static void RunRef<T>(this ref T job, int totalIterations, ref readonly JobExecutionContext ctx)
where T : struct, IJobParallelFor
{
for (var i = 0; i < totalIterations; i++)
{
job.Execute(i, in ctx);
}
}
}
public static class IJobParallelExtensions
{
/// <summary>
/// Runs the job in the calling thread, blocking until the job is complete.
/// </summary>
/// <typeparam name="T">The type of the job.</typeparam>
/// <param name="job">The job to run.</param>
/// <param name="totalIterations">The total number of iterations.</param>
/// <param name="ctx">The job execution context.</param>
public static void Run<T>(this T job, int totalIterations, ref readonly JobExecutionContext ctx)
where T : IJobParallel
{
job.Execute(0, totalIterations, in ctx);
}
/// <summary>
/// Runs the job by reference in the calling thread, blocking until the job is complete.
/// </summary>
/// <typeparam name="T">The type of the job.</typeparam>
/// <param name="job">The job to run.</param>
/// <param name="totalIterations">The total number of iterations.</param>
/// <param name="ctx">The job execution context.</param>
public static void RunRef<T>(this ref T job, int totalIterations, ref readonly JobExecutionContext ctx)
where T : struct, IJobParallel
{
job.Execute(0, totalIterations, in ctx);
}
}