diff --git a/StgSharp.Mathematics/Numeric/MatrixParallel.cs b/StgSharp.Mathematics/Numeric/MatrixParallel.cs index 0ca60967..7f33c363 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallel.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallel.cs @@ -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() diff --git a/StgSharp.Mathematics/Numeric/MatrixParallelHandle.cs b/StgSharp.Mathematics/Numeric/MatrixParallelHandle.cs index 17fb976a..f16124b2 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallelHandle.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallelHandle.cs @@ -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) { diff --git a/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs b/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs index 8a55f434..08490395 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs @@ -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 diff --git a/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs b/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs index fa6a42f4..a8237843 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs @@ -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(); + } } } diff --git a/StgSharpDebug/Program.cs b/StgSharpDebug/Program.cs index 85016753..c7663d88 100644 --- a/StgSharpDebug/Program.cs +++ b/StgSharpDebug/Program.cs @@ -86,10 +86,9 @@ namespace StgSharp { Console.WriteLine(ex); Console.ReadLine(); - /* + /**/ World.WriteLog($"{ex}", LogType.Error); - if( true ) { } - Dialogue.PostError( ex ); + Dialogue.PostError(ex); /**/ World.Terminate(-1); /**/