From 2475a3b0ed46b21c1b19b7c0a11638bd1269e97b Mon Sep 17 00:00:00 2001
From: Youmu Liu <105042599+Nitload-NSI@users.noreply.github.com>
Date: Mon, 1 Sep 2025 22:17:52 +0800
Subject: [PATCH] no progress in matrix parallel
---
.../HighPerformance/Memory/SlabAllocator.cs | 40 +-
.../Mathematics/Linear/Matrix.Basic.cs | 2 +
StgSharp.Common/Mathematics/Linear/Matrix.cs | 138 ++--
.../Mathematics/Linear/MatrixParallel.Task.cs | 49 +-
.../Linear/MatrixParallel.TaskFactory.cs | 738 ------------------
.../Linear/MatrixParallel.TaskWrapFactory.cs | 77 ++
.../Mathematics/Linear/MatrixParallel.cs | 28 +-
StgSharp.Common/Mathematics/Scalar/ACos.cs | 56 +-
8 files changed, 224 insertions(+), 904 deletions(-)
delete mode 100644 StgSharp.Common/Mathematics/Linear/MatrixParallel.TaskFactory.cs
create mode 100644 StgSharp.Common/Mathematics/Linear/MatrixParallel.TaskWrapFactory.cs
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 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.
///
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;