diff --git a/StgSharp.Common/HighPerformance/Memory/SlabAllocator.cs b/StgSharp.Common/HighPerformance/Memory/SlabAllocator.cs index 7c7b36c9..5e81ffcf 100644 --- a/StgSharp.Common/HighPerformance/Memory/SlabAllocator.cs +++ b/StgSharp.Common/HighPerformance/Memory/SlabAllocator.cs @@ -59,25 +59,27 @@ namespace StgSharp.HighPerformance.Memory /// Thrown when requesting unsupported configurations. /// /// - /// Important Threading Considerations: While SLAB - /// allocators themselves may be designed for single-threaded use, allocated objects are - /// frequently shared across multiple threads in real-world applications. Due to the - /// special implementation of expandable concurrent sequential SLAB allocators, they rely - /// on internal expansion locks to ensure that memory buffer expansions (which involve - /// copying the entire buffer to a new location) do not occur while other threads are - /// reading from allocated regions. Sequential Layout Limitations: - ///
Sequential layout SLAB allocators cannot provide a single-threaded - /// version because: They use contiguous memory - /// layout that requires buffer expansion when capacity is exceeded - /// Buffer expansion involves copying all - /// existing data to a new memory location - /// Without proper synchronization, concurrent access to allocated objects during - /// expansion would cause memory corruption The - /// expansion lock mechanism is essential even if allocation itself is single-threaded - ///
Chunked Layout:
- /// Chunked layout allocators can optionally provide single-threaded versions since they - /// don't require buffer expansion and copying. Each chunk is allocated independently, - /// avoiding the memory relocation issues present in sequential layouts.
+ /// Important Threading Considerations: While SLAB + /// /// allocators themselves may be designed for single-threaded use, allocated objects + /// are /// frequently shared across multiple threads in real-world applications. Due + /// to the /// special implementation of expandable concurrent sequential SLAB + /// allocators, they rely /// on internal expansion locks to ensure that memory buffer + /// expansions (which involve /// copying the entire buffer to a new location) do not + /// occur while other threads are /// reading from allocated regions. + /// Sequential Layout Limitations: ///
Sequential layout SLAB + /// allocators cannot provide a single-threaded /// version because:They use contiguous memory /// layout that requires + /// buffer expansion when capacity is exceeded + /// ///Buffer expansion involves copying all /// + /// existing data to a new memory location /// + /// Without proper synchronization, concurrent access to allocated objects during /// + /// expansion would cause memory corruptionThe /// + /// expansion lock mechanism is essential even if allocation itself is single-threaded + /// ///
Chunked Layout:
+ /// /// Chunked layout allocators can optionally provide single-threaded versions since + /// they /// don't require buffer expansion and copying. Each chunk is allocated + /// independently, /// avoiding the memory relocation issues present in sequential + /// layouts.
///
public static SlabAllocator Create(nuint count, SlabBufferLayout layout, bool concurrentSupport = true) { diff --git a/StgSharp.Common/Mathematics/Linear/Matrix.Basic.cs b/StgSharp.Common/Mathematics/Linear/Matrix.Basic.cs index 88486b88..a7d489eb 100644 --- a/StgSharp.Common/Mathematics/Linear/Matrix.Basic.cs +++ b/StgSharp.Common/Mathematics/Linear/Matrix.Basic.cs @@ -46,6 +46,8 @@ namespace StgSharp.Mathematics throw new IndexOutOfRangeException("Matrix dimensions must agree."); } Matrix result = GCMatrix.FromDefault(left.ColumnLength, left.RowLength); + MatrixParallel.PublishTask(); + return result; } } diff --git a/StgSharp.Common/Mathematics/Linear/Matrix.cs b/StgSharp.Common/Mathematics/Linear/Matrix.cs index 1084a5d0..f9a40e07 100644 --- a/StgSharp.Common/Mathematics/Linear/Matrix.cs +++ b/StgSharp.Common/Mathematics/Linear/Matrix.cs @@ -123,94 +123,94 @@ namespace StgSharp.Mathematics } } - public readonly unsafe ref struct MatrixSegmentEnumeration( - MatrixKernel* source, - int stride, - int size, - int secondaryStride, - int secondarySize) + } + + public readonly unsafe ref struct MatrixSegmentEnumeration( + MatrixKernel* source, + int stride, + int size, + int secondaryStride, + int secondarySize) + { + + private readonly MatrixKernel* _source = source; + private readonly int _secondarySize = secondarySize; + private readonly int _secondaryStride = secondaryStride; + + private readonly int _size = size; + private readonly int _stride = stride; + + public Enumerator GetEnumerator() + { + return new Enumerator(in this); + } + + public ref struct Enumerator(in MatrixSegmentEnumeration enumeration) { - private readonly MatrixKernel* _source = source; - private readonly int _secondarySize = secondarySize; - private readonly int _secondaryStride = secondaryStride; + private MatrixKernel* _current = enumeration._source - enumeration._stride; + private readonly MatrixKernel* _end = enumeration._source + enumeration._size; + private readonly int _secondarySize = enumeration._secondarySize; + private readonly int _secondaryStride = enumeration._secondaryStride; + private readonly int _stride = enumeration._stride; - private readonly int _size = size; - private readonly int _stride = stride; - - public Enumerator GetEnumerator() + public readonly Segment Current { - return new Enumerator(in this); +[MethodImpl(MethodImplOptions.AggressiveInlining)] + get => new(_current, _secondarySize, _secondaryStride); } - public ref struct Enumerator(in MatrixSegmentEnumeration enumeration) + public bool MoveNext() { - - private MatrixKernel* _current = enumeration._source - enumeration._stride; - private readonly MatrixKernel* _end = enumeration._source + enumeration._size; - private readonly int _secondarySize = enumeration._secondarySize; - private readonly int _secondaryStride = enumeration._secondaryStride; - private readonly int _stride = enumeration._stride; - - public readonly Segment Current - { -[MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new(_current, _secondarySize, _secondaryStride); - } - - public bool MoveNext() - { - _current += _stride; - return _current < _end; - } - + _current += _stride; + return _current < _end; } } - public readonly unsafe ref struct Segment(MatrixKernel* source, int size, int stride) + } + + public readonly unsafe ref struct Segment(MatrixKernel* source, int size, int stride) + { + + private readonly MatrixKernel* _source = source; + private readonly int _size = size; + private readonly int _stride = stride; + + public ref MatrixKernel this[int index] + { + get + { + if (index < 0 || index >= _size) { + throw new ArgumentOutOfRangeException(nameof(index)); + } + return ref _source[index * _stride]; + } + } + + public Enumerator GetEnumerator() + { + return new Enumerator(_source, _size, _stride); + } + + public ref struct Enumerator(MatrixKernel* source, int count, int stride) { - private readonly MatrixKernel* _source = source; - private readonly int _size = size; + private readonly MatrixKernel* _end = source + (count * stride); private readonly int _stride = stride; - public ref MatrixKernel this[int index] + public MatrixKernel* Current { - get - { - if (index < 0 || index >= _size) { - throw new ArgumentOutOfRangeException(nameof(index)); - } - return ref _source[index * _stride]; - } - } - - public Enumerator GetEnumerator() - { - return new Enumerator(_source, _size, _stride); - } - - public ref struct Enumerator(MatrixKernel* source, int count, int stride) - { - - private readonly MatrixKernel* _end = source + (count * stride); - private readonly int _stride = stride; - - public MatrixKernel* Current - { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get; + get; [MethodImpl(MethodImplOptions.AggressiveInlining)] - private set; - } = source - stride; - - public bool MoveNext() - { - Current += _stride; - return Current < _end; - } + private set; + } = source - stride; + public bool MoveNext() + { + Current += _stride; + return Current < _end; } } diff --git a/StgSharp.Common/Mathematics/Linear/MatrixParallel.Task.cs b/StgSharp.Common/Mathematics/Linear/MatrixParallel.Task.cs index b4a1576c..25f312bf 100644 --- a/StgSharp.Common/Mathematics/Linear/MatrixParallel.Task.cs +++ b/StgSharp.Common/Mathematics/Linear/MatrixParallel.Task.cs @@ -35,60 +35,41 @@ using System.Drawing; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Threading; 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 + [StructLayout(LayoutKind.Explicit)] + public unsafe struct MatrixParallelTaskWrap { - 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(40)] public ScalarDataPacket* scalerPacket; + [FieldOffset(24)] public int ComputeMode; + [FieldOffset(60)] public int count; + + [FieldOffset(48)] public int leftStride; + [FieldOffset(56)] public int resultStride; + [FieldOffset(52)] public int rightStride; [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 + /// Scalar data packet for storing up to 8 parameters as type-erased ulong values Supports + /// reference counting for shared usage across multiple tasks Used to separate scalar data + /// allocation from task allocation and track batch completion /// + [StructLayout(LayoutKind.Explicit, Size = 72)] public unsafe struct ScalarDataPacket { public const int MaxScalarCount = 8; public const int PacketSize = 64; - private fixed ulong Value[8]; + [FieldOffset(0)] private fixed ulong Value[8]; public ScalarDataPacket() { diff --git a/StgSharp.Common/Mathematics/Linear/MatrixParallel.TaskFactory.cs b/StgSharp.Common/Mathematics/Linear/MatrixParallel.TaskFactory.cs deleted file mode 100644 index 687f53d7..00000000 --- a/StgSharp.Common/Mathematics/Linear/MatrixParallel.TaskFactory.cs +++ /dev/null @@ -1,738 +0,0 @@ -//----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -// 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/MatrixParallel.TaskWrapFactory.cs b/StgSharp.Common/Mathematics/Linear/MatrixParallel.TaskWrapFactory.cs new file mode 100644 index 00000000..01f719d7 --- /dev/null +++ b/StgSharp.Common/Mathematics/Linear/MatrixParallel.TaskWrapFactory.cs @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +// file="MatrixParallel.TaskWrapFactory.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.Memory; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StgSharp.Mathematics +{ + internal static unsafe class MatrixParallelFactory + { + + private static readonly SlabAllocator _scalarAllocator = SlabAllocator.Create(64, SlabBufferLayout.Chunked, true); + + private static readonly SlabAllocator _wrapAllocator = SlabAllocator.Create(64, SlabBufferLayout.Chunked, true); + + public static ScalarDataPacket* CreateScalarPacket() + { + ScalarDataPacket* p = (ScalarDataPacket*)_scalarAllocator.Allocate(); + return p; + } + + public static MatrixParallelTaskWrap* FromTaskWrap(MatrixParallelTaskWrap* source, int offset) + { + MatrixParallelTaskWrap* p = (MatrixParallelTaskWrap*)_wrapAllocator.Allocate(); + *p = *source; + p->left += offset * p->leftStride; + p->right += offset * p->rightStride; + p->result += offset * p->resultStride; + return p; + } + + public static void Release(ScalarDataPacket* source) + { + _scalarAllocator.Free((nuint)source); + } + + public static void Release(MatrixParallelTaskWrap* source) + { + if (source->scalerPacket != null) { + _scalarAllocator.Free((nuint)source->scalerPacket); + } + _wrapAllocator.Free((nuint)source); + } + + } +} \ No newline at end of file diff --git a/StgSharp.Common/Mathematics/Linear/MatrixParallel.cs b/StgSharp.Common/Mathematics/Linear/MatrixParallel.cs index 04429612..b00840e1 100644 --- a/StgSharp.Common/Mathematics/Linear/MatrixParallel.cs +++ b/StgSharp.Common/Mathematics/Linear/MatrixParallel.cs @@ -45,23 +45,24 @@ namespace StgSharp.Mathematics internal static class MatrixParallel { - private static Thread[] _threads; - private static Channel _taskChannel = Channel.CreateUnbounded(); + private static readonly Channel _taskChannel = Channel.CreateUnbounded(); private static int _paraState; + private static IReadOnlyList _threads; + public static void Init() { int count = Environment.ProcessorCount - 4; count = count < 0 ? 1 : count; - _threads = new Thread[count]; - Interlocked.Exchange(ref _paraState, 1); + List _t = new(count); + _threads = _t; for (int i = 0; i < count; i++) { - _threads[i] = new(MatrixParallelCycle) - { - IsBackground = true - }; - _threads[i].Start(); + _t.Add(new(MatrixParallelCycle) + { + IsBackground = true + }); + _t[i].Start(); } } @@ -75,13 +76,8 @@ namespace StgSharp.Mathematics 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(); - } + int index = _threads.ToList().IndexOf(t_cur); + while (_taskChannel.Reader.TryRead(out IntPtr ptr)) { } } } diff --git a/StgSharp.Common/Mathematics/Scalar/ACos.cs b/StgSharp.Common/Mathematics/Scalar/ACos.cs index 3ca295fa..f46bc237 100644 --- a/StgSharp.Common/Mathematics/Scalar/ACos.cs +++ b/StgSharp.Common/Mathematics/Scalar/ACos.cs @@ -1,33 +1,33 @@ //----------------------------------------------------------------------- -//----------------------------------------------------------------------- -// file="ACos.cs" -// Project: StgSharp -// AuthorGroup: Nitload Space -// Copyright (c) Nitload Space. All rights reserved. +// ----------------------------------------------------------------------- +// file="ACos.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.Runtime.CompilerServices; @@ -36,10 +36,10 @@ namespace StgSharp.Mathematics public static unsafe partial class Scaler { - [MethodImpl( MethodImplOptions.AggressiveInlining )] - public static unsafe float ACos( float x ) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe float ACos(float x) { - return MathF.Acos( x ); + return MathF.Acos(x); /* int sign = 1;