From 9c4c71dc5bae6b75dc63acee438a8fff6a4b7c83 Mon Sep 17 00:00:00 2001 From: Youmu Liu <105042599+Nitload-NSI@users.noreply.github.com> Date: Mon, 3 Nov 2025 20:03:50 +0800 Subject: [PATCH] [rebuid]use dynamic wrapping instead of static wrapping --- .../Collections/BidirectionalDictionary.cs | 31 ++-- .../Collections/CapacityFixedStack.cs | 8 +- .../Collections/IBidrirectionalDictionary.cs | 42 ++--- .../Collections/PartialDictionary.cs | 174 ------------------ .../Collections/PartialDictionaryValues.cs | 102 ---------- .../Collections/RandomAccessibleStack.cs | 9 +- .../Collections/StringHashMultiplexer.cs | 4 +- .../Numeric/MatrixCompute.Basic.cs | 11 +- StgSharp.Mathematics/Numeric/MatrixMarshal.cs | 40 ---- .../Numeric/MatrixParallel.Publish.cs | 4 + .../Numeric/MatrixParallel.cs | 60 +----- .../Numeric/MatrixParallelTask.cs | 70 ++++--- .../Numeric/MatrixParallelThread.cs | 167 +++++++++++++++++ .../Numeric/MatrixParallelWrap.cs | 152 +++------------ .../Numeric/MatrixTaskFactory.cs | 52 +++--- 15 files changed, 331 insertions(+), 595 deletions(-) delete mode 100644 StgSharp.Common/Collections/PartialDictionary.cs delete mode 100644 StgSharp.Common/Collections/PartialDictionaryValues.cs delete mode 100644 StgSharp.Mathematics/Numeric/MatrixMarshal.cs create mode 100644 StgSharp.Mathematics/Numeric/MatrixParallelThread.cs diff --git a/StgSharp.Common/Collections/BidirectionalDictionary.cs b/StgSharp.Common/Collections/BidirectionalDictionary.cs index 8ed76745..7969ef15 100644 --- a/StgSharp.Common/Collections/BidirectionalDictionary.cs +++ b/StgSharp.Common/Collections/BidirectionalDictionary.cs @@ -29,12 +29,13 @@ using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Diagnostics.CodeAnalysis; using System.Linq; namespace StgSharp.Collections { public sealed class BidirectionalDictionary : IBidirectionalDictionary + where TFirst: notnull + where TSecond: notnull { private readonly Dictionary _forward; @@ -42,25 +43,21 @@ namespace StgSharp.Collections public BidirectionalDictionary() { - _forward = new Dictionary(); - _reverse = new Dictionary(); + _forward = []; + _reverse = []; } public TFirst this[TSecond key] { - get - { - if (_reverse.TryGetValue(key, out TFirst value)) { - return value; - } - throw new ArgumentException($"Cannot find key {key!.ToString()} in dictionary."); - } + get => _reverse.TryGetValue(key, out TFirst value) ? + value : + throw new ArgumentException($"Cannot find key {key} in dictionary."); set { if (_reverse.TryGetValue(key, out TFirst origin)) { _reverse[key] = value; - _forward.Remove(origin); + _ = _forward.Remove(origin); } else { _reverse.Add(key, value); @@ -71,19 +68,15 @@ namespace StgSharp.Collections public TSecond this[TFirst key] { - get - { - if (_forward.TryGetValue(key, out TSecond value)) { - return value; - } - throw new ArgumentException($"Cannot find key {key!.ToString()} in dictionary."); - } + get => _forward.TryGetValue(key, out TSecond value) ? + value : + throw new ArgumentException($"Cannot find key {key} in dictionary."); set { if (_forward.TryGetValue(key, out TSecond origin)) { _forward[key] = value; - _reverse.Remove(origin); + _ = _reverse.Remove(origin); } else { _forward.Add(key, value); diff --git a/StgSharp.Common/Collections/CapacityFixedStack.cs b/StgSharp.Common/Collections/CapacityFixedStack.cs index da84986e..002e91db 100644 --- a/StgSharp.Common/Collections/CapacityFixedStack.cs +++ b/StgSharp.Common/Collections/CapacityFixedStack.cs @@ -28,7 +28,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; namespace StgSharp.Collections @@ -88,6 +87,13 @@ namespace StgSharp.Collections } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ReadOnlySpan PopRange(int count) + { + int i = int.Min(count, _index) - 1; + return _values[0..i]; + } + public void Push(T item) { _values[++_index] = _index < _values.Length - 1 ? diff --git a/StgSharp.Common/Collections/IBidrirectionalDictionary.cs b/StgSharp.Common/Collections/IBidrirectionalDictionary.cs index 73e9977f..200558e8 100644 --- a/StgSharp.Common/Collections/IBidrirectionalDictionary.cs +++ b/StgSharp.Common/Collections/IBidrirectionalDictionary.cs @@ -25,60 +25,60 @@ // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- -using System; -using System.Collections; using System.Collections.Generic; -using System.Threading.Tasks; namespace StgSharp.Collections { public interface IBidirectionalDictionary : IDictionary { - public TFirst this[TSecond key] { get; set; } + TFirst this[TSecond key] { get; set; } - public ICollection FirstIndex { get; } + ICollection FirstIndex { get; } - public ICollection SecondIndex { get; } + ICollection SecondIndex { get; } - public IReadOnlyDictionary Forward { get; } + IReadOnlyDictionary Forward { get; } - public IReadOnlyDictionary Reverse { get; } + IReadOnlyDictionary Reverse { get; } /// - /// Determines whether the - /// contains the specified key. + /// Determines whether the contains the + /// specified key. /// /// /// The value to locate in the . /// /// - /// true if the contains an - /// element with the specified key; otherwise, false. + /// true if the contains an element with + /// the specified key; otherwise, false. /// - public bool Contains(TSecond key); + bool Contains(TSecond key); /// - /// Determines whether the - /// contains the specified key. + /// Determines whether the contains the + /// specified key. /// /// /// The value to locate in the . /// /// - /// true if the contains an - /// element with the specified key; otherwise, false. + /// true if the contains an element with + /// the specified key; otherwise, false. /// - public bool Contains(TFirst key); + bool Contains(TFirst key); - public bool TryGetValue(TSecond key, out TFirst value); + bool TryGetValue(TSecond key, out TFirst value); #pragma warning disable CA1033 ICollection IDictionary.Keys => FirstIndex; ICollection IDictionary.Values => SecondIndex; - bool IDictionary.ContainsKey(TFirst key) => Contains(key); -#pragma warning restore CA1033 + bool IDictionary.ContainsKey(TFirst key) + { + return Contains(key); + } +#pragma warning restore CA1033 } } \ No newline at end of file diff --git a/StgSharp.Common/Collections/PartialDictionary.cs b/StgSharp.Common/Collections/PartialDictionary.cs deleted file mode 100644 index f0c3e314..00000000 --- a/StgSharp.Common/Collections/PartialDictionary.cs +++ /dev/null @@ -1,174 +0,0 @@ -//----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -// file="PartialDictionary" -// Project: StgSharp -// 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. -// -// ----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Net.Http.Headers; -using System.Text; - -namespace StgSharp.Collections -{ - public partial class PartialDictionary : IDictionary - { - - private readonly Dictionary _source; - private readonly HashSet _keys; - private readonly PartialDictionaryValues _values; - - public PartialDictionary(Dictionary source, TKey[] index) - { - _source = source; - _keys = new HashSet(index); - foreach (TKey item in _keys) - { - if (!_source.ContainsKey(item)) { - _source.Add(item, default!); - } - } - _values = new PartialDictionaryValues(this); - } - - public PartialDictionary(Dictionary source, HashSet keys) - { - _source = source; - _keys = keys; - foreach (TKey item in _keys) - { - if (!_source.ContainsKey(item)) { - _source.Add(item, default!); - } - } - _values = new PartialDictionaryValues(this); - } - - public PartialDictionary(Dictionary source, TKey[] index, IHashMultiplexer multiplexer) - { - _source = source; - _keys = new HashSet(index); - foreach (TKey item in _keys) - { - if (!_source.ContainsKey(item)) { - _source.Add(item, default!); - } - } - _values = new PartialDictionaryValues(this); - } - - public TValue this[TKey key] - { - get - { - if (_keys.Contains(key)) { - return _source[key]; - } - throw new KeyNotFoundException(); - } - set - { - if (_keys.Contains(key)) { - _source[key] = value; - } - throw new KeyNotFoundException(); - } - } - - public ICollection Keys => _keys; - - public ICollection Values => _values; - - public int Count => _keys.Count; - - public bool Contains(KeyValuePair item) - { - return _keys.Contains(item.Key) && _source.Contains(item); - } - - public bool ContainsKey(TKey key) - { - return _keys.Contains(key); - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - throw new NotImplementedException(); - } - - public IEnumerator> GetEnumerator() - { - foreach (TKey item in _keys) { - yield return new KeyValuePair(item, _source[item]); - } - } - - public bool TryGetValue(TKey key, out TValue value) - { - if (_keys.Contains(key)) - { - value = _source[key]; - return true; - } - value = default!; - return false; - } - - void ICollection>.Add(KeyValuePair item) - { - return; - } - - void ICollection>.Clear() - { - throw new NotSupportedException(); - } - - bool ICollection>.Remove(KeyValuePair item) - { - throw new NotSupportedException(); - } - - bool ICollection>.IsReadOnly => true; - - void IDictionary.Add(TKey key, TValue value) - { - return; - } - - bool IDictionary.Remove(TKey key) - { - throw new NotSupportedException(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - } -} diff --git a/StgSharp.Common/Collections/PartialDictionaryValues.cs b/StgSharp.Common/Collections/PartialDictionaryValues.cs deleted file mode 100644 index d516b8f1..00000000 --- a/StgSharp.Common/Collections/PartialDictionaryValues.cs +++ /dev/null @@ -1,102 +0,0 @@ -//----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -// file="PartialDictionaryValues" -// Project: StgSharp -// 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. -// -// ----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text; - -namespace StgSharp.Collections -{ - public partial class PartialDictionary - { - - internal sealed class PartialDictionaryValues : ICollection - { - - private readonly PartialDictionary _values; - - public PartialDictionaryValues(PartialDictionary value) - { - _values = value; - } - - public bool IsReadOnly => true; - - public int Count => _values.Count; - - public bool Contains(TValue item) - { - foreach (KeyValuePair kvp in _values) - { - if (kvp.Value != null && kvp.Value.Equals(item)) { - return true; - } - } - return false; - } - - public void CopyTo(TValue[] array, int arrayIndex) - { - foreach (KeyValuePair kvp in _values) - { - array[arrayIndex] = kvp.Value; - arrayIndex++; - } - } - - public IEnumerator GetEnumerator() - { - foreach (TKey key in _values._keys) { - yield return _values._source[key]; - } - } - - void ICollection.Add(TValue item) - { - return; - } - - void ICollection.Clear() - { - return; - } - - bool ICollection.Remove(TValue item) - { - throw new NotSupportedException(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - } - - } -} diff --git a/StgSharp.Common/Collections/RandomAccessibleStack.cs b/StgSharp.Common/Collections/RandomAccessibleStack.cs index 024fe062..fabe52ab 100644 --- a/StgSharp.Common/Collections/RandomAccessibleStack.cs +++ b/StgSharp.Common/Collections/RandomAccessibleStack.cs @@ -28,10 +28,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; namespace StgSharp.Collections { @@ -176,7 +172,10 @@ namespace StgSharp.Collections Array.Resize(ref _array, newCapacity); } - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } } } diff --git a/StgSharp.Common/Collections/StringHashMultiplexer.cs b/StgSharp.Common/Collections/StringHashMultiplexer.cs index 1a09285b..05f2ffc4 100644 --- a/StgSharp.Common/Collections/StringHashMultiplexer.cs +++ b/StgSharp.Common/Collections/StringHashMultiplexer.cs @@ -102,8 +102,8 @@ namespace StgSharp.Collections public int RemainedMultiplexCount { - get => _multiplexers.Value.RemainedMultiplexCount; - set => _multiplexers.Value.RemainedMultiplexCount = value; + get => _multiplexers.Value!.RemainedMultiplexCount; + set => _multiplexers.Value!.RemainedMultiplexCount = value; } public void CacheHash(string obj, int count) diff --git a/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs b/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs index 08ef61dc..2af8c137 100644 --- a/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs +++ b/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs @@ -25,6 +25,7 @@ // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- +using StgSharp.Collections; using StgSharp.HighPerformance; using StgSharp.Internal; using System; @@ -48,8 +49,8 @@ namespace StgSharp.Mathematics.Numeric long count = (long)left.KernelColumnLength * left.KernelRowLength; if (count <= 1024) { - MatrixParallelPool pool = MatrixParallel.LeadParallel(); - if (!pool.TryRentIndividualHandle(out MatrixParallelWrap.Handle? handle)) + CapacityFixedStack pool = MatrixParallel.LeadParallel(); + if (!pool.TryPop(out MatrixParallelThread thread)) { /* * wait @@ -82,8 +83,9 @@ namespace StgSharp.Mathematics.Numeric long count = (long)left.KernelColumnLength * left.KernelRowLength; if (count <= 1024) { - MatrixParallelPool pool = MatrixParallel.LeadParallel(); - if (!pool.TryRentIndividualHandle(out MatrixParallelWrap.Handle? handle)) + // TODO: this is very awkward, blocking thread renting, need a better way to handle small tasks + CapacityFixedStack pool = MatrixParallel.LeadParallel(); + if (!pool.TryPop(out MatrixParallelThread thread)) { /* * wait @@ -95,6 +97,7 @@ namespace StgSharp.Mathematics.Numeric for (int i = 0; i < count; i++) { NativeIntrinsic.Intrinsic.f32_sub(leftPtr + i, rightPtr + i, ansPtr + i); } + return ans; } Stack taskGroup = MatrixParallel.PublicTask(left.GetColumnEnumeration(), right.GetColumnEnumeration(), ans.GetColumnEnumeration(), diff --git a/StgSharp.Mathematics/Numeric/MatrixMarshal.cs b/StgSharp.Mathematics/Numeric/MatrixMarshal.cs deleted file mode 100644 index 967a3a1f..00000000 --- a/StgSharp.Mathematics/Numeric/MatrixMarshal.cs +++ /dev/null @@ -1,40 +0,0 @@ -//----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -// file="MatrixMarshal.cs" -// Project: StgSharp -// AuthorGroup: Nitload Space -// Copyright (c) Nitload Space. 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. -// -// ----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace StgSharp.Mathematics -{ - public readonly ref struct MatrixMarshal { } -} diff --git a/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs b/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs index be8d2684..894aa176 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs @@ -837,6 +837,8 @@ namespace StgSharp.Mathematics.Numeric { #if DEBUG throw new InvalidOperationException("Someone steal parallel wraps from the pool."); +#else + break; #endif } @@ -854,6 +856,8 @@ namespace StgSharp.Mathematics.Numeric { #if DEBUG throw new InvalidOperationException("Zero tasks published."); +#else + break; #endif } diff --git a/StgSharp.Mathematics/Numeric/MatrixParallel.cs b/StgSharp.Mathematics/Numeric/MatrixParallel.cs index e111b859..4e1977a7 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallel.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallel.cs @@ -54,7 +54,6 @@ namespace StgSharp.Mathematics.Numeric public static partial class MatrixParallel { - private static Thread[] _threads; private static readonly (int a, int b)[] LookupTable = [ (1, 1), // 7 (0, 2), // 8 (no non-zero solution) @@ -73,6 +72,8 @@ namespace StgSharp.Mathematics.Numeric ]; private static bool _meaningful; + private static CapacityFixedStack _threads; + private static volatile int RemainThreadCount = 0; private static readonly object _lock = new(); private static ThreadPriority _AfterWork = ThreadPriority.Lowest; @@ -118,46 +119,16 @@ namespace StgSharp.Mathematics.Numeric return; } int count = Environment.ProcessorCount - 4; - count = count == 5 ? 4 : count; - _threads = new Thread[count]; - if (count < 6) - { - if (count == 3) - { - Pool = new(3, [ new MatrixParallelWrap(0, count) ]); - (LargeWrapCount, SmallWrapCount) = (0, 1); - } else - { - count = 4; - Pool = new(4, [ new MatrixParallelWrap(0, count) ]); - (LargeWrapCount, SmallWrapCount) = (1, 0); - } - } else if (count == 6) - { - Pool = new(6, [ - new MatrixParallelWrap(0, 3), - new MatrixParallelWrap(3, 3) - ]); - (LargeWrapCount, SmallWrapCount) = (0, 2); - } else - { - (int _3wrap, int _4wrap) = FastDecompose(count); - CapacityFixedStack stack = new(_4wrap + _3wrap); - int id = 0, idx = 0; - for (; idx < _3wrap; idx++, id += 3) { - stack.Push(new MatrixParallelWrap(idx, 3)); - } - for (; idx < _3wrap + _4wrap; idx++, id += 4) { - stack.Push(new MatrixParallelWrap(id, 4)); - } - Pool = new MatrixParallelPool(count, stack); + _threads = new(count); + for (int i = 0; i < count; i++) { + _threads.Push(new()); } IsInitialized = true; } public static void LaunchParallel(IEnumerable wraps, SleepMode afterWork) { - RemainThreadCount = _threads.Length; + RemainThreadCount = _threads.Count; _AfterWork = (ThreadPriority)afterWork; ResetThreadCount(); foreach (MatrixParallelWrap w in wraps) { @@ -165,36 +136,25 @@ namespace StgSharp.Mathematics.Numeric } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe void MatrixParallelLeaderWork() - { - MatrixParallelWrap.ExecuteTaskPackage(LeaderTask); - _ = Interlocked.Decrement(ref RemainThreadCount); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ResetThreadCount() { - RemainThreadCount = _threads.Length; + RemainThreadCount = _threads.Count; } #region wrap field - private static MatrixParallelPool Pool; - private static int LargeWrapCount; - private static int SmallWrapCount; - - public static MatrixParallelPool LeadParallel() + public static CapacityFixedStack LeadParallel() { #if NET9_0_OR_GREATER #else Monitor.Enter(_lock); #endif - return Pool; + return _threads; } - public static void ReleaseParallelLeadership(ref MatrixParallelPool pool) + public static void ReleaseParallelLeadership(ref CapacityFixedStack pool) { #if NET9_0_OR_GREATER #else diff --git a/StgSharp.Mathematics/Numeric/MatrixParallelTask.cs b/StgSharp.Mathematics/Numeric/MatrixParallelTask.cs index 0addf485..ade862d8 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallelTask.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallelTask.cs @@ -51,77 +51,89 @@ namespace StgSharp.Mathematics.Numeric } [StructLayout(LayoutKind.Sequential)] - internal readonly unsafe struct MatrixParallelTaskPackageNonGeneric + internal unsafe struct MatrixParallelTaskPackageNonGeneric { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void Copy( + MatrixParallelTaskPackageNonGeneric* source, + MatrixParallelTaskPackageNonGeneric* target) + { + Buffer.MemoryCopy( + source, + target, + sizeof(MatrixParallelTaskPackageNonGeneric), + sizeof(MatrixParallelTaskPackageNonGeneric)); + } + #region source // Group 1: Left/Right matrix kernel base address - public readonly IntPtr Left; // 8 - public readonly IntPtr Right; // 8 + public IntPtr Left; // 8 + public IntPtr Right; // 8 #endregion #region ans // Group 2: Result kernel base address + reserved - public readonly IntPtr Result; // 8 - public readonly int ElementSize; - public readonly int ReservedPtr0; // 4 (extension/reserved) + public IntPtr Result; // 8 + public int ElementSize; + public int ReservedPtr0; // 4 (extension/reserved) #endregion #region left enum - public readonly int LeftPrimOffset; // 4 - public readonly int LeftPrimStride; // 4 - public readonly int LeftSecOffset; // 4 - public readonly int LeftSecStride; // 4 + public int LeftPrimOffset; // 4 + public int LeftPrimStride; // 4 + public int LeftSecOffset; // 4 + public int LeftSecStride; // 4 #endregion #region right enum - public readonly int RightPrimOffset; // 4 - public readonly int RightPrimStride; // 4 - public readonly int RightSecOffset; // 4 - public readonly int RightSecStride; // 4 + public int RightPrimOffset; // 4 + public int RightPrimStride; // 4 + public int RightSecOffset; // 4 + public int RightSecStride; // 4 #endregion #region ans enum - public readonly int ResultPrimOffset; // 4 - public readonly int ResultPrimStride; // 4 - public readonly int ResultSecOffset; // 4 - public readonly int ResultSecStride; // 4 + public int ResultPrimOffset; // 4 + public int ResultPrimStride; // 4 + public int ResultSecOffset; // 4 + public int ResultSecStride; // 4 #endregion #region scalar/compute - public readonly ScalarPacket* Scalar; // 8 - public readonly IntPtr ComputeHandle; // 8 + public ScalarPacket* Scalar; // 8 + public IntPtr ComputeHandle; // 8 #endregion #region global profile - public readonly int PrimCount; // 4 - public readonly int ComputeMode; // 4 - public readonly int SecCount; // 4 - private readonly int ReservedInt0; // 4 + public int PrimCount; // 4 + public int ComputeMode; // 4 + public int SecCount; // 4 + private int ReservedInt0; // 4 #endregion #region count offset - public readonly int PrimTileOffset; // 4 - public readonly int SecTileOffset; // 4 - public readonly int PrimCountInTile; // 4 - public readonly int SecCountInTile; // 4 + public int PrimTileOffset; // 4 + public int SecTileOffset; // 4 + public int PrimCountInTile; // 4 + public int SecCountInTile; // 4 - #endregion + #endregion } [StructLayout(LayoutKind.Sequential)] diff --git a/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs b/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs new file mode 100644 index 00000000..c4fa8070 --- /dev/null +++ b/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs @@ -0,0 +1,167 @@ +//----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +// file="MatrixParallelThread" +// Project: StgSharp +// 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. +// +// ----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace StgSharp.Mathematics.Numeric +{ + public class MatrixParallelThread : IDisposable + { + + private bool disposedValue; + private ManualResetEventSlim _resetEvent; + private Thread _managedThread; + + public MatrixParallelThread() + { + _managedThread = new Thread(MatrixParallelWorker); + _resetEvent = new ManualResetEventSlim(false); + } + + // ~MatrixComputeThread() + // { + // Dispose(disposing: false); + // } + + public ThreadPriority AfterWork + { + get => field; + set => field = value; + } + + public void Dispose() + { + Dispose(disposing:true); + GC.SuppressFinalize(this); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void ExecuteTaskPackage(Queue taskQueue) + { + while (taskQueue.TryDequeue(out nint handle)) + { + MatrixParallelTaskPackageNonGeneric* p = (MatrixParallelTaskPackageNonGeneric*)handle; + switch (p->ComputeMode) + { + case 1: + MatrixComputeModel.Compute_Unary(p); + break; + case 2: + MatrixComputeModel.Compute_UnaryScalar(p); + break; + case 3: + MatrixComputeModel.Compute_Binary(p); + break; + case 4: + MatrixComputeModel.Compute_BinaryScalar(p); + break; + default: + break; + } + } + } + + public void Restart() + { + _resetEvent.Set(); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + _resetEvent.Dispose(); + _managedThread.Join(); + } + + disposedValue = true; + } + } + + private unsafe void MatrixParallelWorker() + { + // Thread self = Thread.CurrentThread; + do + { + _resetEvent.Wait(); + _resetEvent.Reset(); + _managedThread.Priority = ThreadPriority.Highest; + switch (Role) + { + case 0://worker + // _ = Interlocked.Decrement(ref RemainThreadCount); + ExecuteTaskPackage(Tasks); + break; + case 1://scheduler + BindedWrap.PublishTaskToWorkers(Tasks); + 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; + } while (true); + } + + #region wrap belong + + internal MatrixParallelWrap BindedWrap { get; set; } = null!; + + internal Queue Tasks { get; } = []; + + internal int Role + { + get; + set + { + if ((Role & (~3u)) == 0) + { + field = value; + } else + { +#if DEBUG + throw new ArgumentOutOfRangeException(nameof(Role)); +#endif + } + } + } + + #endregion + } +} diff --git a/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs b/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs index 54101f95..21e4cbbb 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs @@ -39,44 +39,13 @@ namespace StgSharp.Mathematics.Numeric public unsafe class MatrixParallelWrap { - private readonly Handle[] _resetHandle; - private readonly Thread[] _threads; + private readonly MatrixParallelThread[] _threads; - public MatrixParallelWrap(int id, int wrapSize) + public MatrixParallelWrap() { - ID = id; - _threads = new Thread[wrapSize]; - _resetHandle = new Handle[wrapSize]; - for (int i = 0; i < wrapSize; i++) - { - _threads[i] = new Thread(MatrixParallelWorker) - { - IsBackground = true, - Priority = ThreadPriority.BelowNormal, - Name = $"MPT#{ID}_{i}" - }; - Handle handle = new Handle(i, this); - _resetHandle[i] = handle; - _threads[i].Start(handle); - } + _threads = new MatrixParallelThread[5]; } - public bool IsAllAvailable - { - get - { - foreach (Handle item in _resetHandle) - { - if (item.Role != 0) { - return false; - } - } - return true; - } - } - - public int ID { get; init; } - public static SleepMode AfterWork { get; @@ -87,27 +56,39 @@ namespace StgSharp.Mathematics.Numeric internal ManualResetEventSlim SchedulerReset { get; } = new(false); + private int Count { get; set; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetAllWorker() { - foreach (Handle item in _resetHandle) { - item.ResetEvent.Set(); + foreach (MatrixParallelThread t in _threads) { + t.Restart(); } } - internal bool TryGetLeaderHandle(out Handle? handle) + internal void PublishTaskToWorkers(Queue tasks) { - foreach (Handle item in _resetHandle) + while (tasks.TryDequeue(out nint handle)) { - if (item.Role != 2) - { - handle = item; - item.Role = 2; - return true; - } + MatrixParallelTaskPackageNonGeneric* task = (MatrixParallelTaskPackageNonGeneric*)handle; + PublishTaskToWorkers(task); + } + } + + internal void PublishTaskToWorkers(MatrixParallelTaskPackageNonGeneric* taskPackage) + { + int primCount = taskPackage->PrimCount; + int secCount = taskPackage->SecCount; + + int primAverage = primCount / Count; + int secAverage = secCount / Count; + bool shouldSliceSec = secAverage > 512; + for (int i = 0; i < Count; i++) + { + Queue tasks = _threads[i].Tasks; + MatrixParallelTaskPackageNonGeneric* subTask = MatrixParallelFactory.FromExistPackage(taskPackage); + subTask->PrimTileOffset = i * primAverage; } - handle = null; - return false; } public class Handle(int inWrapIndex, MatrixParallelWrap wrap) @@ -141,71 +122,6 @@ namespace StgSharp.Mathematics.Numeric get => _threads.Length; } - #endregion - - - #region ThreadOperation - - private static unsafe void MatrixParallelWorker([AllowNull] object obj) - { - Handle handle = (obj as Handle)!; - MatrixParallelWrap wrap = handle.Wrap; - int inWrapIndex = handle.InWrapIndex; - Thread self = Thread.CurrentThread; - ManualResetEventSlim reset = handle.ResetEvent; - do - { - reset.Wait(); - reset.Reset(); - Queue taskQueue = handle.TaskCache; - self.Priority = ThreadPriority.Highest; - switch (handle.Role) - { - case 0://worker - // _ = Interlocked.Decrement(ref RemainThreadCount); - ExecuteTaskPackage(handle.TaskCache); - break; - case 1://scheduler - // TODO task publication to worker in wrap - wrap.SetAllWorker(); - ExecuteTaskPackage(taskQueue); - - break; - case 2://leader, error because leader should be at outer thread but not here - break; - default: - break; - } - self.Priority = (ThreadPriority)AfterWork; - } while (true); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe void ExecuteTaskPackage(Queue taskQueue) - { - while (taskQueue.TryDequeue(out nint handle)) - { - MatrixParallelTaskPackageNonGeneric* p = (MatrixParallelTaskPackageNonGeneric*)handle; - switch (p->ComputeMode) - { - case 1: - MatrixComputeModel.Compute_Unary(p); - break; - case 2: - MatrixComputeModel.Compute_UnaryScalar(p); - break; - case 3: - MatrixComputeModel.Compute_Binary(p); - break; - case 4: - MatrixComputeModel.Compute_BinaryScalar(p); - break; - default: - break; - } - } - } - #endregion } @@ -217,18 +133,4 @@ namespace StgSharp.Mathematics.Numeric DeepSleep = ThreadPriority.Lowest, } - - public class MatrixComputeResource - { - - public IEnumerable Wraps { get; set; } - - public int WorkingThreadCount { get; set; } - - /// - /// Closure task leader should do to collect results. - /// - public unsafe IntPtr LeaderClosurePackage { get; set; } - - } } diff --git a/StgSharp.Mathematics/Numeric/MatrixTaskFactory.cs b/StgSharp.Mathematics/Numeric/MatrixTaskFactory.cs index 94507c8e..98374399 100644 --- a/StgSharp.Mathematics/Numeric/MatrixTaskFactory.cs +++ b/StgSharp.Mathematics/Numeric/MatrixTaskFactory.cs @@ -1,30 +1,27 @@ //----------------------------------------------------------------------- // ----------------------------------------------------------------------- -// file="MatrixParallel.TaskFactory.cs" +// file="MatrixTaskFactory" // 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. // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- @@ -85,6 +82,15 @@ namespace StgSharp.Mathematics.Numeric return ptr; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe MatrixParallelTaskPackageNonGeneric* FromExistPackage( + MatrixParallelTaskPackageNonGeneric* exist) + { + MatrixParallelTaskPackageNonGeneric* ptr = (MatrixParallelTaskPackageNonGeneric*)_wrapAllocator.Allocate(); + MatrixParallelTaskPackageNonGeneric.Copy(exist, ptr); + return ptr; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Release(ScalarPacket* source)