Switch matrix parallel to task stealing, type and wrap are refacored, thread execution core has not yet

This commit is contained in:
Youmu Liu
2026-02-24 15:12:23 +08:00
parent d99c1e3aa6
commit d62e59cb93
21 changed files with 1000 additions and 965 deletions
@@ -25,159 +25,18 @@
//
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
using StgSharp.HighPerformance;
using StgSharp.Collections;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net.WebSockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace StgSharp.Mathematics.Numeric
{
public unsafe class MatrixParallelWrap
{
private int _begin;
private int _remainThreadCount;
private readonly MatrixParallelHandle _handle;
internal MatrixParallelWrap(
MatrixParallelHandle handle,
int begin,
int count
)
{
WrapTaskCapacity = count;
_handle = handle;
_begin = begin;
for (int i = 0; i < WrapTaskCapacity; i++)
{
Threads[i].Role = MatrixParallelThread.RoleType.Worker;
Threads[i].BindedWrap = this;
}
Threads[0].Role = MatrixParallelThread.RoleType.Scheduler;
}
public static SleepMode AfterWork
{
get;
set => Interlocked.Exchange(ref Unsafe.As<SleepMode, int>(ref field), (int)value);
}
internal int Magic { get; set; }
private ReadOnlySpan<MatrixParallelThread> Threads
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _handle.Threads[_begin..(_begin + WrapTaskCapacity)];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ReportThreadAccomplished()
{
Interlocked.Decrement(ref _remainThreadCount);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ReportWrapAccomplished()
{
_handle.ReportWrapAccomplished();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetAllWorker()
{
for (int i = 1; i < WrapTaskCapacity; i++) {
Threads[i].Restart();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void WaitAllWorker()
{
SpinWait.SpinUntil(() => Volatile.Read(ref _remainThreadCount) == 0);
}
internal void PublishTaskToWorkers()
{
Queue<nint> tasks = WrapTask;
while (tasks.TryDequeue(out nint handle))
{
MatrixParallelTaskPackage* task = (MatrixParallelTaskPackage*)handle;
if ((int)task->ComputeMode.OperationStyle > 0)
{
PublishBufferTaskToWorkers(task);
} else
{
throw new NotImplementedException();
}
}
}
internal void SetScheduler()
{
MatrixParallelThread thread = Threads[0];
thread.Restart();
_ = Interlocked.Exchange(ref _remainThreadCount, WrapTaskCapacity);
}
private void PublishBufferTaskToWorkers(
MatrixParallelTaskPackage* package
)
{
ReadOnlySpan<MatrixParallelThread> pool = Threads;
if (pool.Length == 1)
{
pool[0].Tasks.Enqueue((nint)package);
return;
}
long count = Unsafe.As<int, long>(ref package->PrimCount);
long actual = count / pool.Length;
long extra = count % pool.Length;
long offset = 0;
MatrixParallelTaskPackage* current = package;
/*
string msg = $"""
Total: count={count}, length={Threads.Length}{Environment.NewLine}
""";
/**/
foreach (MatrixParallelThread thread in pool)
{
long wrapTaskLength = actual;
long ex = extra > 0 ? 1 : 0;
long length = wrapTaskLength + ex;
extra -= ex;
ref long offsetRef = ref Unsafe.As<int, long>(ref current->PrimTileOffset);
offsetRef += offset;
ref long lengthRef = ref Unsafe.As<int, long>(ref current->PrimCount);
lengthRef = length;
thread.Tasks.Enqueue((nint)current);
/*
msg += $"""
Slice to thread: total offset={offsetRef} local offset={offset}, length={lengthRef}{Environment.NewLine}
""";
/**/
current = MatrixParallelFactory.FromExistPackage(current);
offset = length;
}
// Console.WriteLine(msg);
}
#region wrap task
internal unsafe Queue<nint> WrapTask { get; set; } = [];
internal int WrapTaskCapacity { get ; init; }
#endregion
}
public enum SleepMode : int
{
@@ -186,4 +45,85 @@ namespace StgSharp.Mathematics.Numeric
DeepSleep = ThreadPriority.Lowest,
}
public class MatrixParallelWrap : IDisposable
{
private MatrixParallelThread[] _threads;
private bool _disposed = false;
private int _count;
private ManualResetEventSlim _leaderEvent = new ManualResetEventSlim(false);
public ThreadPriority AfterWork { get; private set; }
internal MatrixParallelWrap(
MatrixParallelThread[] threadArray
)
{
_threads = threadArray;
IsMultithread = threadArray.Length > 1;
_count = threadArray.Length;
}
public MatrixParallelQueue TaskQueue { get; set; }
public ReadOnlySpan<MatrixParallelThread> Threads
{
get
{
if (_disposed) {
throw new ObjectDisposedException(typeof(MatrixParallelWrap).Name);
}
return _threads;
}
}
private bool IsMultithread { get; init; }
public void Dispose()
{
if (_disposed) {
return;
}
MatrixParallel.ReturnParallelResources(ref _threads);
_disposed = true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public MatrixParallelThread GetLeader()
{
MatrixParallelThread leader = Threads[1];
leader.Role = MatrixParallelThread.RoleType.Leader;
leader.LeaderEvent = _leaderEvent;
return leader;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void LaunchParallel(
SleepMode afterWork
)
{
AfterWork = (ThreadPriority)afterWork;
MatrixParallelThread leader = GetLeader();
leader.MatrixParallelLeader();
WaitAllWraps();
}
public void WaitAllWraps()
{
if (_disposed) {
throw new ObjectDisposedException(typeof(MatrixParallelWrap).Name);
}
SpinWait.SpinUntil(() => Volatile.Read(ref _count) == 0);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ReportThreadAccomplished()
{
if (_disposed) {
throw new ObjectDisposedException(typeof(MatrixParallelWrap).Name);
}
Interlocked.Decrement(ref _count);
}
}
}