add scheduler method; fixing buffer parallel errors

This commit is contained in:
Youmu Liu
2025-11-19 18:09:25 +08:00
parent 45d1d08af8
commit 04fc55d31e
11 changed files with 272 additions and 339 deletions
@@ -93,7 +93,8 @@ namespace StgSharp.Collections
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public T[] PopRange(int count) public T[] PopRange(int count)
{ {
int i = int.Min(count, _index) - 1; int i = int.Min(count, _index);
_index -= i;
return _values[0..i]; return _values[0..i];
} }
@@ -147,8 +148,7 @@ namespace StgSharp.Collections
public static CapacityFixedStack<T> Create<T>(ReadOnlySpan<T> values) public static CapacityFixedStack<T> Create<T>(ReadOnlySpan<T> values)
{ {
CapacityFixedStack<T> stack = new(values.Length); CapacityFixedStack<T> stack = new(values.Length);
Span<T> sp = stack.GetValueLayout(); stack.PushRange(values);
values.CopyTo(sp);
return stack; return stack;
} }
@@ -68,10 +68,10 @@ namespace StgSharp.Mathematics.Numeric
MatrixParallel.ReturnParallelResources(ref pool); MatrixParallel.ReturnParallelResources(ref pool);
return ans; return ans;
} }
MatrixParallelTaskPackage<float>* package = MatrixParallelFactory.CreateBaseTask<float>(); MatrixParallelTaskPackage* package = MatrixParallelFactory.CreateBaseTask<float>();
package->Left = left.Buffer; package->Left = (nint)left.Buffer;
package->Right = right.Buffer; package->Right = (nint)right.Buffer;
package->Result = ans.Buffer; package->Result = (nint)ans.Buffer;
package->ElementSize = sizeof(float); package->ElementSize = sizeof(float);
package->PrimCount = left.KernelColumnLength; package->PrimCount = left.KernelColumnLength;
package->SecCount = left.KernelRowLength; package->SecCount = left.KernelRowLength;
@@ -80,41 +80,37 @@ namespace StgSharp.Mathematics.Numeric
MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package); MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package);
MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep); MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep);
/*
* run parallel
*/
MatrixParallelFactory.Release(package);
taskGroup.Dispose(); taskGroup.Dispose();
return ans; return ans;
} }
public static unsafe void Fill<T>(this Matrix<float> right, T value) where T : unmanaged, INumber<T> public static unsafe void Fill<T>(this Matrix<float> ans, T value) where T : unmanaged, INumber<T>
{ {
long count = (long)right.KernelColumnLength * right.KernelRowLength; long count = (long)ans.KernelColumnLength * ans.KernelRowLength;
ScalarPacket* scaler = MatrixParallelFactory.CreateScalarPacket(); ScalarPacket* scalar = MatrixParallelFactory.CreateScalarPacket();
scaler->Data<T>(0) = value; scalar->Data<T>(0) = value;
if (count <= 256) if (count <= 256)
{ {
NativeIntrinsic.Intrinsic.f32_fill(right.Buffer, scaler, count); NativeIntrinsic.Intrinsic.f32_fill(ans.Buffer, scalar, count);
return; return;
} else if (count <= 1024) } else if (count <= 1024)
{ {
MatrixParallelThread[] pool = MatrixParallel.LeadParallel(1); MatrixParallelThread[] pool = MatrixParallel.LeadParallel(1);
NativeIntrinsic.Intrinsic.f32_fill(ans.Buffer, scalar, count);
NativeIntrinsic.Intrinsic.f32_fill(right.Buffer, scaler, count);
MatrixParallel.ReturnParallelResources(ref pool); MatrixParallel.ReturnParallelResources(ref pool);
return; return;
} }
MatrixParallelHandle taskGroup =/**/ default MatrixParallelTaskPackage* package = MatrixParallelFactory.CreateBaseTask<float>();
/*MatrixParallel.PublicNoAnswerTask(left.GetColumnEnumeration(), scaler, package->Result = (nint)ans.Buffer;
(delegate* unmanaged[Cdecl]<MatrixKernel<float>*, ScalarPacket*, void>)NativeIntrinsic.Intrinsic.f32_add) package->ElementSize = sizeof(float);
/**/; package->PrimCount = ans.KernelColumnLength;
package->SecCount = ans.KernelRowLength;
package->ComputeMode = new MatrixOpMode(MatrixOperationStyle.BUFFER_OP, MatrixOperationParam.ANS_SCALAR_PARAM);
package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_fill;
package->Scalar = scalar;
MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package);
MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep); MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep);
/*
* run parallel
*/
MatrixParallelFactory.Release(scaler);
taskGroup.Dispose(); taskGroup.Dispose();
} }
@@ -34,31 +34,33 @@ namespace StgSharp.Mathematics.Numeric
internal static class MatrixComputeModel internal static class MatrixComputeModel
{ {
internal static unsafe void BufferComputeBinary(MatrixParallelTaskPackageNonGeneric* p) internal static unsafe void BufferComputeBinary(MatrixParallelTaskPackage* p)
{ {
int size = p->ElementSize * 16; int size = p->ElementSize * 16;
int count = p->PrimCount * p->SecCount; long count = Unsafe.As<int, long>(ref p->PrimCount);
int offset = p->LeftPrimOffset * p->SecCount; long offset = Unsafe.As<int, long>(ref p->PrimTileOffset) * size;
((delegate* unmanaged[Cdecl]<void*, void*, void*, int, void>)p->ComputeHandle)((void*)(p->Left + offset * size), ((delegate* unmanaged[Cdecl]<void*, void*, void*, long, void>)p->ComputeHandle)((void*)(p->Left + offset),
(void*)(p->Right + offset * size), (void*)(p->Right + offset),
(void*)(p->Result + offset * size), (void*)(p->Result + offset),
count); count);
MatrixParallelFactory.Release(p);
} }
internal static unsafe void BufferComputeUnaryScalar(MatrixParallelTaskPackageNonGeneric* p) internal static unsafe void BufferComputeUnaryScalar(MatrixParallelTaskPackage* p)
{ {
int size = p->ElementSize * 16; int size = p->ElementSize * 16;
int count = p->PrimCount * p->SecCount; long count = Unsafe.As<int, long>(ref p->PrimCount);
int offset = p->LeftPrimOffset * p->SecCount; long offset = Unsafe.As<int, long>(ref p->PrimTileOffset) * size;
((delegate* unmanaged[Cdecl]<void*, void*, int, void>)p->ComputeHandle)((void*)(p->Right + offset * size), ((delegate* unmanaged[Cdecl]<void*, void*, long, void>)p->ComputeHandle)((void*)(p->Right + offset),
(void*)(p->Result + offset * size), (void*)(p->Result + offset),
count); count);
MatrixParallelFactory.Release(p);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void Compute_Binary(MatrixParallelTaskPackageNonGeneric* p) internal static unsafe void Compute_Binary(MatrixParallelTaskPackage* p)
{ {
int eSize = p->ElementSize; int eSize = p->ElementSize;
@@ -106,10 +108,11 @@ namespace StgSharp.Mathematics.Numeric
op(left + (nint)lc, right + (nint)rc, ans + (nint)ac); op(left + (nint)lc, right + (nint)rc, ans + (nint)ac);
} }
} }
MatrixParallelFactory.Release(p);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void Compute_BinaryScalar(MatrixParallelTaskPackageNonGeneric* p) internal static unsafe void Compute_BinaryScalar(MatrixParallelTaskPackage* p)
{ {
int eSize = p->ElementSize; int eSize = p->ElementSize;
@@ -157,10 +160,11 @@ namespace StgSharp.Mathematics.Numeric
op(left + (nint)lc, right + (nint)rc, ans + (nint)ac, p->Scalar); op(left + (nint)lc, right + (nint)rc, ans + (nint)ac, p->Scalar);
} }
} }
MatrixParallelFactory.Release(p);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void Compute_Unary(MatrixParallelTaskPackageNonGeneric* p) internal static unsafe void Compute_Unary(MatrixParallelTaskPackage* p)
{ {
int eSize = p->ElementSize; int eSize = p->ElementSize;
@@ -201,10 +205,11 @@ namespace StgSharp.Mathematics.Numeric
op(right + (nint)rc, ans + (nint)ac); op(right + (nint)rc, ans + (nint)ac);
} }
} }
MatrixParallelFactory.Release(p);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void Compute_UnaryScalar(MatrixParallelTaskPackageNonGeneric* p) internal static unsafe void Compute_UnaryScalar(MatrixParallelTaskPackage* p)
{ {
int eSize = p->ElementSize; int eSize = p->ElementSize;
@@ -245,6 +250,7 @@ namespace StgSharp.Mathematics.Numeric
op(right + (nint)rc, ans + (nint)ac, p->Scalar); op(right + (nint)rc, ans + (nint)ac, p->Scalar);
} }
} }
MatrixParallelFactory.Release(p);
} }
} }
@@ -41,12 +41,14 @@ namespace StgSharp.Mathematics.Numeric
public static partial class MatrixParallel public static partial class MatrixParallel
{ {
private const int MIN_TASK_PER_THREAD = 256;
private const int REC_TASK_PER_THREAD = 1024;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe MatrixParallelHandle ScheduleTask<T>(MatrixParallelTaskPackage<T>* package) internal static unsafe MatrixParallelHandle ScheduleTask(MatrixParallelTaskPackage* package)
where T : unmanaged,INumber<T>
{ {
MatrixParallelTaskPackageNonGeneric* nonGeneric = (MatrixParallelTaskPackageNonGeneric*)package; MatrixParallelTaskPackage* nonGeneric = package;
switch (nonGeneric->ComputeMode.OperationStyle) switch (nonGeneric->ComputeMode.OperationStyle)
{ {
case MatrixOperationStyle.PANEL_OP: case MatrixOperationStyle.PANEL_OP:
@@ -60,12 +62,46 @@ namespace StgSharp.Mathematics.Numeric
} }
} }
private static unsafe MatrixParallelHandle ScheduleBufferTask(MatrixParallelTaskPackageNonGeneric* package) private static unsafe MatrixParallelHandle ScheduleBufferTask(MatrixParallelTaskPackage* package)
{ {
throw new NotImplementedException(); int primCount = package->PrimCount;
int secCount = package->SecCount;
long count = (long)primCount * secCount;
long recommendCount = count / 1024;
MatrixParallelThread[] pool = LeadParallel((int)recommendCount);
MatrixParallelHandle handle = new MatrixParallelHandle(pool);
if (handle.Wraps.Count() == 1)
{
ref long offsetRef = ref Unsafe.As<int, long>(ref package->PrimTileOffset);
offsetRef = 0;
ref long lengthRef = ref Unsafe.As<int, long>(ref package->PrimCount);
lengthRef = count;
handle.Wraps.First().WrapTask.Enqueue((nint)package);
return handle;
}
long actual = count / pool.Length;
long extra = count % pool.Length;
long offset = 0;
MatrixParallelTaskPackage* current = package;
foreach (MatrixParallelWrap wrap in handle.Wraps)
{
long wrapTaskLength = actual * wrap.WrapTaskCapacity;
long ex = Math.Min(extra, wrap.WrapTaskCapacity);
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 = wrapTaskLength + ex;
wrap.WrapTask.Enqueue((nint) current);
current = MatrixParallelFactory.FromExistPackage(current);
offset += wrapTaskLength;
}
return handle;
} }
private static unsafe MatrixParallelHandle ScheduleKernelTask(MatrixParallelTaskPackageNonGeneric* package) private static unsafe MatrixParallelHandle ScheduleKernelTask(MatrixParallelTaskPackage* package)
{ {
int primCount = package->PrimCount; int primCount = package->PrimCount;
int secCount = package->SecCount; int secCount = package->SecCount;
@@ -73,17 +109,17 @@ namespace StgSharp.Mathematics.Numeric
int tileCount = (primCount + tileWidth - 1) / tileWidth; int tileCount = (primCount + tileWidth - 1) / tileWidth;
MatrixParallelThread[] pool = LeadParallel(tileCount); MatrixParallelThread[] pool = LeadParallel(tileCount);
/*
if (pool.Length == 0) if (pool.Length == 0)
{ {
/* // no need
* wait until has enough threads // LeadParallel has contained capacity check
*/
} }
/**/
MatrixParallelHandle handle = new MatrixParallelHandle(pool); MatrixParallelHandle handle = new MatrixParallelHandle(pool);
if (handle.Wraps.Count() == 1) if (handle.Wraps.Count() == 1)
{ {
handle.Wraps.First().WrapTask = package; handle.Wraps.First().WrapTask.Enqueue((nint)package);
return handle; return handle;
} }
int threadCount = pool.Length; int threadCount = pool.Length;
@@ -94,7 +130,7 @@ namespace StgSharp.Mathematics.Numeric
int total = primCount; int total = primCount;
Stack<MatrixParallelWrap> taskBunch = new Stack<MatrixParallelWrap>(threadCount); Stack<MatrixParallelWrap> taskBunch = new Stack<MatrixParallelWrap>(threadCount);
MatrixParallelTaskPackageNonGeneric* current = package; MatrixParallelTaskPackage* current = package;
foreach (MatrixParallelWrap wrap in handle.Wraps) foreach (MatrixParallelWrap wrap in handle.Wraps)
{ {
bool hasSlice = columnAfterBaseTile > 0; bool hasSlice = columnAfterBaseTile > 0;
@@ -127,7 +163,7 @@ namespace StgSharp.Mathematics.Numeric
total -= columnInWrap; total -= columnInWrap;
// set to wrap and push // set to wrap and push
wrap.WrapTask = current; wrap.WrapTask.Enqueue((nint)current);
if (total <= 0) if (total <= 0)
{ {
@@ -71,7 +71,7 @@ namespace StgSharp.Mathematics.Numeric
RemainThreadCount = _threads.Count; RemainThreadCount = _threads.Count;
_AfterWork = (ThreadPriority)afterWork; _AfterWork = (ThreadPriority)afterWork;
foreach (MatrixParallelWrap w in handle.Wraps) { foreach (MatrixParallelWrap w in handle.Wraps) {
w.SchedulerReset.Set(); w.SetScheduler();
} }
} }
@@ -1,9 +1,9 @@
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// file="MatrixParallelPool" // file="MatrixParallelHandle"
// Project: StgSharp // Project: StgSharp
// AuthorGroup: Nitload Space // AuthorGroup: Nitload
// Copyright (c) Nitload Space. All rights reserved. // Copyright (c) Nitload. All rights reserved.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
@@ -39,7 +39,8 @@ namespace StgSharp.Mathematics.Numeric
public struct MatrixParallelHandle : IDisposable public struct MatrixParallelHandle : IDisposable
{ {
private static readonly (int a, int b)[] LookupTable = [ (1, 1), // 7 private static readonly (int a, int b)[] LookupTable = [
(1, 1), // 7
(0, 2), // 8 (no non-zero solution) (0, 2), // 8 (no non-zero solution)
(3, 0), // 9 (no non-zero solution) (3, 0), // 9 (no non-zero solution)
(2, 1), // 10 (2, 1), // 10
@@ -157,6 +158,7 @@ namespace StgSharp.Mathematics.Numeric
{ {
MatrixParallelWrap wrap = new MatrixParallelWrap(_threads, 0, count); MatrixParallelWrap wrap = new MatrixParallelWrap(_threads, 0, count);
_wraps = [ wrap ]; _wraps = [ wrap ];
return;
} }
(int c3,int c4) = FastDecompose(_threads.Length); (int c3,int c4) = FastDecompose(_threads.Length);
_wraps = new(c3 + c4); _wraps = new(c3 + c4);
@@ -82,16 +82,13 @@ namespace StgSharp.Mathematics.Numeric
} }
[StructLayout(LayoutKind.Explicit, Size = 128)] [StructLayout(LayoutKind.Explicit, Size = 128)]
internal unsafe struct MatrixParallelTaskPackageNonGeneric public unsafe struct MatrixParallelTaskPackage
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void Copy( public static unsafe void Copy(MatrixParallelTaskPackage* source, MatrixParallelTaskPackage* target)
MatrixParallelTaskPackageNonGeneric* source,
MatrixParallelTaskPackageNonGeneric* target)
{ {
Buffer.MemoryCopy(source, target, sizeof(MatrixParallelTaskPackageNonGeneric), Buffer.MemoryCopy(source, target, sizeof(MatrixParallelTaskPackage), sizeof(MatrixParallelTaskPackage));
sizeof(MatrixParallelTaskPackageNonGeneric));
} }
#region source #region source
@@ -113,7 +110,7 @@ namespace StgSharp.Mathematics.Numeric
#region left enum #region left enum
[FieldOffset(32)] public int LeftPrimOffset; // 4 [FieldOffset(32)]public int LeftPrimOffset; // 4
[FieldOffset(36)]public int LeftPrimStride; // 4 [FieldOffset(36)]public int LeftPrimStride; // 4
[FieldOffset(40)]public int LeftSecOffset; // 4 [FieldOffset(40)]public int LeftSecOffset; // 4
[FieldOffset(44)]public int LeftSecStride; // 4 [FieldOffset(44)]public int LeftSecStride; // 4
@@ -122,7 +119,7 @@ namespace StgSharp.Mathematics.Numeric
#region right enum #region right enum
[FieldOffset(32)] public int RightPrimOffset; // 4 [FieldOffset(32)]public int RightPrimOffset; // 4
[FieldOffset(36)]public int RightPrimStride; // 4 [FieldOffset(36)]public int RightPrimStride; // 4
[FieldOffset(40)]public int RightSecOffset; // 4 [FieldOffset(40)]public int RightSecOffset; // 4
[FieldOffset(44)]public int RightSecStride; // 4 [FieldOffset(44)]public int RightSecStride; // 4
@@ -147,9 +144,9 @@ namespace StgSharp.Mathematics.Numeric
#region global profile #region global profile
[FieldOffset(96)]public int PrimCount; // 4 [FieldOffset(96)]public int PrimCount; // 4
[FieldOffset(100)]public MatrixOpMode ComputeMode; // 4 [FieldOffset(100)]public int SecCount; // 4
[FieldOffset(104)]public int SecCount; // 4 [FieldOffset(104)]public MatrixOpMode ComputeMode; // 4
[FieldOffset(108)]private int ReservedInt0; // 4 [FieldOffset(108)]private int ReservedInt0; // 4
#endregion #endregion
@@ -163,90 +160,4 @@ namespace StgSharp.Mathematics.Numeric
#endregion #endregion
} }
[StructLayout(LayoutKind.Explicit, Size =128)]
internal unsafe struct MatrixParallelTaskPackage<T> where T : unmanaged, INumber<T>
{
public MatrixParallelTaskPackage()
{
Unsafe.SkipInit(out this);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void Copy(MatrixParallelTaskPackage<T>* source, MatrixParallelTaskPackage<T>* target)
{
Buffer.MemoryCopy(source, target, sizeof(MatrixParallelTaskPackage<T>),
sizeof(MatrixParallelTaskPackage<T>));
}
#region source
// Group 1: Left/Right matrix kernel base address
[FieldOffset(0)]public MatrixKernel<T>* Left; // 8
[FieldOffset(8)] public MatrixKernel<T>* Right; // 8
#endregion
#region ans
// Group 2: Result kernel base address + reserved
[FieldOffset(16)] public MatrixKernel<T>* Result; // 8
[FieldOffset(24)] public int ElementSize = sizeof(T);
[FieldOffset(28)] public int ReservedPtr0; // 4 (extension/reserved)
#endregion
#region left enum
[FieldOffset(32)]public int LeftPrimOffset; // 4
[FieldOffset(36)]public int LeftPrimStride; // 4
[FieldOffset(40)]public int LeftSecOffset; // 4
[FieldOffset(44)] public int LeftSecStride; // 4
#endregion
#region right enum
[FieldOffset(48)]public int RightPrimOffset; // 4
[FieldOffset(52)]public int RightPrimStride; // 4
[FieldOffset(56)]public int RightSecOffset; // 4
[FieldOffset(60)]public int RightSecStride; // 4
#endregion
#region ans enum
[FieldOffset(64)]public int ResultPrimOffset; // 4
[FieldOffset(68)]public int ResultPrimStride; // 4
[FieldOffset(72)]public int ResultSecOffset; // 4
[FieldOffset(76)] public int ResultSecStride; // 4
#endregion
#region scalar/compute
[FieldOffset(80)] public ScalarPacket* Scalar; // 8
[FieldOffset(88)]public IntPtr ComputeHandle; // 8
#endregion
#region global profile
[FieldOffset(96)] public int PrimCount; // 4
[FieldOffset(100)]public MatrixOpMode ComputeMode; // 4
[FieldOffset(104)]public int SecCount; // 4
[FieldOffset(108)] private readonly int ReservedInt0; // 4
#endregion
#region count offset
[FieldOffset(112)]public int PrimTileOffset; // 4
[FieldOffset(116)]public int SecTileOffset; // 4
[FieldOffset(120)]public int PrimColumnCountInTile; // 4
[FieldOffset(124)]public int SecColumnCountInTile; // 4
#endregion
}
} }
@@ -27,6 +27,7 @@
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@@ -53,6 +54,7 @@ namespace StgSharp.Mathematics.Numeric
_affinity = AffinityAllocator.Allocate(); _affinity = AffinityAllocator.Allocate();
_managedThread = new Thread(MatrixParallelWorker); _managedThread = new Thread(MatrixParallelWorker);
_managedThread.Start();
_resetEvent = new ManualResetEventSlim(false); _resetEvent = new ManualResetEventSlim(false);
} }
@@ -78,7 +80,7 @@ namespace StgSharp.Mathematics.Numeric
{ {
while (taskQueue.TryDequeue(out nint handle)) while (taskQueue.TryDequeue(out nint handle))
{ {
MatrixParallelTaskPackageNonGeneric* p = (MatrixParallelTaskPackageNonGeneric*)handle; MatrixParallelTaskPackage* p = (MatrixParallelTaskPackage*)handle;
switch (p->ComputeMode.OperationStyle) switch (p->ComputeMode.OperationStyle)
{ {
case MatrixOperationStyle.PANEL_OP: case MatrixOperationStyle.PANEL_OP:
@@ -127,16 +129,12 @@ namespace StgSharp.Mathematics.Numeric
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Restart() public void Restart()
{ {
_resetEvent.Set(); _resetEvent.Set();
} }
public void ReturnToPool()
{
// MatrixParallel.(this);
}
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
if (!disposedValue) if (!disposedValue)
@@ -159,27 +157,30 @@ namespace StgSharp.Mathematics.Numeric
// Bind OS-thread affinity once when the worker starts running // Bind OS-thread affinity once when the worker starts running
ApplyAffinityIfNeeded(); ApplyAffinityIfNeeded();
// Thread self = Thread.CurrentThread; while (true)
_resetEvent.Wait();
_resetEvent.Reset();
_managedThread.Priority = ThreadPriority.Highest;
switch (Role)
{ {
case 0://worker // Thread self = Thread.CurrentThread;
// _ = Interlocked.Decrement(ref RemainThreadCount); _managedThread.Priority = ThreadPriority.Highest;
ExecuteTaskPackage(Tasks); _resetEvent.Wait();
break; _resetEvent.Reset();
case 1://scheduler switch (Role)
BindedWrap.PublishTaskToWorkers(Tasks); {
BindedWrap.SetAllWorker(); case 0://worker
ExecuteTaskPackage(Tasks); // _ = Interlocked.Decrement(ref RemainThreadCount);
break; ExecuteTaskPackage(Tasks);
case 2://leader, error because leader should be at outer thread but not here break;
break; case 1://scheduler
default: BindedWrap.PublishTaskToWorkers(BindedWrap.WrapTask);
break; BindedWrap.SetAllWorker();
ExecuteTaskPackage(Tasks);
break;
case 2://leader, error because leader should be at outer thread but not here
break;
default:
break;
}
_managedThread.Priority = AfterWork;
} }
_managedThread.Priority = AfterWork;
} }
#region core affinity #region core affinity
@@ -44,10 +44,13 @@ namespace StgSharp.Mathematics.Numeric
internal MatrixParallelWrap(MatrixParallelThread[] threads, int begin, int count) internal MatrixParallelWrap(MatrixParallelThread[] threads, int begin, int count)
{ {
WrapTaskCapacity = count;
_threads = threads; _threads = threads;
_begin = begin; _begin = begin;
Count = threads.Length;
_threads[_begin].Role = 1; _threads[_begin].Role = 1;
for (int i = _begin; i < _begin + WrapTaskCapacity; i++) {
_threads[i].BindedWrap = this;
}
} }
public MatrixParallelWrap() public MatrixParallelWrap()
@@ -63,15 +66,11 @@ namespace StgSharp.Mathematics.Numeric
internal int Magic { get; set; } internal int Magic { get; set; }
internal ManualResetEventSlim SchedulerReset { get; } = new(false);
private int Count { get; set; }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetAllWorker() public void SetAllWorker()
{ {
foreach (MatrixParallelThread t in _threads) { for (int i = _begin; i < _begin + WrapTaskCapacity; i++) {
t.Restart(); _threads[i].Restart();
} }
} }
@@ -79,25 +78,124 @@ namespace StgSharp.Mathematics.Numeric
{ {
while (tasks.TryDequeue(out nint handle)) while (tasks.TryDequeue(out nint handle))
{ {
MatrixParallelTaskPackageNonGeneric* task = (MatrixParallelTaskPackageNonGeneric*)handle; MatrixParallelTaskPackage* task = (MatrixParallelTaskPackage*)handle;
PublishTaskToWorkers(task); switch (task->ComputeMode.OperationStyle)
{
case MatrixOperationStyle.PANEL_OP:
break;
case MatrixOperationStyle.BUFFER_OP:
PublishBufferTaskToWorkers(task);
break;
case MatrixOperationStyle.KERNEL_OP:
PublishBufferTaskToWorkers(task);
break;
default:
break;
}
} }
} }
internal void PublishTaskToWorkers(MatrixParallelTaskPackageNonGeneric* taskPackage) internal void SetScheduler()
{ {
int primCount = taskPackage->PrimCount; MatrixParallelThread thread = _threads[_begin];
int secCount = taskPackage->SecCount; thread.Restart();
}
int primAverage = primCount / Count; private void PublishBufferTaskToWorkers(MatrixParallelTaskPackage* package)
int secAverage = secCount / Count; {
bool shouldSliceSec = secAverage > 512; long count = Unsafe.As<int, long>(ref package->PrimCount);
for (int i = _begin; i < _begin + Count; i++) long recommendCount = count / 1024;
MatrixParallelThread[] pool = _threads;
if (pool.Length == 1)
{ {
Queue<IntPtr> tasks = _threads[i].Tasks; pool[0].Tasks.Enqueue((nint)package);
MatrixParallelTaskPackageNonGeneric* subTask = MatrixParallelFactory.FromExistPackage(taskPackage); return;
subTask->PrimTileOffset = i * primAverage;
} }
long actual = count / pool.Length;
long extra = count % pool.Length;
long offset = 0;
MatrixParallelTaskPackage* current = package;
foreach (MatrixParallelThread thread in pool)
{
long wrapTaskLength = actual;
long ex = extra > 0 ? 1 : 0;
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 = wrapTaskLength + ex;
pool[0].Tasks.Enqueue((nint)current);
current = MatrixParallelFactory.FromExistPackage(current);
offset += wrapTaskLength;
}
}
private void PublishKernelTaskToWorkers(MatrixParallelTaskPackage* package)
{
int primCount = package->PrimCount;
int secCount = package->SecCount;
MatrixParallelThread[] pool = _threads;
if (pool.Length == 1)
{
pool[0].Tasks.Enqueue((nint)package);
return;
}
throw new NotImplementedException();
/*
int threadCount = pool.Length;
int tilePerThreadLess = tileCount / threadCount; // tiles per thread without extra slice
int columnAfterBaseTile = tileCount % threadCount * tileWidth; // tile sliced into columns
int extraColumnPerThread = columnAfterBaseTile / threadCount;
int extraColumnCount = columnAfterBaseTile % threadCount; // columns to be sliced
int total = primCount;
Stack<MatrixParallelWrap> taskBunch = new Stack<MatrixParallelWrap>(threadCount);
MatrixParallelTaskPackageNonGeneric* current = package;
foreach (MatrixParallelWrap wrap in pool.Wraps)
{
bool hasSlice = columnAfterBaseTile > 0;
bool isLargeSlice = extraColumnCount > 0;
// _count tiles for wrap
int wrapWidth = wrap!.WrapTaskCapacity;
int columnFromSlicingCount = (hasSlice ? extraColumnPerThread : 0) * wrapWidth;
int baseColumn = wrapWidth * tilePerThreadLess * tileWidth;
int columnInWrap = baseColumn + columnFromSlicingCount + (isLargeSlice ? 1 : 0);
// set tasks
if (columnInWrap == 0)
{
#if DEBUG
throw new InvalidOperationException("Zero tasks published.");
#else
break;
#endif
}
// update current task
current->PrimColumnCountInTile = columnInWrap;
current->SecColumnCountInTile = current->SecCount;
current->SecTileOffset = 0;
// remove tiles _count
extraColumnCount--;
columnAfterBaseTile -= columnFromSlicingCount;
total -= columnInWrap;
// set to wrap and push
wrap.WrapTask = current;
if (total <= 0)
{
break;
}
current = MatrixParallelFactory.FromExistPackage(current);
current->PrimTileOffset += columnInWrap;
}
/**/
return;
} }
public class Handle(int inWrapIndex, MatrixParallelWrap wrap) public class Handle(int inWrapIndex, MatrixParallelWrap wrap)
@@ -121,15 +219,11 @@ namespace StgSharp.Mathematics.Numeric
#region wrap task #region wrap task
internal MatrixParallelTaskPackageNonGeneric* WrapTask { get; set; } internal unsafe Queue<nint> WrapTask { get; set; } = [];
internal int WrapTaskSliceCount { get; set; } internal int WrapTaskSliceCount { get; set; }
internal int WrapTaskCapacity internal int WrapTaskCapacity { get ; init; }
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _threads.Length;
}
#endregion #endregion
} }
@@ -55,13 +55,13 @@ namespace StgSharp.Mathematics.Numeric
private static SlabAllocator<ScalarPacket> _scalarAllocator ; private static SlabAllocator<ScalarPacket> _scalarAllocator ;
private static SlabAllocator<MatrixParallelTaskPackageNonGeneric> _wrapAllocator; private static SlabAllocator<MatrixParallelTaskPackage> _wrapAllocator;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static MatrixParallelTaskPackage<T>* CreateBaseTask<T>() where T: unmanaged, INumber<T> public static MatrixParallelTaskPackage* CreateBaseTask<T>() where T : unmanaged, INumber<T>
{ {
MatrixParallelTaskPackage<T>* p = (MatrixParallelTaskPackage<T>*)_wrapAllocator.Allocate(); MatrixParallelTaskPackage* p = (MatrixParallelTaskPackage*)_wrapAllocator.Allocate();
Span<byte> s = new Span<byte>((byte*)p, sizeof(MatrixParallelTaskPackage<T>)); Span<byte> s = new Span<byte>((byte*)p, sizeof(MatrixParallelTaskPackage));
s.Fill(0); s.Fill(0);
return p; return p;
} }
@@ -74,20 +74,19 @@ namespace StgSharp.Mathematics.Numeric
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe MatrixParallelTaskPackage<T>* FromExistPackage<T>(MatrixParallelTaskPackage<T>* exist) public static unsafe MatrixParallelTaskPackage* FromExistPackage<T>(MatrixParallelTaskPackage* exist)
where T: unmanaged, INumber<T> where T : unmanaged, INumber<T>
{ {
MatrixParallelTaskPackage<T>* ptr = (MatrixParallelTaskPackage<T>*)_wrapAllocator.Allocate(); MatrixParallelTaskPackage* ptr = (MatrixParallelTaskPackage*)_wrapAllocator.Allocate();
MatrixParallelTaskPackage<T>.Copy(exist, ptr); MatrixParallelTaskPackage.Copy(exist, ptr);
return ptr; return ptr;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe MatrixParallelTaskPackageNonGeneric* FromExistPackage( public static unsafe MatrixParallelTaskPackage* FromExistPackage(MatrixParallelTaskPackage* exist)
MatrixParallelTaskPackageNonGeneric* exist)
{ {
MatrixParallelTaskPackageNonGeneric* ptr = (MatrixParallelTaskPackageNonGeneric*)_wrapAllocator.Allocate(); MatrixParallelTaskPackage* ptr = (MatrixParallelTaskPackage*)_wrapAllocator.Allocate();
MatrixParallelTaskPackageNonGeneric.Copy(exist, ptr); MatrixParallelTaskPackage.Copy(exist, ptr);
return ptr; return ptr;
} }
@@ -99,7 +98,7 @@ namespace StgSharp.Mathematics.Numeric
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Release(MatrixParallelTaskPackageNonGeneric* source) public static void Release(MatrixParallelTaskPackage* source)
{ {
if (source->Scalar != null) { if (source->Scalar != null) {
_scalarAllocator.Free((nuint)source->Scalar); _scalarAllocator.Free((nuint)source->Scalar);
@@ -108,7 +107,7 @@ namespace StgSharp.Mathematics.Numeric
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Release<T>(MatrixParallelTaskPackage<T>* source) where T: unmanaged, INumber<T> public static void Release<T>(MatrixParallelTaskPackage* source) where T : unmanaged, INumber<T>
{ {
if (source->Scalar != null) { if (source->Scalar != null) {
_scalarAllocator.Free((nuint)source->Scalar); _scalarAllocator.Free((nuint)source->Scalar);
@@ -123,7 +122,7 @@ namespace StgSharp.Mathematics.Numeric
{ {
_intermediateResult = new hlsfAllocator(64 * 16 * 16); _intermediateResult = new hlsfAllocator(64 * 16 * 16);
_scalarAllocator = SlabAllocator<ScalarPacket>.Create(64 * 1024, SlabBufferLayout.Chunked); _scalarAllocator = SlabAllocator<ScalarPacket>.Create(64 * 1024, SlabBufferLayout.Chunked);
_wrapAllocator = SlabAllocator<MatrixParallelTaskPackageNonGeneric>. _wrapAllocator = SlabAllocator<MatrixParallelTaskPackage>.
Create(128 * 1024, SlabBufferLayout.Chunked); Create(128 * 1024, SlabBufferLayout.Chunked);
} }
} }
+4 -116
View File
@@ -62,133 +62,20 @@ namespace StgSharp
try try
{ {
World.Initialize().UseModule<NumericalModule>().UseModule<GraphicModule>().InitializeModule(); World.Initialize().UseModule<NumericalModule>().UseModule<GraphicModule>().InitializeModule();
TestRender();
/*
// New test with synchronized start:
// - 8 producer threads, each pushing 1000 unique integers
// - 8 consumer threads, each attempting to pop 1000 times
// - Consumers print one line per successful pop
// - Finally, print popped/remaining counts and values
const int producerThreads = 8; // TestRender();
const int consumerThreads = 8;
const int perProducer = 1000;
const int perConsumerAttempts = 1000;
ConcurrentBufferStack<int> stack = new ConcurrentBufferStack<int>();
Thread[] producers = new Thread[producerThreads];
Thread[] consumers = new Thread[consumerThreads];
ConcurrentBag<int> popped = new ConcurrentBag<int>();
int totalThreads = producerThreads + consumerThreads;
using CountdownEvent ready = new CountdownEvent(totalThreads);
using ManualResetEventSlim startGate = new ManualResetEventSlim(false);
for (int c = 0; c < consumerThreads; c++)
{
consumers[c] = new Thread(() => {
ready.Signal();
startGate.Wait();
for (int k = 0; k < perConsumerAttempts; k++)
{
if (stack.TryPop(out int v))
{
popped.Add(v);
// Console.WriteLine($"pop: {v}");
} else
{
Thread.Yield();
}
}
})
{
IsBackground = true
};
}
for (int p = 0; p < producerThreads; p++)
{
int captured = p;
producers[p] = new Thread(() => {
ready.Signal();
startGate.Wait();
int begin = captured * perProducer + 10 * perProducer;
for (int j = 0; j < perProducer; j++)
{
stack.Push(begin + j);
if ((j & 0xFF) == 0) {
Thread.Yield();
}
}
})
{
IsBackground = true
};
}
foreach (Thread t in consumers) {
t.Start();
}
foreach (Thread t in producers) {
t.Start();
}
// Ensure all threads are ready, then start simultaneously
ready.Wait();
startGate.Set();
foreach (Thread t in producers) {
t.Join();
}
foreach (Thread t in consumers) {
t.Join();
}
// Gather remaining data
List<int> remaining = [];
while (stack.TryPop(out int value)) {
remaining.Add(value);
}
Console.WriteLine($"Popped count: {popped.Count}");
/*
Console.WriteLine("Popped values:");
foreach (int v in popped)
{
Console.Write(v);
Console.Write('\t');
}
Console.WriteLine();
/*
Console.WriteLine($"Remaining count: {remaining.Count}");
Console.WriteLine("Remaining values:");
foreach (int v in remaining)
{
Console.Write(v);
Console.Write('\t');
}
Console.WriteLine();
// Sanity check
Console.WriteLine($"Produced: {producerThreads * perProducer}, Popped+Remaining: {popped.Count + remaining.Count}");
/*
// 原有的矩阵测试代码 // 原有的矩阵测试代码
HybridLayerSegregatedFitAllocator hlsf = new HybridLayerSegregatedFitAllocator(64 * 400 * 400); HybridLayerSegregatedFitAllocator hlsf = new HybridLayerSegregatedFitAllocator(64 * 400 * 400);
Matrix<float> m = Matrix<float>.FromHlsf(20, 20, hlsf); Matrix<float> m = Matrix<float>.FromHlsf(200, 200, hlsf);
m.Fill(1.0f); m.Fill(1.0f);
Matrix<float> n = m.Add(m); Matrix<float> n = m.Add(m);
for (int i = 0; i < 20; i++) for (int i = 0; i < 20; i++)
{ {
for (int j = 0; j < 20; j++) { for (int j = 0; j < 20; j++) {
Console.Write($"{n[i, j].ToString("0.000")}\t"); Console.Write($"{n[i, j]:0.0E+00} \t");
} }
Console.WriteLine(); Console.WriteLine();
} }
@@ -198,6 +85,7 @@ namespace StgSharp
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine(ex); Console.WriteLine(ex);
Console.ReadLine();
/* /*
World.WriteLog($"{ex}", LogType.Error); World.WriteLog($"{ex}", LogType.Error);
if( true ) { } if( true ) { }