add scheduler method; fixing buffer parallel errors
This commit is contained in:
@@ -70,9 +70,11 @@ namespace StgSharp.Mathematics.Numeric
|
||||
{
|
||||
RemainThreadCount = _threads.Count;
|
||||
_AfterWork = (ThreadPriority)afterWork;
|
||||
MatrixParallelThread leader = handle.GetLeader();
|
||||
foreach (MatrixParallelWrap w in handle.Wraps) {
|
||||
w.SetScheduler();
|
||||
}
|
||||
leader.MatrixParallelLeader();
|
||||
}
|
||||
|
||||
internal static void Init()
|
||||
|
||||
@@ -97,6 +97,13 @@ namespace StgSharp.Mathematics.Numeric
|
||||
|
||||
private bool IsMultithread { get; init; }
|
||||
|
||||
public MatrixParallelThread DefineLeader()
|
||||
{
|
||||
MatrixParallelThread leader = _threads[1];
|
||||
leader.Role = 2;
|
||||
return leader;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) {
|
||||
|
||||
@@ -37,7 +37,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Mathematics.Numeric
|
||||
{
|
||||
public class MatrixParallelThread : IDisposable
|
||||
public partial class MatrixParallelThread : IDisposable
|
||||
{
|
||||
|
||||
// Affinity binding info for this thread
|
||||
@@ -58,6 +58,9 @@ namespace StgSharp.Mathematics.Numeric
|
||||
_resetEvent = new ManualResetEventSlim(false);
|
||||
}
|
||||
|
||||
// Global runtime switch: true => UMA/no-affinity; false => NUMA/affinity (auto-detected)
|
||||
public static bool UseUmaAffinityPath { get; } = DetectUmaAffinityPath();
|
||||
|
||||
// ~MatrixComputeThread()
|
||||
// {
|
||||
// Dispose(disposing: false);
|
||||
@@ -135,6 +138,36 @@ namespace StgSharp.Mathematics.Numeric
|
||||
_resetEvent.Set();
|
||||
}
|
||||
|
||||
internal void MatrixParallelLeader()
|
||||
{
|
||||
Thread current = Thread.CurrentThread;
|
||||
current.Priority = ThreadPriority.Highest;
|
||||
Thread.Sleep(0);
|
||||
|
||||
#if WINDOWS
|
||||
if (!UseUmaAffinityPath)
|
||||
{
|
||||
// NUMA/affinity path: bind to this thread's reserved mask, then restore
|
||||
nuint previousMask = SetThreadAffinityMask(GetCurrentThread(), _affinity.Mask);
|
||||
bool affinityChanged = previousMask != 0; // nonzero => success
|
||||
ExecuteTaskPackage(Tasks);
|
||||
if (affinityChanged) {
|
||||
_ = SetThreadAffinityMask(GetCurrentThread(), previousMask);
|
||||
}
|
||||
} else
|
||||
{
|
||||
// UMA path: no affinity binding
|
||||
ExecuteTaskPackage(Tasks);
|
||||
}
|
||||
#else
|
||||
// Non-Windows: no affinity control
|
||||
ExecuteTaskPackage(Tasks);
|
||||
#endif
|
||||
|
||||
this.Role = 1;
|
||||
current.Priority = ThreadPriority.Normal;
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
@@ -152,6 +185,36 @@ namespace StgSharp.Mathematics.Numeric
|
||||
}
|
||||
}
|
||||
|
||||
private static bool DetectUmaAffinityPath()
|
||||
{
|
||||
#if WINDOWS
|
||||
try
|
||||
{
|
||||
// Quick heuristic: single CPU looks like UMA
|
||||
if (Environment.ProcessorCount <= 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Query NUMA topology: highest node number 0 => single node => UMA
|
||||
uint highest = 0;
|
||||
if (GetNumaHighestNodeNumber(out highest)) {
|
||||
return highest == 0;
|
||||
}
|
||||
|
||||
// If query fails, prefer UMA (safer: no affinity changes)
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
// Non-Windows: treat as UMA (no affinity API available)
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
private unsafe void MatrixParallelWorker()
|
||||
{
|
||||
// Bind OS-thread affinity once when the worker starts running
|
||||
@@ -312,6 +375,10 @@ namespace StgSharp.Mathematics.Numeric
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern nuint SetThreadAffinityMask(IntPtr hThread, nuint dwThreadAffinityMask);
|
||||
|
||||
[LibraryImport("kernel32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool GetNumaHighestNodeNumber(out uint HighestNodeNumber);
|
||||
|
||||
#elif LINUX
|
||||
|
||||
#endif
|
||||
|
||||
@@ -69,8 +69,11 @@ namespace StgSharp.Mathematics.Numeric
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetAllWorker()
|
||||
{
|
||||
for (int i = _begin; i < _begin + WrapTaskCapacity; i++) {
|
||||
_threads[i].Restart();
|
||||
for (int i = _begin; i < _begin + WrapTaskCapacity; i++)
|
||||
{
|
||||
if (_threads[i].Role != 3) {
|
||||
_threads[i].Restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user