diff --git a/.cr/personal/Editor/Right Margin Line/Right Margin Line.xml b/.cr/personal/Editor/Right Margin Line/Right Margin Line.xml index b18e300f..4f8bf4f3 100644 --- a/.cr/personal/Editor/Right Margin Line/Right Margin Line.xml +++ b/.cr/personal/Editor/Right Margin Line/Right Margin Line.xml @@ -2,7 +2,7 @@ True - + 2 \ No newline at end of file diff --git a/.cr/team/Editor/Formatting/Wrapping.CSharp.xml b/.cr/team/Editor/Formatting/Wrapping.CSharp.xml index ee502938..8b5b7c97 100644 --- a/.cr/team/Editor/Formatting/Wrapping.CSharp.xml +++ b/.cr/team/Editor/Formatting/Wrapping.CSharp.xml @@ -11,11 +11,13 @@ - + + WrapAfter + 4 diff --git a/StgSharp.Common/Collections/CapacityFixedStack.cs b/StgSharp.Common/Collections/CapacityFixedStack.cs index 002e91db..e8389de7 100644 --- a/StgSharp.Common/Collections/CapacityFixedStack.cs +++ b/StgSharp.Common/Collections/CapacityFixedStack.cs @@ -29,6 +29,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; +using System.Threading; namespace StgSharp.Collections { @@ -45,6 +46,8 @@ namespace StgSharp.Collections _index = -1; } + public T? First => Volatile.Read(ref _index) > 0 ? _values[0] : default; + public bool IsEmpty => _index == -1; public int Count => _index + 1; diff --git a/StgSharp.Common/Internal/Intrinsic/MatInterface.cs b/StgSharp.Common/Internal/Intrinsic/MatInterface.cs deleted file mode 100644 index d2033627..00000000 --- a/StgSharp.Common/Internal/Intrinsic/MatInterface.cs +++ /dev/null @@ -1,35 +0,0 @@ -//----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -// file="MatInterface" -// 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.Text; - -namespace StgSharp.Internal.Intrinsic -{ - public interface IMat { } -} diff --git a/StgSharp.Common/Mathematics/Graphic/Matrix44.cs b/StgSharp.Common/Mathematics/Graphic/Matrix44.cs index e747948e..dc37b507 100644 --- a/StgSharp.Common/Mathematics/Graphic/Matrix44.cs +++ b/StgSharp.Common/Mathematics/Graphic/Matrix44.cs @@ -27,14 +27,17 @@ // ----------------------------------------------------------------------- using StgSharp.Mathematics.Numeric; using System; +using System.Collections; +using System.Collections.Generic; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace StgSharp.Mathematics.Graphic { - [StructLayout(LayoutKind.Explicit, Size = 2 * 16 * sizeof(float) + sizeof(bool), Pack = 16)] - public unsafe struct Matrix44 : IEquatable, IMatrix + [CollectionBuilder(builderType:typeof(Matrix44), methodName: nameof(Matrix44.FromSpan))] + [StructLayout(LayoutKind.Explicit, Size = (2 * 16 * sizeof(float)) + sizeof(bool), Pack = 16)] + public unsafe struct Matrix44 : IEquatable, IMatrix, IEnumerable { [FieldOffset(2 * 64 * sizeof(float))] internal bool isTransposed; @@ -160,12 +163,6 @@ namespace StgSharp.Mathematics.Graphic return MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As(ref mat), 16); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe float Det() - { - return 0; - } - public override bool Equals(object? obj) { return obj is Matrix44 x && Equals(x); @@ -176,11 +173,24 @@ namespace StgSharp.Mathematics.Graphic return mat.Equals(other.mat); } + public static Matrix44 FromSpan(ReadOnlySpan rowSpan) + { + Matrix44 mat = new Matrix44(); + + mat.transpose.colum0 = rowSpan[0].vec; + mat.transpose.colum1 = rowSpan[1].vec; + mat.transpose.colum2 = rowSpan[2].vec; + mat.transpose.colum3 = rowSpan[3].vec; + + NativeIntrinsic.Intrinsic.f32_transpose(&mat.transpose, &mat.mat); + mat.isTransposed = false; + return mat; + } + public override int GetHashCode() { - return HashCode.Combine( - mat.colum0.GetHashCode(), mat.colum1.GetHashCode(), mat.colum2.GetHashCode(), - mat.colum3.GetHashCode()); + return HashCode.Combine(mat.colum0.GetHashCode(), mat.colum1.GetHashCode(), mat.colum2.GetHashCode(), + mat.colum3.GetHashCode()); } public override string ToString() @@ -194,11 +204,8 @@ namespace StgSharp.Mathematics.Graphic { if (!isTransposed) { - fixed (ColumnSet4* source = &mat, target = &transpose) - { + fixed (ColumnSet4* source = &mat, target = &transpose) { NativeIntrinsic.Intrinsic.f32_transpose(source, target); - - // InternalIO.Intrinsic.transpose44(source, target); } isTransposed = true; } @@ -207,13 +214,9 @@ namespace StgSharp.Mathematics.Graphic [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe Matrix44 operator -(Matrix44 left, Matrix44 right) { - return new Matrix44 - { - column0 = right.column0 - left.column0, - column1 = right.column1 - left.column1, - column2 = right.column2 - left.column2, - column3 = right.column3 - left.column3 - }; + Matrix44 ret = new(); + NativeIntrinsic.Intrinsic.f32_sub(&left, &right, &ret); + return ret; } public static bool operator !=(Matrix44 left, Matrix44 right) @@ -224,47 +227,37 @@ namespace StgSharp.Mathematics.Graphic [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe Matrix44 operator *(Matrix44 mat, float value) { - return new Matrix44( - mat.mat.colum0 * value, mat.mat.colum1 * value, mat.mat.colum2 * value, - mat.mat.colum3 * value); + return new Matrix44(mat.mat.colum0 * value, mat.mat.colum1 * value, mat.mat.colum2 * value, + mat.mat.colum3 * value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Matrix44 operator *(Matrix44 left, Matrix44 right) { left.InternalTranspose(); - return new Matrix44( - Vector4.Dot(left.transpose.colum0, right.mat.colum0), - Vector4.Dot(left.transpose.colum0, right.mat.colum1), - Vector4.Dot(left.transpose.colum0, right.mat.colum2), - Vector4.Dot(left.transpose.colum0, right.mat.colum3), - - Vector4.Dot(left.transpose.colum1, right.mat.colum0), - Vector4.Dot(left.transpose.colum1, right.mat.colum1), - Vector4.Dot(left.transpose.colum1, right.mat.colum2), - Vector4.Dot(left.transpose.colum1, right.mat.colum3), - - Vector4.Dot(left.transpose.colum2, right.mat.colum0), - Vector4.Dot(left.transpose.colum2, right.mat.colum1), - Vector4.Dot(left.transpose.colum2, right.mat.colum2), - Vector4.Dot(left.transpose.colum2, right.mat.colum3), - - Vector4.Dot(left.transpose.colum3, right.mat.colum0), - Vector4.Dot(left.transpose.colum3, right.mat.colum1), - Vector4.Dot(left.transpose.colum3, right.mat.colum2), - Vector4.Dot(left.transpose.colum3, right.mat.colum3)); + return new Matrix44(Vector4.Dot(left.transpose.colum0, right.mat.colum0), + Vector4.Dot(left.transpose.colum0, right.mat.colum1), + Vector4.Dot(left.transpose.colum0, right.mat.colum2), + Vector4.Dot(left.transpose.colum0, right.mat.colum3), + Vector4.Dot(left.transpose.colum1, right.mat.colum0), + Vector4.Dot(left.transpose.colum1, right.mat.colum1), + Vector4.Dot(left.transpose.colum1, right.mat.colum2), + Vector4.Dot(left.transpose.colum1, right.mat.colum3), + Vector4.Dot(left.transpose.colum2, right.mat.colum0), + Vector4.Dot(left.transpose.colum2, right.mat.colum1), + Vector4.Dot(left.transpose.colum2, right.mat.colum2), + Vector4.Dot(left.transpose.colum2, right.mat.colum3), + Vector4.Dot(left.transpose.colum3, right.mat.colum0), + Vector4.Dot(left.transpose.colum3, right.mat.colum1), + Vector4.Dot(left.transpose.colum3, right.mat.colum2), + Vector4.Dot(left.transpose.colum3, right.mat.colum3)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe Matrix44 operator +(Matrix44 left, Matrix44 right) { - Matrix44 ret = new() - { - column0 = left.column0 + right.column0, - column1 = left.column1 + right.column1, - column2 = left.column2 + right.column2, - column3 = left.column3 + right.column3 - }; + Matrix44 ret = new(); + NativeIntrinsic.Intrinsic.f32_add(&left, &right, &ret); return ret; } @@ -273,5 +266,18 @@ namespace StgSharp.Mathematics.Graphic return left.Equals(right); } + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + ref Vec4 col0 = ref column0; + for (int i = 0; i < 4; i++) { + yield return Unsafe.Add(ref col0, i); + } + } + } } diff --git a/StgSharp.Common/Mathematics/Graphic/Vec4.cs b/StgSharp.Common/Mathematics/Graphic/Vec4.cs index b4186d61..44edf4ae 100644 --- a/StgSharp.Common/Mathematics/Graphic/Vec4.cs +++ b/StgSharp.Common/Mathematics/Graphic/Vec4.cs @@ -36,8 +36,9 @@ using System.Runtime.InteropServices; namespace StgSharp.Mathematics.Graphic { + [CollectionBuilder(builderType:typeof(Vec4), methodName: nameof(Vec4.FromSpan))] [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 16)] - public struct Vec4 : IEquatable, IUnmanagedVector + public unsafe struct Vec4 : IEquatable, IUnmanagedVector { [FieldOffset(0)] internal unsafe fixed float num[4]; @@ -127,11 +128,33 @@ namespace StgSharp.Mathematics.Graphic return left + right; } + public ReadOnlySpan AsSpan() + { + return MemoryMarshal.CreateReadOnlySpan(ref reg.Member(0), 4); + } + public override bool Equals(object obj) { return obj is Vec4 v && v == this; } + public static Vec4 FromSpan(ReadOnlySpan span) + { + return new Vec4 + { + X = span[0], + Y = span[1], + Z = span[2], + W = span[3] + }; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ReadOnlySpan.Enumerator GetEnumerator() + { + return AsSpan().GetEnumerator(); + } + public override int GetHashCode() { return vec.GetHashCode(); @@ -163,11 +186,8 @@ namespace StgSharp.Mathematics.Graphic public static Vec4 operator *(Matrix44 mat, Vec4 vec) { mat.InternalTranspose(); - return new Vec4( - Vector4.Dot(mat.transpose.colum0, vec.vec), - Vector4.Dot(mat.transpose.colum1, vec.vec), - Vector4.Dot(mat.transpose.colum2, vec.vec), - Vector4.Dot(mat.transpose.colum3, vec.vec)); + return new Vec4(Vector4.Dot(mat.transpose.colum0, vec.vec), Vector4.Dot(mat.transpose.colum1, vec.vec), + Vector4.Dot(mat.transpose.colum2, vec.vec), Vector4.Dot(mat.transpose.colum3, vec.vec)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/StgSharp.Common/Mathematics/Linear/IMatrix.cs b/StgSharp.Common/Mathematics/Linear/IMatrix.cs index e19a0f81..f626e927 100644 --- a/StgSharp.Common/Mathematics/Linear/IMatrix.cs +++ b/StgSharp.Common/Mathematics/Linear/IMatrix.cs @@ -30,6 +30,7 @@ using StgSharp.Graphics; using System; using System.Collections.Generic; using System.Numerics; +using System.Runtime.CompilerServices; using System.Text; namespace StgSharp.Mathematics.Numeric diff --git a/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs b/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs index 9ec89dec..5dd527ac 100644 --- a/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs +++ b/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs @@ -47,6 +47,16 @@ namespace StgSharp.Mathematics.Numeric } Matrix ans = Matrix.FromDefault(left.ColumnLength, left.RowLength); long count = (long)left.KernelColumnLength * left.KernelRowLength; + if (count <= 256) + { + MatrixKernel* leftPtr = left.Buffer; + MatrixKernel* rightPtr = right.Buffer; + MatrixKernel* ansPtr = ans.Buffer; + for (int i = 0; i < count; i++) { + NativeIntrinsic.Intrinsic.f32_add(leftPtr + i, rightPtr + i, ansPtr + i); + } + return ans; + } if (count <= 1024) { ReadOnlySpan pool = MatrixParallel.LeadParallel(1); @@ -64,50 +74,14 @@ namespace StgSharp.Mathematics.Numeric } return ans; } - Stack taskGroup = MatrixParallel.PublicTask(left.GetColumnEnumeration(), right.GetColumnEnumeration(), ans.GetColumnEnumeration(), + MatrixParallelHandle taskGroup = MatrixParallel.PublicTask(left.GetColumnEnumeration(), right.GetColumnEnumeration(), ans.GetColumnEnumeration(), (delegate**, MatrixKernel*, MatrixKernel*, void>)NativeIntrinsic.Intrinsic.f32_add); MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep); /* * run parallel */ - return ans; - } - - public static unsafe Matrix Sub(Matrix left, Matrix right) - { - if (left.ColumnLength != right.ColumnLength || left.RowLength != right.RowLength) { - throw new IndexOutOfRangeException("Matrix dimensions must agree."); - } - Matrix ans = Matrix.FromDefault(left.ColumnLength, left.RowLength); - long count = (long)left.KernelColumnLength * left.KernelRowLength; - if (count <= 1024) - { - // TODO: this is very awkward, blocking thread renting, need a better way to handle small tasks - ReadOnlySpan pool = MatrixParallel.LeadParallel(1); - if (pool.Length == 0) - { - /* - * wait - */ - } - MatrixParallel.ReleaseParallelLeadership(ref pool); - MatrixKernel* leftPtr = left.Buffer; - MatrixKernel* rightPtr = right.Buffer; - MatrixKernel* ansPtr = ans.Buffer; - for (int i = 0; i < count; i++) { - NativeIntrinsic.Intrinsic.f32_sub(leftPtr + i, rightPtr + i, ansPtr + i); - } - - // thread. - - return ans; - } - Stack taskGroup = MatrixParallel.PublicTask(left.GetColumnEnumeration(), right.GetColumnEnumeration(), ans.GetColumnEnumeration(), - (delegate**, MatrixKernel*, MatrixKernel*, void>)NativeIntrinsic.Intrinsic.f32_sub); - /* - * run parallel - */ + taskGroup.Dispose(); return ans; } diff --git a/StgSharp.Mathematics/Numeric/MatrixParallel.Await.cs b/StgSharp.Mathematics/Numeric/MatrixParallel.Await.cs new file mode 100644 index 00000000..a64d2b77 --- /dev/null +++ b/StgSharp.Mathematics/Numeric/MatrixParallel.Await.cs @@ -0,0 +1,116 @@ +//----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +// file="MatrixParallel.Await" +// 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.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StgSharp.Mathematics.Numeric +{ + public static partial class MatrixParallel + { + + private static ConcurrentQueue _awaitingLeaderHandle; + + private static volatile int _createGeneration = 0; + private static int _sortState; + + public static MatrixParallelThread[] LeadParallel(int recommendCount) + { + int min = int.Min(recommendCount, _threads.Capacity); + min /= 2; + MatrixParallelThread[] ret; + if (_threads.Count < min) + { + WaitHandle handle = new WaitHandle + { + CreateGeneration = _createGeneration, + LeastCount = min, + BestCount = recommendCount + }; + _awaitingLeaderHandle.Enqueue(handle); + int cycleGeneration = _createGeneration; + while (true) + { + // TODO 排队等待,对前八个按照优先级排序,优先级最高的独占进行等待,其他继续排队 + if (_createGeneration != cycleGeneration) + { + if (Interlocked.Exchange(ref _sortState, 1) == 0) + { + // TODO 排序 + _ = Interlocked.Exchange(ref _sortState, 0); + } else + { + cycleGeneration = _createGeneration; + continue; + } + } + if (_awaitingLeaderHandle.TryPeek(out WaitHandle? p) && p == handle) + { + // get the leader + ret = _threads.PopRange(recommendCount); + _awaitingLeaderHandle.TryDequeue(out _); + break; + } + Thread.Sleep(0); + } + } else + { + // directly get the leader + ret = _threads.PopRange(recommendCount); + } + _ = Interlocked.Increment(ref _createGeneration); + return ret; + } + + public static void ReturnParallelResources(ref MatrixParallelThread[] pool) + { + _threads.PushRange(pool); + pool = null!; + } + + private record class WaitHandle + { + + public int CreateGeneration { get; set; } + + public int LeastCount { get; set; } + + public int BestCount { get; set; } + + public int CurrentPriority(int currentGeneration) + { + return (currentGeneration - CreateGeneration) * (MatrixParallel._threads.Capacity - LeastCount); + } + + } + + } +} diff --git a/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs b/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs index 47622543..eda3cf23 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs @@ -40,10 +40,10 @@ namespace StgSharp.Mathematics.Numeric public static partial class MatrixParallel { - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration source, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration source, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation) where T: unmanaged, INumber { MatrixParallelTaskPackage* package = MatrixParallelFactory.CreateBaseTask(); @@ -66,11 +66,11 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration left, - MatrixSegmentEnumeration right, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration left, + MatrixSegmentEnumeration right, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation) where T: unmanaged, INumber { MatrixParallelTaskPackage* package = MatrixParallelFactory.CreateBaseTask(); @@ -99,11 +99,11 @@ namespace StgSharp.Mathematics.Numeric } // Unary with 1..8 scalars (each scalar is independent generic type) - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration source, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration source, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0) where T: unmanaged, INumber where TScalar0: unmanaged, INumber { @@ -130,12 +130,12 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration source, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0, - TScalar1 s1) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration source, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0, + TScalar1 s1) where T: unmanaged, INumber where TScalar0: unmanaged, INumber where TScalar1: unmanaged, INumber @@ -165,12 +165,12 @@ namespace StgSharp.Mathematics.Numeric } // Binary with 1..8 scalars (each scalar is independent generic type) - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration left, - MatrixSegmentEnumeration right, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration left, + MatrixSegmentEnumeration right, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0) where T: unmanaged, INumber where TScalar0: unmanaged, INumber { @@ -202,13 +202,13 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration source, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0, - TScalar1 s1, - TScalar2 s2) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration source, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0, + TScalar1 s1, + TScalar2 s2) where T: unmanaged, INumber where TScalar0: unmanaged, INumber where TScalar1: unmanaged, INumber @@ -239,13 +239,13 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration left, - MatrixSegmentEnumeration right, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0, - TScalar1 s1) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration left, + MatrixSegmentEnumeration right, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0, + TScalar1 s1) where T: unmanaged, INumber where TScalar0: unmanaged, INumber where TScalar1: unmanaged, INumber @@ -279,14 +279,14 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration source, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0, - TScalar1 s1, - TScalar2 s2, - TScalar3 s3) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration source, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0, + TScalar1 s1, + TScalar2 s2, + TScalar3 s3) where T: unmanaged, INumber where TScalar0: unmanaged, INumber where TScalar1: unmanaged, INumber @@ -319,14 +319,14 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration left, - MatrixSegmentEnumeration right, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0, - TScalar1 s1, - TScalar2 s2) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration left, + MatrixSegmentEnumeration right, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0, + TScalar1 s1, + TScalar2 s2) where T: unmanaged, INumber where TScalar0: unmanaged, INumber where TScalar1: unmanaged, INumber @@ -362,15 +362,15 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration source, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0, - TScalar1 s1, - TScalar2 s2, - TScalar3 s3, - TScalar4 s4) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration source, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0, + TScalar1 s1, + TScalar2 s2, + TScalar3 s3, + TScalar4 s4) where T: unmanaged, INumber where TScalar0: unmanaged, INumber where TScalar1: unmanaged, INumber @@ -405,15 +405,15 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration left, - MatrixSegmentEnumeration right, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0, - TScalar1 s1, - TScalar2 s2, - TScalar3 s3) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration left, + MatrixSegmentEnumeration right, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0, + TScalar1 s1, + TScalar2 s2, + TScalar3 s3) where T: unmanaged, INumber where TScalar0: unmanaged, INumber where TScalar1: unmanaged, INumber @@ -451,16 +451,16 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration source, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0, - TScalar1 s1, - TScalar2 s2, - TScalar3 s3, - TScalar4 s4, - TScalar5 s5) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration source, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0, + TScalar1 s1, + TScalar2 s2, + TScalar3 s3, + TScalar4 s4, + TScalar5 s5) where T: unmanaged, INumber where TScalar0: unmanaged, INumber where TScalar1: unmanaged, INumber @@ -497,16 +497,16 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration left, - MatrixSegmentEnumeration right, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0, - TScalar1 s1, - TScalar2 s2, - TScalar3 s3, - TScalar4 s4) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration left, + MatrixSegmentEnumeration right, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0, + TScalar1 s1, + TScalar2 s2, + TScalar3 s3, + TScalar4 s4) where T: unmanaged, INumber where TScalar0: unmanaged, INumber where TScalar1: unmanaged, INumber @@ -546,17 +546,17 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration source, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0, - TScalar1 s1, - TScalar2 s2, - TScalar3 s3, - TScalar4 s4, - TScalar5 s5, - TScalar6 s6) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration source, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0, + TScalar1 s1, + TScalar2 s2, + TScalar3 s3, + TScalar4 s4, + TScalar5 s5, + TScalar6 s6) where T: unmanaged, INumber where TScalar0: unmanaged, INumber where TScalar1: unmanaged, INumber @@ -595,17 +595,17 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration left, - MatrixSegmentEnumeration right, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0, - TScalar1 s1, - TScalar2 s2, - TScalar3 s3, - TScalar4 s4, - TScalar5 s5) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration left, + MatrixSegmentEnumeration right, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0, + TScalar1 s1, + TScalar2 s2, + TScalar3 s3, + TScalar4 s4, + TScalar5 s5) where T: unmanaged, INumber where TScalar0: unmanaged, INumber where TScalar1: unmanaged, INumber @@ -647,18 +647,18 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration source, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0, - TScalar1 s1, - TScalar2 s2, - TScalar3 s3, - TScalar4 s4, - TScalar5 s5, - TScalar6 s6, - TScalar7 s7) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration source, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0, + TScalar1 s1, + TScalar2 s2, + TScalar3 s3, + TScalar4 s4, + TScalar5 s5, + TScalar6 s6, + TScalar7 s7) where T: unmanaged, INumber where TScalar0: unmanaged, INumber where TScalar1: unmanaged, INumber @@ -699,18 +699,18 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration left, - MatrixSegmentEnumeration right, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0, - TScalar1 s1, - TScalar2 s2, - TScalar3 s3, - TScalar4 s4, - TScalar5 s5, - TScalar6 s6) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration left, + MatrixSegmentEnumeration right, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0, + TScalar1 s1, + TScalar2 s2, + TScalar3 s3, + TScalar4 s4, + TScalar5 s5, + TScalar6 s6) where T: unmanaged, INumber where TScalar0: unmanaged, INumber where TScalar1: unmanaged, INumber @@ -754,19 +754,19 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - public static unsafe Stack PublicTask( - MatrixSegmentEnumeration left, - MatrixSegmentEnumeration right, - MatrixSegmentEnumeration ans, - delegate**, MatrixKernel*, MatrixKernel*, void> Operation, - TScalar0 s0, - TScalar1 s1, - TScalar2 s2, - TScalar3 s3, - TScalar4 s4, - TScalar5 s5, - TScalar6 s6, - TScalar7 s7) + public static unsafe MatrixParallelHandle PublicTask( + MatrixSegmentEnumeration left, + MatrixSegmentEnumeration right, + MatrixSegmentEnumeration ans, + delegate**, MatrixKernel*, MatrixKernel*, void> Operation, + TScalar0 s0, + TScalar1 s1, + TScalar2 s2, + TScalar3 s3, + TScalar4 s4, + TScalar5 s5, + TScalar6 s6, + TScalar7 s7) where T: unmanaged, INumber where TScalar0: unmanaged, INumber where TScalar1: unmanaged, INumber @@ -812,7 +812,7 @@ namespace StgSharp.Mathematics.Numeric return PublicTaskPrivate(package); } - private static unsafe Stack PublicTaskPrivate(MatrixParallelTaskPackage* package) + private static unsafe MatrixParallelHandle PublicTaskPrivate(MatrixParallelTaskPackage* package) where T: unmanaged, INumber { int primCount = package->PrimCount; @@ -820,15 +820,21 @@ namespace StgSharp.Mathematics.Numeric int tileWidth = (1024 / secCount) + 1; int tileCount = (primCount + tileWidth - 1) / tileWidth; - ReadOnlySpan pool = LeadParallel(tileCount); + MatrixParallelThread[] pool = LeadParallel(tileCount); - int threadCount = pool.Length; if (pool.Length == 0) { /* * wait until has enough threads */ } + MatrixParallelHandle handle = new MatrixParallelHandle(pool); + if (handle.Wraps.Count() == 1) + { + handle.Wraps.First().WrapTask = (MatrixParallelTaskPackageNonGeneric*)package; + return handle; + } + int threadCount = pool.Length; int tilePerThreadLess = tileCount / threadCount; // tiles per thread without extra slice int columnAfterBaseTile = tileCount % threadCount * tileWidth; // tile sliced into columns int extraColumnPerThread = columnAfterBaseTile / threadCount; @@ -837,13 +843,13 @@ namespace StgSharp.Mathematics.Numeric int total = primCount; Stack taskBunch = new Stack(threadCount); MatrixParallelTaskPackage* current = package; - foreach (MatrixParallelThread thread in pool) + foreach (MatrixParallelWrap wrap in handle.Wraps) { bool hasSlice = columnAfterBaseTile > 0; bool isLargeSlice = extraColumnCount > 0; // count tiles for wrap - int wrapWidth =/**/ 3/* wrap!.WrapTaskCapacity/**/; + int wrapWidth = wrap!.WrapTaskCapacity/**/; int columnFromSlicingCount = (hasSlice ? extraColumnPerThread : 0) * wrapWidth; int baseColumn = wrapWidth * tilePerThreadLess * tileWidth; int columnInWrap = baseColumn + columnFromSlicingCount + (isLargeSlice ? 1 : 0); @@ -869,10 +875,7 @@ namespace StgSharp.Mathematics.Numeric total -= columnInWrap; // set to wrap and push - // wrap.Tasks.Enqueue((IntPtr)current); - - // taskBunch.Push(wrap); - + wrap.WrapTask = (MatrixParallelTaskPackageNonGeneric*)current; if (total <= 0) { @@ -882,7 +885,7 @@ namespace StgSharp.Mathematics.Numeric current->PrimTileOffset += columnInWrap; } - return taskBunch; + return handle; } } diff --git a/StgSharp.Mathematics/Numeric/MatrixParallel.cs b/StgSharp.Mathematics/Numeric/MatrixParallel.cs index 0ff8b4c9..91d876ef 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallel.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallel.cs @@ -27,6 +27,7 @@ // ----------------------------------------------------------------------- using StgSharp.Collections; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; @@ -74,46 +75,18 @@ namespace StgSharp.Mathematics.Numeric for (int i = 0; i < count; i++) { _threads.Push(new()); } + _awaitingLeaderHandle = new ConcurrentQueue(); IsInitialized = true; } - public static void LaunchParallel(IEnumerable wraps, SleepMode afterWork) + public static void LaunchParallel(MatrixParallelHandle handle, SleepMode afterWork) { RemainThreadCount = _threads.Count; _AfterWork = (ThreadPriority)afterWork; - ResetThreadCount(); - foreach (MatrixParallelWrap w in wraps) { + foreach (MatrixParallelWrap w in handle.Wraps) { w.SchedulerReset.Set(); } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ResetThreadCount() - { - RemainThreadCount = _threads.Count; - } - - #region wrap field - - public static MatrixParallelThread[] LeadParallel(int recommendCount) - { -#if NET9_0_OR_GREATER -#else - Monitor.Enter(_lock); -#endif - - return _threads.PopRange(recommendCount); - } - - public static void ReleaseParallelLeadership(ref MatrixParallelThread[] pool) - { -#if NET9_0_OR_GREATER -#else - Monitor.Exit(_lock); -#endif - pool = null!; - } - - #endregion } } \ No newline at end of file diff --git a/StgSharp.Mathematics/Numeric/MatrixParallelTask.cs b/StgSharp.Mathematics/Numeric/MatrixParallelHandle.cs similarity index 100% rename from StgSharp.Mathematics/Numeric/MatrixParallelTask.cs rename to StgSharp.Mathematics/Numeric/MatrixParallelHandle.cs diff --git a/StgSharp.Mathematics/Numeric/MatrixParallelPool.cs b/StgSharp.Mathematics/Numeric/MatrixParallelPool.cs index c5efa236..8553fcfb 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallelPool.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallelPool.cs @@ -78,6 +78,17 @@ namespace StgSharp.Mathematics.Numeric } } + internal IEnumerable Wraps + { + get + { + if (_disposed) { + throw new ObjectDisposedException(typeof(MatrixParallelHandle).Name); + } + return _wraps; + } + } + internal ReadOnlySpan ThreadsUnsafe { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -91,10 +102,16 @@ namespace StgSharp.Mathematics.Numeric if (_disposed) { return; } - MatrixParallel.ReleaseParallelLeadership(ref _threads); + MatrixParallel.ReturnParallelResources(ref _threads); _disposed = true; } + public MatrixParallelThread GetLeader() + { + Threads[0].Role = 2; + return Threads[0]; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static (int count_3, int count_4) FastDecompose(int c) { @@ -139,11 +156,22 @@ namespace StgSharp.Mathematics.Numeric int count = _threads.Length; if (count < 6) { - MatrixParallelWrap wrap = new MatrixParallelWrap(_threads); + MatrixParallelWrap wrap = new MatrixParallelWrap(_threads, 0, count); _wraps = [ wrap ]; } (int c3,int c4) = FastDecompose(_threads.Length); _wraps = new(c3 + c4); + int begin = 0; + for (int i = 0; i < c3; i++) + { + _wraps.Push(new MatrixParallelWrap(_threads, begin, 3)); + begin += 3; + } + for (int i = 0; i < c4; i++) + { + _wraps.Push(new MatrixParallelWrap(_threads, begin, 4)); + begin += 4; + } } } diff --git a/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs b/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs index 62e6b10e..e123e41a 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs @@ -118,30 +118,27 @@ namespace StgSharp.Mathematics.Numeric private unsafe void MatrixParallelWorker() { // Thread self = Thread.CurrentThread; - do + _resetEvent.Wait(); + _resetEvent.Reset(); + _managedThread.Priority = ThreadPriority.Highest; + switch (Role) { - _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); + 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); + break; + case 2://leader, error because leader should be at outer thread but not here + break; + default: + break; + } + _managedThread.Priority = AfterWork; } #region wrap belong @@ -150,10 +147,10 @@ namespace StgSharp.Mathematics.Numeric internal Queue Tasks { get; } = []; - internal int Role + public int Role { get; - set + internal set { if ((Role & (~3u)) == 0) { diff --git a/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs b/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs index 16bb7bfb..e1d80fbd 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallelWrap.cs @@ -42,10 +42,12 @@ namespace StgSharp.Mathematics.Numeric private readonly MatrixParallelThread[] _threads; private int _begin; - internal MatrixParallelWrap(MatrixParallelThread[] threads) + internal MatrixParallelWrap(MatrixParallelThread[] threads, int begin, int count) { _threads = threads; + _begin = begin; Count = threads.Length; + _threads[_begin].Role = 1; } public MatrixParallelWrap() @@ -90,7 +92,7 @@ namespace StgSharp.Mathematics.Numeric int primAverage = primCount / Count; int secAverage = secCount / Count; bool shouldSliceSec = secAverage > 512; - for (int i = 0; i < Count; i++) + for (int i = _begin; i < _begin + Count; i++) { Queue tasks = _threads[i].Tasks; MatrixParallelTaskPackageNonGeneric* subTask = MatrixParallelFactory.FromExistPackage(taskPackage); diff --git a/StgSharpDebug/Program.cs b/StgSharpDebug/Program.cs index 38db3ab8..cf61ef1f 100644 --- a/StgSharpDebug/Program.cs +++ b/StgSharpDebug/Program.cs @@ -32,6 +32,7 @@ using StgSharp.Graphics; using StgSharp.HighPerformance; using StgSharp.HighPerformance.Memory; using StgSharp.Mathematics; +using StgSharp.Mathematics.Graphic; using StgSharp.Mathematics.Numeric; using StgSharp.Model.Step; using StgSharp.MVVM; @@ -61,6 +62,7 @@ namespace StgSharp { World.Init(); + // New test with synchronized start: // - 8 producer threads, each pushing 1000 unique integers // - 8 consumer threads, each attempting to pop 1000 times