diff --git a/StgSharp.Common/Collections/CapacityFixedBag.cs b/StgSharp.Common/Collections/CapacityFixedBag.cs index 69c48c28..bb1fbd5a 100644 --- a/StgSharp.Common/Collections/CapacityFixedBag.cs +++ b/StgSharp.Common/Collections/CapacityFixedBag.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Reflection; namespace StgSharp.Collections { @@ -72,6 +73,16 @@ namespace StgSharp.Collections } } + public void RemoveAt(int index) + { + if (index >= 0) + { + _buffer[index] = _buffer[Count - 1]; + _buffer[Count - 1] = default!; + Count--; + } + } + IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); diff --git a/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs b/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs index f97c01b0..d7216bb4 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs @@ -820,27 +820,27 @@ namespace StgSharp.Mathematics.Numeric int tileWidth = (1024 / secCount) + 1; int tileCount = (primCount / tileWidth) + 1; - CapacityFixedStack wraps = LeadParallel(); + MatrixParallelPool pool = LeadParallel(); - int tilePerThreadLess = tileCount / wraps.Count; - int tileToSlice = tileCount % wraps.Count; - int slicingPerWrap = tileToSlice / wraps.Count; - int extraTiles = tileToSlice % wraps.Count; + int tilePerThreadLess = tileCount / pool.SpareThreadCount; + int tileToSlice = tileCount % pool.SpareThreadCount; + int slicingPerWrap = tileToSlice / pool.SpareThreadCount; + int extraTiles = tileToSlice % pool.SpareThreadCount; int total = tileCount; int begin = 0; - Stack taskBunch = new Stack(wraps.Count); + Stack taskBunch = new Stack(pool.SpareThreadCount); while (tileCount > 0) { - MatrixParallelWrap wrap = wraps.Pop(); + _ = pool.TryRequestWrap(out MatrixParallelWrap? wrap); bool hasSlice = tileToSlice > 0; bool isLargeSlice = extraTiles > 0; // count tiles for wrap // TODO 此处应该是线程数量而不是线程束数量 // TODO 需要想办法正确同步线程数量信息 - int toSlice = hasSlice ? wrap.WrapTaskCapacity * slicingPerWrap : 0; - int baseTile = wrap.WrapTaskCapacity * tilePerThreadLess; + int toSlice = hasSlice ? wrap!.WrapTaskCapacity * slicingPerWrap : 0; + int baseTile = wrap!.WrapTaskCapacity * tilePerThreadLess; int tileInWrap = baseTile + toSlice + (isLargeSlice ? 1 : 0); int columnInWrap = tileInWrap * tileWidth; @@ -857,7 +857,7 @@ namespace StgSharp.Mathematics.Numeric begin += tileInWrap; taskBunch.Push(wrap); } - ReleaseParallelLeadership(ref wraps); + ReleaseParallelLeadership(ref pool); return taskBunch; } diff --git a/StgSharp.Mathematics/Numeric/MatrixParallelPool.cs b/StgSharp.Mathematics/Numeric/MatrixParallelPool.cs index a2309f31..e464cf82 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallelPool.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallelPool.cs @@ -28,6 +28,7 @@ using StgSharp.Collections; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -46,34 +47,63 @@ namespace StgSharp.Mathematics.Numeric { SpareWrap = CapacityFixedStackBuilder.Create(wrapSpan); SingleThreadAllocation = new CapacityFixedBag(wrapSpan.Length); - SpareThreads = threadCount; + SpareThreadCount = threadCount; } internal MatrixParallelPool(int threadCount, CapacityFixedStack wrapSpan) { SpareWrap = wrapSpan; SingleThreadAllocation = new CapacityFixedBag(wrapSpan.Count); - SpareThreads = threadCount; + SpareThreadCount = threadCount; } - public int SpareThreads { get; set; } + public int SpareThreadCount { get; set; } internal CapacityFixedBag SingleThreadAllocation { get; set; } internal CapacityFixedStack SpareWrap { get; set; } - public bool TryRequestLeaderHandle(out MatrixParallelWrap.Handle handle) { } + public void ReturnIndividualHandle(ref MatrixParallelWrap.Handle handle) + { + MatrixParallelWrap wrap = handle.Wrap; + handle.Role = 0; + if (wrap.IsAllAvailable) + { + SingleThreadAllocation.RemoveAt(wrap.Magic); + SpareWrap.Push(wrap); + SpareThreadCount += wrap.WrapTaskCapacity; + } + } - public bool TryRequestWrap(out MatrixParallelWrap? wrap) + public bool TryRentIndividualHandle(out MatrixParallelWrap.Handle handle) + { + foreach (MatrixParallelWrap item in SingleThreadAllocation) + { + if (item.TryGetLeaderHandle(out handle!)) { + return true; + } + } + if (TryRequestWrap(out MatrixParallelWrap wrap)) + { + wrap!.Magic = SingleThreadAllocation.Count; + SingleThreadAllocation.Add(wrap); + if (wrap.TryGetLeaderHandle(out handle!)) { + return true; + } + } + handle = null!; + return false; + } + + public bool TryRequestWrap([NotNull]out MatrixParallelWrap? wrap) { if (SpareWrap.TryPop(out wrap)) { - SpareThreads -= wrap.WrapTaskCapacity; + SpareThreadCount -= wrap.WrapTaskCapacity; return true; - } else - { - return false; } + wrap = null!; + return false; } } diff --git a/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs b/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs index 668f5dde..bcf37e8b 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs @@ -45,6 +45,7 @@ namespace StgSharp.Mathematics.Numeric { ID = id; _threads = new Thread[wrapSize]; + _resetHandle = new Handle[wrapSize]; for (int i = 0; i < wrapSize; i++) { _threads[i] = new Thread(MatrixParallelWorker) @@ -53,7 +54,23 @@ namespace StgSharp.Mathematics.Numeric Priority = ThreadPriority.BelowNormal, Name = $"MPT#{ID}_{i}" }; - _threads[i].Start(new Handle(i, this)); + Handle handle = new Handle(i, this); + _resetHandle[i] = handle; + _threads[i].Start(handle); + } + } + + public bool IsAllAvailable + { + get + { + foreach (Handle item in _resetHandle) + { + if (item.Role != 0) { + return false; + } + } + return true; } } @@ -75,6 +92,21 @@ namespace StgSharp.Mathematics.Numeric } } + internal bool TryGetLeaderHandle(out Handle? handle) + { + foreach (Handle item in _resetHandle) + { + if (item.Role != 2) + { + handle = item; + item.Role = 2; + return true; + } + } + handle = null; + return false; + } + public class Handle(int inWrapIndex, MatrixParallelWrap wrap) {