diff --git a/StgSharp.Common/Threading/ThreadHelper.cs b/StgSharp.Common/Threading/ThreadHelper.cs index 8dba6e9e..4b3f5bf9 100644 --- a/StgSharp.Common/Threading/ThreadHelper.cs +++ b/StgSharp.Common/Threading/ThreadHelper.cs @@ -74,9 +74,9 @@ namespace StgSharp.Threading [LibraryImport(Native.LibName, EntryPoint = "sn_set_thread_affinity")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)] - internal static partial void SetThreadAffinity( - uint globalCoreId, - uint numaNodeId + private static partial void SetThreadAffinity( + uint globalCoreId, + uint numaNodeId ); #pragma warning restore CA5393 diff --git a/StgSharp.Mathematics/Numeric/Linear/MatrixCompute.Sequential.cs b/StgSharp.Mathematics/Numeric/Linear/MatrixCompute.Sequential.cs index 4ad66cbb..9d4454cb 100644 --- a/StgSharp.Mathematics/Numeric/Linear/MatrixCompute.Sequential.cs +++ b/StgSharp.Mathematics/Numeric/Linear/MatrixCompute.Sequential.cs @@ -89,7 +89,7 @@ namespace StgSharp.Mathematics.Numeric.Linear MkProc op = (MkProc)NumericalModule.GlobalContext. mat_mk[elementType.IntrinsicNode]. Get(task->ComputeHandle); - if (count <= 256) + if ((count <= 256) || !MatrixParallel.IsParallelMeaningful) { op(task); return; @@ -101,43 +101,10 @@ namespace StgSharp.Mathematics.Numeric.Linear return; } pool = MatrixParallel.LeadParallel(count / 1024); - MatrixParallelWrap taskGroup = MatrixParallel.ScheduleTask(pool, task); + MatrixParallelWrap taskGroup = MatrixParallel.ScheduleTask(pool, task); taskGroup.LaunchParallel(SleepMode.DeepSleep); taskGroup.Dispose(); } - private struct SequentialPredictor : IMatrixPredictor - { - - public static PredictPolicy Policy => PredictPolicy.Sequential; - - public PredictResult Predict( - Span node, - out int count - ) - { - throw new NotImplementedException(); - } - - public void Prefetch( - nuint origin, - ulong policy, - Span cache - ) - { - throw new NotImplementedException(); - } - - public void WriteBack( - nuint origin, - ulong policy, - ReadOnlySpan cache - ) - { - throw new NotImplementedException(); - } - - } - } } diff --git a/StgSharp.Mathematics/Numeric/NumericalModule.cs b/StgSharp.Mathematics/Numeric/NumericalModule.cs index 3fd2adcc..a47d9970 100644 --- a/StgSharp.Mathematics/Numeric/NumericalModule.cs +++ b/StgSharp.Mathematics/Numeric/NumericalModule.cs @@ -76,7 +76,14 @@ namespace StgSharp.Mathematics.Numeric IModuleInitializeProfile profile ) { - MatrixParallel.Init(); + try + { + MatrixParallel.Init(); + } + finally + { + GC.Collect(); + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/StgSharp.Mathematics/Numeric/Runtime/MatrixEnumerator.cs b/StgSharp.Mathematics/Numeric/Runtime/MatrixEnumerator.cs index b03920f3..c711851f 100644 --- a/StgSharp.Mathematics/Numeric/Runtime/MatrixEnumerator.cs +++ b/StgSharp.Mathematics/Numeric/Runtime/MatrixEnumerator.cs @@ -1,30 +1,27 @@ //----------------------------------------------------------------------- // ----------------------------------------------------------------------- -// file="MatrixEnumerator.cs" +// file="MatrixEnumerator" // Project: StgSharp -// AuthorGroup: Nitload Space -// Copyright (c) Nitload Space. All rights reserved. +// AuthorGroup: Nitload +// Copyright (c) Nitload. All rights reserved. // -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and -// this permission notice shall be included in all copies -// or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED “AS IS”, -// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- @@ -47,38 +44,52 @@ namespace StgSharp.Mathematics.Numeric.Runtime } - public unsafe interface IMatrixCachePredictor : IL4Predict where T: unmanaged, INumber - where TSelf: class, IMatrixCachePredictor + public unsafe interface IMatrixCachePredictor : IL4Predict + where TSelf : class, IMatrixCachePredictor { public static abstract PredictPolicy Policy { get; set; } } - public sealed unsafe class BufferSequentialPredictor : IMatrixCachePredictor, T> - where T: unmanaged, INumber + public sealed unsafe class BufferSequentialPredictor : IMatrixCachePredictor { - private MatrixParallelTask* origin; + private readonly MatrixParallelTask* origin; + private readonly int _kernelSize; public static PredictPolicy Policy { get; set; } = PredictPolicy.SquareRowMajor; - public bool IsSamePolicy(uint policy, IL4Predict predict) + public bool IsSamePolicy( + uint policy, + IL4Predict predict + ) { throw new NotImplementedException(); } - public PredictResult Predict(Span node, out int count) + public PredictResult Predict( + Span node, + out int count + ) { throw new NotImplementedException(); } - public void Prefetch(nuint origin, uint policy, Span cache) + public void Prefetch( + nuint origin, + uint policy, + Span cache + ) { throw new NotImplementedException(); } - public void WriteBack(nuint origin, uint policy, ReadOnlySpan cache) + public void WriteBack( + nuint origin, + uint policy, + ReadOnlySpan cache + ) { throw new NotImplementedException(); } diff --git a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.Numa.cs b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.Numa.cs index 6384400c..57a1cd39 100644 --- a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.Numa.cs +++ b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.Numa.cs @@ -25,6 +25,7 @@ // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- +using StgSharp.HighPerformance.Memory; using System; using System.Collections.Generic; using System.Linq; @@ -36,13 +37,26 @@ namespace StgSharp.Mathematics.Numeric public static unsafe partial class MatrixParallel { + private static L4[] _numaBuffer; + private static NumaMeasurement[] _numaMeasurements; + private static int[] _numaPayload; private static MatrixParallelThread[][] _numaThreads; + private static MatrixParallelThread[] _threads; private static void UpdateThreadPayload() { for (int i = 0; i < _numaPayload.Length; i++) { } } + private struct NumaMeasurement + { + + public uint ActivePredictors; + public uint ActiveThreadCount; + public ulong ActiveTasks; + + } + } } diff --git a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.cs b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.cs index acaa3ca4..e758501a 100644 --- a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.cs +++ b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.cs @@ -43,8 +43,6 @@ namespace StgSharp.Mathematics.Numeric private static CapacityFixedStack _retiredThreads; - private static CapacityFixedStack _threads; - public static bool IsParallelSupported { get; } = Environment.ProcessorCount > 6; public static bool IsParallelMeaningful => IsParallelSupported && @@ -84,9 +82,9 @@ namespace StgSharp.Mathematics.Numeric contextMap = []; int count = Environment.ProcessorCount; SIMDID globalSimd = new SIMDID(0); - _threads = new(count); _retiredThreads = new(RESERVED_THREAD_COUNT); + // init thread on all logical cores _numaThreads = Numa.CreateForeachThread( core => { MatrixParallelThread thread = new(core); @@ -101,37 +99,97 @@ namespace StgSharp.Mathematics.Numeric return thread; }); + // make global simd context IntrinsicContext globalContext = new(); LoadIntrinsicFunction(&globalContext, globalSimd.Mask); NumericalModule.GlobalContext = globalContext; NumericalModule.GlobalIntrinsicMask = globalSimd; ContextCount = contextMap.Count; + + // retire threads if (ContextCount == 1) { - int retireCount = Math.Min(RESERVED_THREAD_COUNT, Math.Max(0, _threads.Count)); - for (int i = 0; i < retireCount; i++) { - RetireThread(_threads.Pop()); + MatrixParallelThread[] threadArr = _numaThreads[0]; + int retireCount = Math.Min(RESERVED_THREAD_COUNT, Math.Max(0, threadArr.Length)); + for (int i = 1; i <= retireCount; i++) { + RetireThread(threadArr[^i]); } + _numaThreads[0] = threadArr[0..^retireCount]; } else { - // TODO 切换来源 - // TODO _threads退休并移除 - MatrixParallelThread[] allThreads = _threads.PopRange(_threads.Count); - Array.Sort(allThreads, static( - left, - right - ) => CompareSIMDID(left.Simd, right.Simd)); - int retireCount = Math.Min(RESERVED_THREAD_COUNT, Math.Max(0, allThreads.Length - 1)); - for (int i = 0; i < retireCount; i++) { - RetireThread(allThreads[i]); - } - _threads.PushRange(allThreads.AsSpan(retireCount)); + RetireWhenMultipleSIMDID(); } - _meaningful = _threads.Count > 1; - _awaitingLeaderHandle = new AwaitingQueue(); + _meaningful = _threads.Length > 1; + + // _awaitingLeaderHandle = new AwaitingQueue(); IsInitialized = true; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void RetireThread( + MatrixParallelThread thread + ) + { + thread.Pause(); + thread.Dispose(); + _retiredThreads.Push(thread); + } + + private static void RetireWhenMultipleSIMDID() + { + MatrixParallelThread[] allThreads = new MatrixParallelThread[Environment.ProcessorCount]; + int offset = 0; + foreach (MatrixParallelThread[] threadArr in _numaThreads) + { + Array.Copy(threadArr, 0, allThreads, offset, threadArr.Length); + offset += threadArr.Length; + } + Array.Sort(allThreads, static( + left, + right + ) => CompareSIMDID(left.Simd, right.Simd)); + int retireCount = Math.Min(RESERVED_THREAD_COUNT, Math.Max(0, allThreads.Length)); + + // HashSet retiredSet = []; + MatrixParallelThread[] retireArr = new MatrixParallelThread[retireCount]; + for (int i = 0; i < retireCount; i++) + { + MatrixParallelThread thread = allThreads[i]; + retireArr[i] = thread; + RetireThread(thread); + } + + // rebuild numa active arrays + for (int numa = 0; numa < _numaThreads.Length; numa++) + { + MatrixParallelThread[] source = _numaThreads[numa]; + int keepCount = 0; + + for (int i = 0; i < source.Length; i++) + { + if (!retireArr.Contains(source[i])) { + keepCount++; + } + } + + MatrixParallelThread[] active = new MatrixParallelThread[keepCount]; + int index = 0; + for (int i = 0; i < source.Length; i++) + { + MatrixParallelThread thread = source[i]; + if (!retireArr.Contains(thread)) { + active[index++] = thread; + } + } + + _numaThreads[numa] = active; + } + + _threads = allThreads[retireCount..]; + } + + #region C invoke + [LibraryImport(Native.LibName, EntryPoint = "sn_compare_simd")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)] @@ -148,15 +206,6 @@ namespace StgSharp.Mathematics.Numeric ulong id ); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void RetireThread( - MatrixParallelThread thread - ) - { - thread.Pause(); - _retiredThreads.Push(thread); - } - [LibraryImport(Native.LibName, EntryPoint = "sn_get_unite_simd")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)] @@ -165,5 +214,6 @@ namespace StgSharp.Mathematics.Numeric SIMDID right ); + #endregion } } diff --git a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelQueue.cs b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelQueue.cs index eb0e1ebd..2ffff4f8 100644 --- a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelQueue.cs +++ b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelQueue.cs @@ -39,8 +39,8 @@ using System.Threading.Tasks; namespace StgSharp.Mathematics.Numeric { - internal unsafe class MatrixParallelQueue where T : unmanaged, INumber - where TPredictor : class, IMatrixCachePredictor + internal unsafe class MatrixParallelQueue + where TPredictor : class, IMatrixCachePredictor { [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelThread.cs b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelThread.cs index 2267aeeb..4cb5f1a9 100644 --- a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelThread.cs +++ b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelThread.cs @@ -48,7 +48,7 @@ namespace StgSharp.Mathematics.Numeric } - public unsafe partial class MatrixParallelThread : IDisposable + public unsafe partial class MatrixParallelThread : IEquatable, IDisposable { private IntrinsicContext* _context; @@ -122,7 +122,7 @@ namespace StgSharp.Mathematics.Numeric State = MatrixThreadState.Born; // Bind OS-thread affinity once when the worker starts running - ThreadHelper.SetThreadAffinity(BindedLogicalCore); + ThreadHelper.BindToLogicalCore(BindedLogicalCore); _ = Thread.Yield(); if (Simd.Mask != 0) { @@ -186,6 +186,13 @@ namespace StgSharp.Mathematics.Numeric IntrinsicContext* context, ulong id ); + + public bool Equals( + MatrixParallelThread? other + ) + { + return (other is not null) && ReferenceEquals(this, other); + } #pragma warning restore CA5393 } } diff --git a/StgSharp.Mathematics/StgSharp.Mathematics.csproj b/StgSharp.Mathematics/StgSharp.Mathematics.csproj index c82748a5..c498a5df 100644 --- a/StgSharp.Mathematics/StgSharp.Mathematics.csproj +++ b/StgSharp.Mathematics/StgSharp.Mathematics.csproj @@ -5,11 +5,6 @@ - - - - - diff --git a/StgSharp.Native/sn-head/StgSharpNative.h b/StgSharp.Native/sn-head/StgSharpNative.h index e5d41ac6..a1179018 100644 --- a/StgSharp.Native/sn-head/StgSharpNative.h +++ b/StgSharp.Native/sn-head/StgSharpNative.h @@ -41,7 +41,6 @@ extern SN_API char infolog[512]; SN_API int SN_DECL glCheckShaderStat(GladGLContext *context, uint64_t shaderHandle, int key, char **logRef); SN_API void SN_DECL initGL(int majorVersion, int minorVersion); -SN_API unsigned int SN_DECL linkShaderProgram(GladGLContext *context, GLuint shadertype); SN_API void SN_DECL loadImageData(char *location, Image *out, imageLoader loader); SN_API GLFWglproc SN_DECL loadGlfuncDefault(char *procName); SN_API void SN_DECL unloadImageData(Image *out); diff --git a/StgSharp.Native/sn-src/sn_native.c b/StgSharp.Native/sn-src/sn_native.c index 2a62c7ce..b1d0374b 100644 --- a/StgSharp.Native/sn-src/sn_native.c +++ b/StgSharp.Native/sn-src/sn_native.c @@ -44,19 +44,6 @@ SN_API GLFWglproc SN_DECL loadGlfuncDefault(char *procName) return (GLFWglproc)ret; } -SN_API unsigned int SN_DECL linkShaderProgram(GladGLContext *context, GLuint shaderProgram) -{ - context->LinkProgram(shaderProgram); - - int success; - context->GetProgramiv(shaderProgram, GL_LINK_STATUS, &success); - if (!success) { - context->GetProgramInfoLog(shaderProgram, 512, NULL, infolog); - return 0; - } else { - return shaderProgram; - } -} SN_API void SN_DECL loadImageData(char *location, Image *out, imageLoader loader) {