Switch matrix parallel to task stealing, type and wrap are refacored, thread execution core has not yet
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user