diff --git a/StgSharp.Common/HighPerformance/Memory/ConcurrentBufferStack.cs b/StgSharp.Common/HighPerformance/Memory/ConcurrentBufferStack.cs index 07246f3c..e56c5e2d 100644 --- a/StgSharp.Common/HighPerformance/Memory/ConcurrentBufferStack.cs +++ b/StgSharp.Common/HighPerformance/Memory/ConcurrentBufferStack.cs @@ -87,6 +87,11 @@ namespace StgSharp.HighPerformance.Memory private readonly BufferExpansionLock _lock = new(); private ulong _count; + public ConcurrentBufferStack() + { + AllocateBuffer(4); + } + public ConcurrentBufferStack(int capacity) { if (capacity <= 0) { diff --git a/StgSharp.Common/Mathematics/Linear/IFixedVector.cs b/StgSharp.Common/Mathematics/Linear/IFixedVector.cs index 078dd1a4..16cb4df6 100644 --- a/StgSharp.Common/Mathematics/Linear/IFixedVector.cs +++ b/StgSharp.Common/Mathematics/Linear/IFixedVector.cs @@ -1,33 +1,33 @@ //----------------------------------------------------------------------- -//----------------------------------------------------------------------- -// file="IFixedVector.cs" -// Project: StgSharp -// AuthorGroup: Nitload Space -// Copyright (c) Nitload Space. All rights reserved. +// ----------------------------------------------------------------------- +// file="IFixedVector.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: +// 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 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. +// 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; @@ -38,7 +38,7 @@ using System.Threading.Tasks; namespace StgSharp.Mathematics { - public interface IFixedVector where TSelf: struct, IFixedVector + public interface IFixedVector where TSelf: unmanaged, IFixedVector { public static abstract TSelf Zero { get; } diff --git a/StgSharp.Common/Mathematics/Linear/MatrixParallel.Task.cs b/StgSharp.Common/Mathematics/Linear/MatrixParallel.Task.cs new file mode 100644 index 00000000..b4a1576c --- /dev/null +++ b/StgSharp.Common/Mathematics/Linear/MatrixParallel.Task.cs @@ -0,0 +1,107 @@ +//----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +// file="MatrixParallel.Task.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 StgSharp.HighPerformance; + +using System; +using System.Drawing; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace StgSharp.Mathematics +{ + /// + /// Matrix parallel computation task structure with scalar data packet support Uses type- + /// erased design for thread pool compatibility + /// + [StructLayout(LayoutKind.Explicit, Size = 48)] + public unsafe struct MatrixParallelTask + { + + public const int SizeofConstantParameter = sizeof(ulong); + public const int SizeOfTask = 48; + + [FieldOffset(0)] public MatrixKernel* left; + [FieldOffset(8)] public MatrixKernel* result; + [FieldOffset(16)] public MatrixKernel* right; + [FieldOffset(24)] public int scalerCount; + [FieldOffset(32)] public IntPtr executionHandle; + + /// + /// Pointer to the scalar data packet containing up to 8 parameters Each parameter is + /// stored as ulong (8 bytes) for type erasure + /// + [FieldOffset(40)] public nint scalerDataPacket; + + /// + /// Execute the task using type-erased function pointer + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly void Execute() + { + if (scalerCount == 0) + { + ((delegate*)executionHandle)(left, right, result); + } else + { + ((delegate*)executionHandle)(left, right, result, (void*)scalerDataPacket); + } + } + + } + + /// + /// Scalar data packet for storing up to 8 parameters as type-erased ulong values Used to + /// separate scalar data allocation from task allocation + /// + public unsafe struct ScalarDataPacket + { + + public const int MaxScalarCount = 8; + public const int PacketSize = 64; + + private fixed ulong Value[8]; + + public ScalarDataPacket() + { + Unsafe.SkipInit(out this); + } + + public ref T GetScalerRef(int index) where T: unmanaged, INumber + { + if (index is < 0 or >= MaxScalarCount) { + throw new IndexOutOfRangeException("ScalarDataPacket index out of range"); + } + return ref Unsafe.As(ref Value[index]); + } + + } +} diff --git a/StgSharp.Common/Mathematics/Linear/MatrixParallel.TaskFactory.cs b/StgSharp.Common/Mathematics/Linear/MatrixParallel.TaskFactory.cs new file mode 100644 index 00000000..687f53d7 --- /dev/null +++ b/StgSharp.Common/Mathematics/Linear/MatrixParallel.TaskFactory.cs @@ -0,0 +1,738 @@ +//----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +// file="MatrixParallel.TaskFactory.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 StgSharp.HighPerformance; +using StgSharp.HighPerformance.Memory; +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace StgSharp.Mathematics +{ + /// + /// Factory for creating and managing MatrixParallelTask instances with pooled allocation Uses + /// separate SLAB allocators for tasks and scalar data packets + /// + public static unsafe class MatrixParallelTaskFactory + { + + private static readonly SlabAllocator ScalarPacketAllocator = + SlabAllocator.Create(1024, SlabBufferLayout.Chunked, true); + + // SLAB allocators for pooled allocation + private static readonly SlabAllocator TaskAllocator = + SlabAllocator.Create(2048, SlabBufferLayout.Chunked, true); + + /// + /// Create a task with no scalar parameters + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static MatrixTaskHandle CreateTask( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle) + { + nuint taskPtr = TaskAllocator.Allocate(); + MatrixParallelTask* task = (MatrixParallelTask*)taskPtr; + + task->left = left; + task->right = right; + task->result = result; + task->executionHandle = executionHandle; + task->scalerCount = 0; + task->scalerDataPacket = 0; // null pointer + + return new MatrixTaskHandle(task, null, false); + } + + /// + /// Create a task with 1 scalar parameter + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static MatrixTaskHandle CreateTask( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + T0 scaler0) + where T0: unmanaged, INumber + { + return CreateTaskInternal(left, right, result, executionHandle, 1, &InitializePacket, scaler0); + } + + /// + /// Create a task with 2 scalar parameters + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static MatrixTaskHandle CreateTask( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + T0 scaler0, + T1 scaler1) + where T0: unmanaged, INumber + where T1: unmanaged, INumber + { + return CreateTaskInternal( + left, right, result, executionHandle, 2, &InitializePacket, scaler0, scaler1); + } + + /// + /// Create a task with 3 scalar parameters + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static MatrixTaskHandle CreateTask( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + T0 scaler0, + T1 scaler1, + T2 scaler2) + where T0: unmanaged, INumber + where T1: unmanaged, INumber + where T2: unmanaged, INumber + { + return CreateTaskInternal( + left, right, result, executionHandle, 3, &InitializePacket, scaler0, scaler1, scaler2); + } + + /// + /// Create a task with 4 scalar parameters + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static MatrixTaskHandle CreateTask( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + T0 scaler0, + T1 scaler1, + T2 scaler2, + T3 scaler3) + where T0: unmanaged, INumber + where T1: unmanaged, INumber + where T2: unmanaged, INumber + where T3: unmanaged, INumber + { + return CreateTaskInternal( + left, right, result, executionHandle, 4, &InitializePacket, scaler0, scaler1, scaler2, + scaler3); + } + + /// + /// Create a task with 5 scalar parameters + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static MatrixTaskHandle CreateTask( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + T0 scaler0, + T1 scaler1, + T2 scaler2, + T3 scaler3, + T4 scaler4) + where T0: unmanaged, INumber + where T1: unmanaged, INumber + where T2: unmanaged, INumber + where T3: unmanaged, INumber + where T4: unmanaged, INumber + { + return CreateTaskInternal( + left, right, result, executionHandle, 5, &InitializePacket, scaler0, scaler1, + scaler2, scaler3, scaler4); + } + + /// + /// Create a task with 6 scalar parameters + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static MatrixTaskHandle CreateTask( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + T0 scaler0, + T1 scaler1, + T2 scaler2, + T3 scaler3, + T4 scaler4, + T5 scaler5) + where T0: unmanaged, INumber + where T1: unmanaged, INumber + where T2: unmanaged, INumber + where T3: unmanaged, INumber + where T4: unmanaged, INumber + where T5: unmanaged, INumber + { + return CreateTaskInternal( + left, right, result, executionHandle, 6, &InitializePacket, scaler0, scaler1, + scaler2, scaler3, scaler4, scaler5); + } + + /// + /// Create a task with 7 scalar parameters + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static MatrixTaskHandle CreateTask( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + T0 scaler0, + T1 scaler1, + T2 scaler2, + T3 scaler3, + T4 scaler4, + T5 scaler5, + T6 scaler6) + where T0: unmanaged, INumber + where T1: unmanaged, INumber + where T2: unmanaged, INumber + where T3: unmanaged, INumber + where T4: unmanaged, INumber + where T5: unmanaged, INumber + where T6: unmanaged, INumber + { + return CreateTaskInternal( + left, right, result, executionHandle, 7, &InitializePacket, scaler0, + scaler1, scaler2, scaler3, scaler4, scaler5, scaler6); + } + + /// + /// Create a task with 8 scalar parameters (maximum) + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static MatrixTaskHandle CreateTask( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + T0 scaler0, + T1 scaler1, + T2 scaler2, + T3 scaler3, + T4 scaler4, + T5 scaler5, + T6 scaler6, + T7 scaler7) + where T0: unmanaged, INumber + where T1: unmanaged, INumber + where T2: unmanaged, INumber + where T3: unmanaged, INumber + where T4: unmanaged, INumber + where T5: unmanaged, INumber + where T6: unmanaged, INumber + where T7: unmanaged, INumber + { + return CreateTaskInternal( + left, right, result, executionHandle, 8, &InitializePacket, scaler0, + scaler1, scaler2, scaler3, scaler4, scaler5, scaler6, scaler7); + } + + /// + /// Get allocation statistics for monitoring pool usage + /// + public static (long TaskCount, long PacketCount, long TotalMemory) GetStatistics() + { + // Note: This would need to be implemented in SlabAllocator to get actual statistics + // For now, return placeholder values + return (0, 0, 0); + } + + /// + /// Clean up all allocators (call on application shutdown) + /// + public static void Shutdown() + { + TaskAllocator?.Dispose(); + ScalarPacketAllocator?.Dispose(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void AllocateTaskAndPacket( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + int scalerCount, + out MatrixParallelTask* task, + out ScalarDataPacket* packet) + { + if (scalerCount is < 1 or > ScalarDataPacket.MaxScalarCount) { + throw new ArgumentOutOfRangeException(nameof(scalerCount)); + } + + // Allocate task + nuint taskPtr = TaskAllocator.Allocate(); + task = (MatrixParallelTask*)taskPtr; + + // Allocate scalar packet + nuint packetPtr = ScalarPacketAllocator.Allocate(); + packet = (ScalarDataPacket*)packetPtr; + + // Initialize task + task->left = left; + task->right = right; + task->result = result; + task->executionHandle = executionHandle; + task->scalerCount = scalerCount; + + // Clear packet memory + Unsafe.InitBlock(packet, 0, ScalarDataPacket.PacketSize); + } + + /// + /// Internal helper for creating tasks with scalar packets + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static MatrixTaskHandle CreateTaskInternal( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + int scalerCount, + delegate* packetInitializer, + T0 param0) + where T0: unmanaged + { + AllocateTaskAndPacket( + left, right, result, executionHandle, scalerCount, out MatrixParallelTask* task, + out ScalarDataPacket* packet); + packetInitializer(packet, param0); + task->scalerDataPacket = (nint)packet; + return new MatrixTaskHandle(task, packet, true); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static MatrixTaskHandle CreateTaskInternal( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + int scalerCount, + delegate* packetInitializer, + T0 param0, + T1 param1) + where T0: unmanaged + where T1: unmanaged + { + AllocateTaskAndPacket( + left, right, result, executionHandle, scalerCount, out MatrixParallelTask* task, + out ScalarDataPacket* packet); + packetInitializer(packet, param0, param1); + task->scalerDataPacket = (nint)packet; + return new MatrixTaskHandle(task, packet, true); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static MatrixTaskHandle CreateTaskInternal( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + int scalerCount, + delegate* packetInitializer, + T0 param0, + T1 param1, + T2 param2) + where T0: unmanaged + where T1: unmanaged + where T2: unmanaged + { + AllocateTaskAndPacket( + left, right, result, executionHandle, scalerCount, out MatrixParallelTask* task, + out ScalarDataPacket* packet); + packetInitializer(packet, param0, param1, param2); + task->scalerDataPacket = (nint)packet; + return new MatrixTaskHandle(task, packet, true); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static MatrixTaskHandle CreateTaskInternal( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + int scalerCount, + delegate* packetInitializer, + T0 param0, + T1 param1, + T2 param2, + T3 param3) + where T0: unmanaged + where T1: unmanaged + where T2: unmanaged + where T3: unmanaged + { + AllocateTaskAndPacket( + left, right, result, executionHandle, scalerCount, out MatrixParallelTask* task, + out ScalarDataPacket* packet); + packetInitializer(packet, param0, param1, param2, param3); + task->scalerDataPacket = (nint)packet; + return new MatrixTaskHandle(task, packet, true); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static MatrixTaskHandle CreateTaskInternal( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + int scalerCount, + delegate* packetInitializer, + T0 param0, + T1 param1, + T2 param2, + T3 param3, + T4 param4) + where T0: unmanaged + where T1: unmanaged + where T2: unmanaged + where T3: unmanaged + where T4: unmanaged + { + AllocateTaskAndPacket( + left, right, result, executionHandle, scalerCount, out MatrixParallelTask* task, + out ScalarDataPacket* packet); + packetInitializer(packet, param0, param1, param2, param3, param4); + task->scalerDataPacket = (nint)packet; + return new MatrixTaskHandle(task, packet, true); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static MatrixTaskHandle CreateTaskInternal( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + int scalerCount, + delegate* packetInitializer, + T0 param0, + T1 param1, + T2 param2, + T3 param3, + T4 param4, + T5 param5) + where T0: unmanaged + where T1: unmanaged + where T2: unmanaged + where T3: unmanaged + where T4: unmanaged + where T5: unmanaged + { + AllocateTaskAndPacket( + left, right, result, executionHandle, scalerCount, out MatrixParallelTask* task, + out ScalarDataPacket* packet); + packetInitializer(packet, param0, param1, param2, param3, param4, param5); + task->scalerDataPacket = (nint)packet; + return new MatrixTaskHandle(task, packet, true); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static MatrixTaskHandle CreateTaskInternal( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + int scalerCount, + delegate* packetInitializer, + T0 param0, + T1 param1, + T2 param2, + T3 param3, + T4 param4, + T5 param5, + T6 param6) + where T0: unmanaged + where T1: unmanaged + where T2: unmanaged + where T3: unmanaged + where T4: unmanaged + where T5: unmanaged + where T6: unmanaged + { + AllocateTaskAndPacket( + left, right, result, executionHandle, scalerCount, out MatrixParallelTask* task, + out ScalarDataPacket* packet); + packetInitializer(packet, param0, param1, param2, param3, param4, param5, param6); + task->scalerDataPacket = (nint)packet; + return new MatrixTaskHandle(task, packet, true); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static MatrixTaskHandle CreateTaskInternal( + MatrixKernel* left, + MatrixKernel* right, + MatrixKernel* result, + IntPtr executionHandle, + int scalerCount, + delegate* packetInitializer, + T0 param0, + T1 param1, + T2 param2, + T3 param3, + T4 param4, + T5 param5, + T6 param6, + T7 param7) + where T0: unmanaged + where T1: unmanaged + where T2: unmanaged + where T3: unmanaged + where T4: unmanaged + where T5: unmanaged + where T6: unmanaged + where T7: unmanaged + { + AllocateTaskAndPacket( + left, right, result, executionHandle, scalerCount, out MatrixParallelTask* task, + out ScalarDataPacket* packet); + packetInitializer(packet, param0, param1, param2, param3, param4, param5, param6, param7); + task->scalerDataPacket = (nint)packet; + return new MatrixTaskHandle(task, packet, true); + } + + // Static packet initializer functions + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void InitializePacket(ScalarDataPacket* packet, T0 s0) where T0: unmanaged, INumber + { + packet->GetScalerRef(0) = s0; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void InitializePacket(ScalarDataPacket* packet, T0 s0, T1 s1) + where T0: unmanaged, INumber + where T1: unmanaged, INumber + { + packet->GetScalerRef(0) = s0; + packet->GetScalerRef(1) = s1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void InitializePacket(ScalarDataPacket* packet, T0 s0, T1 s1, T2 s2) + where T0: unmanaged, INumber + where T1: unmanaged, INumber + where T2: unmanaged, INumber + { + packet->GetScalerRef(0) = s0; + packet->GetScalerRef(1) = s1; + packet->GetScalerRef(2) = s2; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void InitializePacket(ScalarDataPacket* packet, T0 s0, T1 s1, T2 s2, T3 s3) + where T0: unmanaged, INumber + where T1: unmanaged, INumber + where T2: unmanaged, INumber + where T3: unmanaged, INumber + { + packet->GetScalerRef(0) = s0; + packet->GetScalerRef(1) = s1; + packet->GetScalerRef(2) = s2; + packet->GetScalerRef(3) = s3; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void InitializePacket( + ScalarDataPacket* packet, + T0 s0, + T1 s1, + T2 s2, + T3 s3, + T4 s4) + where T0: unmanaged, INumber + where T1: unmanaged, INumber + where T2: unmanaged, INumber + where T3: unmanaged, INumber + where T4: unmanaged, INumber + { + packet->GetScalerRef(0) = s0; + packet->GetScalerRef(1) = s1; + packet->GetScalerRef(2) = s2; + packet->GetScalerRef(3) = s3; + packet->GetScalerRef(4) = s4; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void InitializePacket( + ScalarDataPacket* packet, + T0 s0, + T1 s1, + T2 s2, + T3 s3, + T4 s4, + T5 s5) + where T0: unmanaged, INumber + where T1: unmanaged, INumber + where T2: unmanaged, INumber + where T3: unmanaged, INumber + where T4: unmanaged, INumber + where T5: unmanaged, INumber + { + packet->GetScalerRef(0) = s0; + packet->GetScalerRef(1) = s1; + packet->GetScalerRef(2) = s2; + packet->GetScalerRef(3) = s3; + packet->GetScalerRef(4) = s4; + packet->GetScalerRef(5) = s5; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void InitializePacket( + ScalarDataPacket* packet, + T0 s0, + T1 s1, + T2 s2, + T3 s3, + T4 s4, + T5 s5, + T6 s6) + where T0: unmanaged, INumber + where T1: unmanaged, INumber + where T2: unmanaged, INumber + where T3: unmanaged, INumber + where T4: unmanaged, INumber + where T5: unmanaged, INumber + where T6: unmanaged, INumber + { + packet->GetScalerRef(0) = s0; + packet->GetScalerRef(1) = s1; + packet->GetScalerRef(2) = s2; + packet->GetScalerRef(3) = s3; + packet->GetScalerRef(4) = s4; + packet->GetScalerRef(5) = s5; + packet->GetScalerRef(6) = s6; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void InitializePacket( + ScalarDataPacket* packet, + T0 s0, + T1 s1, + T2 s2, + T3 s3, + T4 s4, + T5 s5, + T6 s6, + T7 s7) + where T0: unmanaged, INumber + where T1: unmanaged, INumber + where T2: unmanaged, INumber + where T3: unmanaged, INumber + where T4: unmanaged, INumber + where T5: unmanaged, INumber + where T6: unmanaged, INumber + where T7: unmanaged, INumber + { + packet->GetScalerRef(0) = s0; + packet->GetScalerRef(1) = s1; + packet->GetScalerRef(2) = s2; + packet->GetScalerRef(3) = s3; + packet->GetScalerRef(4) = s4; + packet->GetScalerRef(5) = s5; + packet->GetScalerRef(6) = s6; + packet->GetScalerRef(7) = s7; + } + + /// + /// Task handle containing both task and scalar packet pointers + /// + public readonly struct MatrixTaskHandle : IDisposable + { + + internal readonly ScalarDataPacket* ScalarPacketPtr; + internal readonly MatrixParallelTask* TaskPtr; + public readonly bool HasScalarPacket; + + internal MatrixTaskHandle( + MatrixParallelTask* taskPtr, + ScalarDataPacket* scalarPacketPtr, + bool hasScalarPacket) + { + TaskPtr = taskPtr; + ScalarPacketPtr = scalarPacketPtr; + HasScalarPacket = hasScalarPacket; + } + + public bool IsValid => TaskPtr != null; + + /// + /// Release the allocated resources back to pools + /// + public void Dispose() + { + if (IsValid) + { + TaskAllocator.Free((nuint)TaskPtr); + if (HasScalarPacket && ScalarPacketPtr != null) { + ScalarPacketAllocator.Free((nuint)ScalarPacketPtr); + } + } + } + + /// + /// Execute the task + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly void Execute() + { + if (!IsValid) { + throw new InvalidOperationException("Invalid task handle"); + } + + TaskPtr->Execute(); + } + + /// + /// Execute the task and automatically dispose the handle + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteAndDispose() + { + try + { + Execute(); + } + finally + { + Dispose(); + } + } + + } + + } +} \ No newline at end of file diff --git a/StgSharp.Common/Mathematics/Linear/MatrixParallelTask.cs b/StgSharp.Common/Mathematics/Linear/MatrixParallel.cs similarity index 56% rename from StgSharp.Common/Mathematics/Linear/MatrixParallelTask.cs rename to StgSharp.Common/Mathematics/Linear/MatrixParallel.cs index c1992c9b..04429612 100644 --- a/StgSharp.Common/Mathematics/Linear/MatrixParallelTask.cs +++ b/StgSharp.Common/Mathematics/Linear/MatrixParallel.cs @@ -1,6 +1,6 @@ //----------------------------------------------------------------------- // ----------------------------------------------------------------------- -// file="MatrixParallelTask.cs" +// file="MatrixParallel.cs" // Project: StgSharp // AuthorGroup: Nitload Space // Copyright (c) Nitload Space. All rights reserved. @@ -28,45 +28,61 @@ // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- -using StgSharp.HighPerformance; +using StgSharp.HighPerformance.Memory; + using System; using System.Collections.Generic; -using System.Drawing; using System.IO.Pipes; using System.Linq; -using System.Numerics; -using System.Runtime.InteropServices; +using System.Reflection.Metadata; using System.Text; using System.Threading; +using System.Threading.Channels; using System.Threading.Tasks; namespace StgSharp.Mathematics { - [StructLayout(LayoutKind.Explicit)] - internal unsafe struct MatrixParallelTask + internal static class MatrixParallel { - [FieldOffset(0)] public MatrixKernel* left; - [FieldOffset(8)] public MatrixKernel* result; - [FieldOffset(16)]public MatrixKernel* right; - [FieldOffset(24)]public int constCount; - [FieldOffset(32)]public IntPtr executionHandle; + private static Thread[] _threads; + private static Channel _taskChannel = Channel.CreateUnbounded(); + private static int _paraState; - } + public static void Init() + { + int count = Environment.ProcessorCount - 4; + count = count < 0 ? 1 : count; + _threads = new Thread[count]; + Interlocked.Exchange(ref _paraState, 1); + for (int i = 0; i < count; i++) + { + _threads[i] = new(MatrixParallelCycle) + { + IsBackground = true + }; + _threads[i].Start(); + } + } - [StructLayout(LayoutKind.Explicit)] - internal unsafe struct MatrixParallelTask where T: unmanaged, INumber - { + public static void PublishTask() { } - [FieldOffset(0)] public MatrixKernel* left; - [FieldOffset(8)] public MatrixKernel* result; - [FieldOffset(16)]public MatrixKernel* right; - [FieldOffset(24)]public int constCount; - [FieldOffset(32)] public IntPtr executionHandle; - [FieldOffset(0)] public MatrixParallelTask task; - [FieldOffset(sizeof(MatrixParallelTask))]public T Constant; + public static void Terminate() + { + _ = Interlocked.Exchange(ref _paraState, 0); + } - public void Execute() { } + private static unsafe void MatrixParallelCycle() + { + Thread t_cur = Thread.CurrentThread; + while (_taskChannel.Reader.TryRead(out IntPtr ptr)) + { + MatrixParallelTask* taskHandle = (MatrixParallelTask*)ptr; + + // Execute the task directly + taskHandle->Execute(); + } + } } } diff --git a/StgSharp.Common/Mathematics/Scalar/Compare.cs b/StgSharp.Common/Mathematics/Scalar/Compare.cs index da4851ce..5a9d27b6 100644 --- a/StgSharp.Common/Mathematics/Scalar/Compare.cs +++ b/StgSharp.Common/Mathematics/Scalar/Compare.cs @@ -1,33 +1,33 @@ //----------------------------------------------------------------------- -//----------------------------------------------------------------------- -// file="Compare.cs" -// Project: StgSharp -// AuthorGroup: Nitload Space -// Copyright (c) Nitload Space. All rights reserved. +// ----------------------------------------------------------------------- +// file="Compare.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: +// 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 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. +// 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; @@ -39,24 +39,24 @@ namespace StgSharp.Mathematics public static partial class Scaler { - public static float MaxOf( params float[] stream ) + public static float MaxOf(params float[] stream) { - float ret = stream[ 0 ]; - foreach( float num in stream ) + float ret = stream[0]; + foreach (float num in stream) { - if( ret < num ) { + if (ret < num) { ret = num; } } return ret; } - public static float MinOf( params float[] stream ) + public static float MinOf(params float[] stream) { - float ret = stream[ 0 ]; - foreach( float num in stream ) + float ret = stream[0]; + foreach (float num in stream) { - if( ret > num ) { + if (ret > num) { ret = num; } }