no progress in matrix parallel
This commit is contained in:
@@ -59,25 +59,27 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
/// Thrown when requesting unsupported configurations.
|
/// Thrown when requesting unsupported configurations.
|
||||||
/// </exception>
|
/// </exception>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <para><strong> Important Threading Considerations: </strong></para> <para> While SLAB
|
/// <para><strong> Important Threading Considerations: </strong></para> <para>While SLAB
|
||||||
/// allocators themselves may be designed for single-threaded use, allocated objects are
|
/// /// allocators themselves may be designed for single-threaded use, allocated objects
|
||||||
/// frequently shared across multiple threads in real-world applications. Due to the
|
/// are /// frequently shared across multiple threads in real-world applications. Due
|
||||||
/// special implementation of expandable concurrent sequential SLAB allocators, they rely
|
/// to the /// special implementation of expandable concurrent sequential SLAB
|
||||||
/// on internal expansion locks to ensure that memory buffer expansions (which involve
|
/// allocators, they rely /// on internal expansion locks to ensure that memory buffer
|
||||||
/// copying the entire buffer to a new location) do not occur while other threads are
|
/// expansions (which involve /// copying the entire buffer to a new location) do not
|
||||||
/// reading from allocated regions.</para> <para><strong> Sequential Layout Limitations:
|
/// occur while other threads are /// reading from allocated regions. </para>
|
||||||
/// </strong><br /> Sequential layout SLAB allocators cannot provide a single-threaded
|
/// <para><strong>Sequential Layout Limitations: ///</strong><br /> Sequential layout SLAB
|
||||||
/// version because:<list type="bullet"><item><description> They use contiguous memory
|
/// allocators cannot provide a single-threaded /// version because:<list
|
||||||
/// layout that requires buffer expansion when capacity is exceeded
|
/// type="bullet"><item><description>They use contiguous memory /// layout that requires
|
||||||
/// </description></item><item><description> Buffer expansion involves copying all
|
/// buffer expansion when capacity is exceeded
|
||||||
/// existing data to a new memory location </description></item><item><description>
|
/// ///</description></item><item><description>Buffer expansion involves copying all ///
|
||||||
/// Without proper synchronization, concurrent access to allocated objects during
|
/// existing data to a new memory location</description></item><item><description> ///
|
||||||
/// expansion would cause memory corruption </description></item><item><description> The
|
/// Without proper synchronization, concurrent access to allocated objects during ///
|
||||||
/// expansion lock mechanism is essential even if allocation itself is single-threaded
|
/// expansion would cause memory corruption</description></item><item><description>The ///
|
||||||
/// </description></item></list></para> <para><strong> Chunked Layout: </strong><br />
|
/// expansion lock mechanism is essential even if allocation itself is single-threaded
|
||||||
/// Chunked layout allocators can optionally provide single-threaded versions since they
|
/// ///</description></item></list></para> <para><strong> Chunked Layout: </strong><br />
|
||||||
/// don't require buffer expansion and copying. Each chunk is allocated independently,
|
/// /// Chunked layout allocators can optionally provide single-threaded versions since
|
||||||
/// avoiding the memory relocation issues present in sequential layouts.</para>
|
/// they /// don't require buffer expansion and copying. Each chunk is allocated
|
||||||
|
/// independently, /// avoiding the memory relocation issues present in sequential
|
||||||
|
/// layouts. </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static SlabAllocator<T> Create(nuint count, SlabBufferLayout layout, bool concurrentSupport = true)
|
public static SlabAllocator<T> Create(nuint count, SlabBufferLayout layout, bool concurrentSupport = true)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ namespace StgSharp.Mathematics
|
|||||||
throw new IndexOutOfRangeException("Matrix dimensions must agree.");
|
throw new IndexOutOfRangeException("Matrix dimensions must agree.");
|
||||||
}
|
}
|
||||||
Matrix<float> result = GCMatrix<float>.FromDefault(left.ColumnLength, left.RowLength);
|
Matrix<float> result = GCMatrix<float>.FromDefault(left.ColumnLength, left.RowLength);
|
||||||
|
MatrixParallel.PublishTask();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,94 +123,94 @@ namespace StgSharp.Mathematics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly unsafe ref struct MatrixSegmentEnumeration(
|
}
|
||||||
MatrixKernel* source,
|
|
||||||
int stride,
|
public readonly unsafe ref struct MatrixSegmentEnumeration(
|
||||||
int size,
|
MatrixKernel* source,
|
||||||
int secondaryStride,
|
int stride,
|
||||||
int secondarySize)
|
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 MatrixKernel* _current = enumeration._source - enumeration._stride;
|
||||||
private readonly int _secondarySize = secondarySize;
|
private readonly MatrixKernel* _end = enumeration._source + enumeration._size;
|
||||||
private readonly int _secondaryStride = secondaryStride;
|
private readonly int _secondarySize = enumeration._secondarySize;
|
||||||
|
private readonly int _secondaryStride = enumeration._secondaryStride;
|
||||||
|
private readonly int _stride = enumeration._stride;
|
||||||
|
|
||||||
private readonly int _size = size;
|
public readonly Segment Current
|
||||||
private readonly int _stride = stride;
|
|
||||||
|
|
||||||
public Enumerator GetEnumerator()
|
|
||||||
{
|
{
|
||||||
return new Enumerator(in this);
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => new(_current, _secondarySize, _secondaryStride);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref struct Enumerator(in MatrixSegmentEnumeration enumeration)
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
_current += _stride;
|
||||||
private MatrixKernel* _current = enumeration._source - enumeration._stride;
|
return _current < _end;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 MatrixKernel* _end = source + (count * stride);
|
||||||
private readonly int _size = size;
|
|
||||||
private readonly int _stride = 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)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get;
|
get;
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private set;
|
private set;
|
||||||
} = source - stride;
|
} = source - stride;
|
||||||
|
|
||||||
public bool MoveNext()
|
|
||||||
{
|
|
||||||
Current += _stride;
|
|
||||||
return Current < _end;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
Current += _stride;
|
||||||
|
return Current < _end;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,60 +35,41 @@ using System.Drawing;
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace StgSharp.Mathematics
|
namespace StgSharp.Mathematics
|
||||||
{
|
{
|
||||||
/// <summary>
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
/// Matrix parallel computation task structure with scalar data packet support Uses type-
|
public unsafe struct MatrixParallelTaskWrap
|
||||||
/// erased design for thread pool compatibility
|
|
||||||
/// </summary>
|
|
||||||
[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(0)] public MatrixKernel* left;
|
||||||
[FieldOffset(8)] public MatrixKernel* result;
|
[FieldOffset(8)] public MatrixKernel* result;
|
||||||
[FieldOffset(16)] public MatrixKernel* right;
|
[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;
|
[FieldOffset(32)] public IntPtr executionHandle;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pointer to the scalar data packet containing up to 8 parameters Each parameter is
|
|
||||||
/// stored as ulong (8 bytes) for type erasure
|
|
||||||
/// </summary>
|
|
||||||
[FieldOffset(40)] public nint scalerDataPacket;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Execute the task using type-erased function pointer
|
|
||||||
/// </summary>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public readonly void Execute()
|
|
||||||
{
|
|
||||||
if (scalerCount == 0)
|
|
||||||
{
|
|
||||||
((delegate*<MatrixKernel*, MatrixKernel*, MatrixKernel*, void>)executionHandle)(left, right, result);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
((delegate*<MatrixKernel*, MatrixKernel*, MatrixKernel*, void*, void>)executionHandle)(left, right, result, (void*)scalerDataPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Scalar data packet for storing up to 8 parameters as type-erased ulong values Used to
|
/// Scalar data packet for storing up to 8 parameters as type-erased ulong values Supports
|
||||||
/// separate scalar data allocation from task allocation
|
/// reference counting for shared usage across multiple tasks Used to separate scalar data
|
||||||
|
/// allocation from task allocation and track batch completion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Explicit, Size = 72)]
|
||||||
public unsafe struct ScalarDataPacket
|
public unsafe struct ScalarDataPacket
|
||||||
{
|
{
|
||||||
|
|
||||||
public const int MaxScalarCount = 8;
|
public const int MaxScalarCount = 8;
|
||||||
public const int PacketSize = 64;
|
public const int PacketSize = 64;
|
||||||
|
|
||||||
private fixed ulong Value[8];
|
[FieldOffset(0)] private fixed ulong Value[8];
|
||||||
|
|
||||||
public ScalarDataPacket()
|
public ScalarDataPacket()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Factory for creating and managing MatrixParallelTask instances with pooled allocation Uses
|
|
||||||
/// separate SLAB allocators for tasks and scalar data packets
|
|
||||||
/// </summary>
|
|
||||||
public static unsafe class MatrixParallelTaskFactory
|
|
||||||
{
|
|
||||||
|
|
||||||
private static readonly SlabAllocator<ScalarDataPacket> ScalarPacketAllocator =
|
|
||||||
SlabAllocator<ScalarDataPacket>.Create(1024, SlabBufferLayout.Chunked, true);
|
|
||||||
|
|
||||||
// SLAB allocators for pooled allocation
|
|
||||||
private static readonly SlabAllocator<MatrixParallelTask> TaskAllocator =
|
|
||||||
SlabAllocator<MatrixParallelTask>.Create(2048, SlabBufferLayout.Chunked, true);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a task with no scalar parameters
|
|
||||||
/// </summary>
|
|
||||||
[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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a task with 1 scalar parameter
|
|
||||||
/// </summary>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static MatrixTaskHandle CreateTask<T0>(
|
|
||||||
MatrixKernel* left,
|
|
||||||
MatrixKernel* right,
|
|
||||||
MatrixKernel* result,
|
|
||||||
IntPtr executionHandle,
|
|
||||||
T0 scaler0)
|
|
||||||
where T0: unmanaged, INumber<T0>
|
|
||||||
{
|
|
||||||
return CreateTaskInternal(left, right, result, executionHandle, 1, &InitializePacket<T0>, scaler0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a task with 2 scalar parameters
|
|
||||||
/// </summary>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static MatrixTaskHandle CreateTask<T0, T1>(
|
|
||||||
MatrixKernel* left,
|
|
||||||
MatrixKernel* right,
|
|
||||||
MatrixKernel* result,
|
|
||||||
IntPtr executionHandle,
|
|
||||||
T0 scaler0,
|
|
||||||
T1 scaler1)
|
|
||||||
where T0: unmanaged, INumber<T0>
|
|
||||||
where T1: unmanaged, INumber<T1>
|
|
||||||
{
|
|
||||||
return CreateTaskInternal(
|
|
||||||
left, right, result, executionHandle, 2, &InitializePacket<T0, T1>, scaler0, scaler1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a task with 3 scalar parameters
|
|
||||||
/// </summary>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static MatrixTaskHandle CreateTask<T0, T1, T2>(
|
|
||||||
MatrixKernel* left,
|
|
||||||
MatrixKernel* right,
|
|
||||||
MatrixKernel* result,
|
|
||||||
IntPtr executionHandle,
|
|
||||||
T0 scaler0,
|
|
||||||
T1 scaler1,
|
|
||||||
T2 scaler2)
|
|
||||||
where T0: unmanaged, INumber<T0>
|
|
||||||
where T1: unmanaged, INumber<T1>
|
|
||||||
where T2: unmanaged, INumber<T2>
|
|
||||||
{
|
|
||||||
return CreateTaskInternal(
|
|
||||||
left, right, result, executionHandle, 3, &InitializePacket<T0, T1, T2>, scaler0, scaler1, scaler2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a task with 4 scalar parameters
|
|
||||||
/// </summary>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static MatrixTaskHandle CreateTask<T0, T1, T2, T3>(
|
|
||||||
MatrixKernel* left,
|
|
||||||
MatrixKernel* right,
|
|
||||||
MatrixKernel* result,
|
|
||||||
IntPtr executionHandle,
|
|
||||||
T0 scaler0,
|
|
||||||
T1 scaler1,
|
|
||||||
T2 scaler2,
|
|
||||||
T3 scaler3)
|
|
||||||
where T0: unmanaged, INumber<T0>
|
|
||||||
where T1: unmanaged, INumber<T1>
|
|
||||||
where T2: unmanaged, INumber<T2>
|
|
||||||
where T3: unmanaged, INumber<T3>
|
|
||||||
{
|
|
||||||
return CreateTaskInternal(
|
|
||||||
left, right, result, executionHandle, 4, &InitializePacket<T0, T1, T2, T3>, scaler0, scaler1, scaler2,
|
|
||||||
scaler3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a task with 5 scalar parameters
|
|
||||||
/// </summary>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static MatrixTaskHandle CreateTask<T0, T1, T2, T3, T4>(
|
|
||||||
MatrixKernel* left,
|
|
||||||
MatrixKernel* right,
|
|
||||||
MatrixKernel* result,
|
|
||||||
IntPtr executionHandle,
|
|
||||||
T0 scaler0,
|
|
||||||
T1 scaler1,
|
|
||||||
T2 scaler2,
|
|
||||||
T3 scaler3,
|
|
||||||
T4 scaler4)
|
|
||||||
where T0: unmanaged, INumber<T0>
|
|
||||||
where T1: unmanaged, INumber<T1>
|
|
||||||
where T2: unmanaged, INumber<T2>
|
|
||||||
where T3: unmanaged, INumber<T3>
|
|
||||||
where T4: unmanaged, INumber<T4>
|
|
||||||
{
|
|
||||||
return CreateTaskInternal(
|
|
||||||
left, right, result, executionHandle, 5, &InitializePacket<T0, T1, T2, T3, T4>, scaler0, scaler1,
|
|
||||||
scaler2, scaler3, scaler4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a task with 6 scalar parameters
|
|
||||||
/// </summary>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static MatrixTaskHandle CreateTask<T0, T1, T2, T3, T4, T5>(
|
|
||||||
MatrixKernel* left,
|
|
||||||
MatrixKernel* right,
|
|
||||||
MatrixKernel* result,
|
|
||||||
IntPtr executionHandle,
|
|
||||||
T0 scaler0,
|
|
||||||
T1 scaler1,
|
|
||||||
T2 scaler2,
|
|
||||||
T3 scaler3,
|
|
||||||
T4 scaler4,
|
|
||||||
T5 scaler5)
|
|
||||||
where T0: unmanaged, INumber<T0>
|
|
||||||
where T1: unmanaged, INumber<T1>
|
|
||||||
where T2: unmanaged, INumber<T2>
|
|
||||||
where T3: unmanaged, INumber<T3>
|
|
||||||
where T4: unmanaged, INumber<T4>
|
|
||||||
where T5: unmanaged, INumber<T5>
|
|
||||||
{
|
|
||||||
return CreateTaskInternal(
|
|
||||||
left, right, result, executionHandle, 6, &InitializePacket<T0, T1, T2, T3, T4, T5>, scaler0, scaler1,
|
|
||||||
scaler2, scaler3, scaler4, scaler5);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a task with 7 scalar parameters
|
|
||||||
/// </summary>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static MatrixTaskHandle CreateTask<T0, T1, T2, T3, T4, T5, T6>(
|
|
||||||
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<T0>
|
|
||||||
where T1: unmanaged, INumber<T1>
|
|
||||||
where T2: unmanaged, INumber<T2>
|
|
||||||
where T3: unmanaged, INumber<T3>
|
|
||||||
where T4: unmanaged, INumber<T4>
|
|
||||||
where T5: unmanaged, INumber<T5>
|
|
||||||
where T6: unmanaged, INumber<T6>
|
|
||||||
{
|
|
||||||
return CreateTaskInternal(
|
|
||||||
left, right, result, executionHandle, 7, &InitializePacket<T0, T1, T2, T3, T4, T5, T6>, scaler0,
|
|
||||||
scaler1, scaler2, scaler3, scaler4, scaler5, scaler6);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a task with 8 scalar parameters (maximum)
|
|
||||||
/// </summary>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static MatrixTaskHandle CreateTask<T0, T1, T2, T3, T4, T5, T6, T7>(
|
|
||||||
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<T0>
|
|
||||||
where T1: unmanaged, INumber<T1>
|
|
||||||
where T2: unmanaged, INumber<T2>
|
|
||||||
where T3: unmanaged, INumber<T3>
|
|
||||||
where T4: unmanaged, INumber<T4>
|
|
||||||
where T5: unmanaged, INumber<T5>
|
|
||||||
where T6: unmanaged, INumber<T6>
|
|
||||||
where T7: unmanaged, INumber<T7>
|
|
||||||
{
|
|
||||||
return CreateTaskInternal(
|
|
||||||
left, right, result, executionHandle, 8, &InitializePacket<T0, T1, T2, T3, T4, T5, T6, T7>, scaler0,
|
|
||||||
scaler1, scaler2, scaler3, scaler4, scaler5, scaler6, scaler7);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get allocation statistics for monitoring pool usage
|
|
||||||
/// </summary>
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clean up all allocators (call on application shutdown)
|
|
||||||
/// </summary>
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Internal helper for creating tasks with scalar packets
|
|
||||||
/// </summary>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static MatrixTaskHandle CreateTaskInternal<T0>(
|
|
||||||
MatrixKernel* left,
|
|
||||||
MatrixKernel* right,
|
|
||||||
MatrixKernel* result,
|
|
||||||
IntPtr executionHandle,
|
|
||||||
int scalerCount,
|
|
||||||
delegate*<ScalarDataPacket*, T0, void> 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<T0, T1>(
|
|
||||||
MatrixKernel* left,
|
|
||||||
MatrixKernel* right,
|
|
||||||
MatrixKernel* result,
|
|
||||||
IntPtr executionHandle,
|
|
||||||
int scalerCount,
|
|
||||||
delegate*<ScalarDataPacket*, T0, T1, void> 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<T0, T1, T2>(
|
|
||||||
MatrixKernel* left,
|
|
||||||
MatrixKernel* right,
|
|
||||||
MatrixKernel* result,
|
|
||||||
IntPtr executionHandle,
|
|
||||||
int scalerCount,
|
|
||||||
delegate*<ScalarDataPacket*, T0, T1, T2, void> 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<T0, T1, T2, T3>(
|
|
||||||
MatrixKernel* left,
|
|
||||||
MatrixKernel* right,
|
|
||||||
MatrixKernel* result,
|
|
||||||
IntPtr executionHandle,
|
|
||||||
int scalerCount,
|
|
||||||
delegate*<ScalarDataPacket*, T0, T1, T2, T3, void> 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<T0, T1, T2, T3, T4>(
|
|
||||||
MatrixKernel* left,
|
|
||||||
MatrixKernel* right,
|
|
||||||
MatrixKernel* result,
|
|
||||||
IntPtr executionHandle,
|
|
||||||
int scalerCount,
|
|
||||||
delegate*<ScalarDataPacket*, T0, T1, T2, T3, T4, void> 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<T0, T1, T2, T3, T4, T5>(
|
|
||||||
MatrixKernel* left,
|
|
||||||
MatrixKernel* right,
|
|
||||||
MatrixKernel* result,
|
|
||||||
IntPtr executionHandle,
|
|
||||||
int scalerCount,
|
|
||||||
delegate*<ScalarDataPacket*, T0, T1, T2, T3, T4, T5, void> 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<T0, T1, T2, T3, T4, T5, T6>(
|
|
||||||
MatrixKernel* left,
|
|
||||||
MatrixKernel* right,
|
|
||||||
MatrixKernel* result,
|
|
||||||
IntPtr executionHandle,
|
|
||||||
int scalerCount,
|
|
||||||
delegate*<ScalarDataPacket*, T0, T1, T2, T3, T4, T5, T6, void> 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<T0, T1, T2, T3, T4, T5, T6, T7>(
|
|
||||||
MatrixKernel* left,
|
|
||||||
MatrixKernel* right,
|
|
||||||
MatrixKernel* result,
|
|
||||||
IntPtr executionHandle,
|
|
||||||
int scalerCount,
|
|
||||||
delegate*<ScalarDataPacket*, T0, T1, T2, T3, T4, T5, T6, T7, void> 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<T0>(ScalarDataPacket* packet, T0 s0) where T0: unmanaged, INumber<T0>
|
|
||||||
{
|
|
||||||
packet->GetScalerRef<T0>(0) = s0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static void InitializePacket<T0, T1>(ScalarDataPacket* packet, T0 s0, T1 s1)
|
|
||||||
where T0: unmanaged, INumber<T0>
|
|
||||||
where T1: unmanaged, INumber<T1>
|
|
||||||
{
|
|
||||||
packet->GetScalerRef<T0>(0) = s0;
|
|
||||||
packet->GetScalerRef<T1>(1) = s1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static void InitializePacket<T0, T1, T2>(ScalarDataPacket* packet, T0 s0, T1 s1, T2 s2)
|
|
||||||
where T0: unmanaged, INumber<T0>
|
|
||||||
where T1: unmanaged, INumber<T1>
|
|
||||||
where T2: unmanaged, INumber<T2>
|
|
||||||
{
|
|
||||||
packet->GetScalerRef<T0>(0) = s0;
|
|
||||||
packet->GetScalerRef<T1>(1) = s1;
|
|
||||||
packet->GetScalerRef<T2>(2) = s2;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static void InitializePacket<T0, T1, T2, T3>(ScalarDataPacket* packet, T0 s0, T1 s1, T2 s2, T3 s3)
|
|
||||||
where T0: unmanaged, INumber<T0>
|
|
||||||
where T1: unmanaged, INumber<T1>
|
|
||||||
where T2: unmanaged, INumber<T2>
|
|
||||||
where T3: unmanaged, INumber<T3>
|
|
||||||
{
|
|
||||||
packet->GetScalerRef<T0>(0) = s0;
|
|
||||||
packet->GetScalerRef<T1>(1) = s1;
|
|
||||||
packet->GetScalerRef<T2>(2) = s2;
|
|
||||||
packet->GetScalerRef<T3>(3) = s3;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static void InitializePacket<T0, T1, T2, T3, T4>(
|
|
||||||
ScalarDataPacket* packet,
|
|
||||||
T0 s0,
|
|
||||||
T1 s1,
|
|
||||||
T2 s2,
|
|
||||||
T3 s3,
|
|
||||||
T4 s4)
|
|
||||||
where T0: unmanaged, INumber<T0>
|
|
||||||
where T1: unmanaged, INumber<T1>
|
|
||||||
where T2: unmanaged, INumber<T2>
|
|
||||||
where T3: unmanaged, INumber<T3>
|
|
||||||
where T4: unmanaged, INumber<T4>
|
|
||||||
{
|
|
||||||
packet->GetScalerRef<T0>(0) = s0;
|
|
||||||
packet->GetScalerRef<T1>(1) = s1;
|
|
||||||
packet->GetScalerRef<T2>(2) = s2;
|
|
||||||
packet->GetScalerRef<T3>(3) = s3;
|
|
||||||
packet->GetScalerRef<T4>(4) = s4;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static void InitializePacket<T0, T1, T2, T3, T4, T5>(
|
|
||||||
ScalarDataPacket* packet,
|
|
||||||
T0 s0,
|
|
||||||
T1 s1,
|
|
||||||
T2 s2,
|
|
||||||
T3 s3,
|
|
||||||
T4 s4,
|
|
||||||
T5 s5)
|
|
||||||
where T0: unmanaged, INumber<T0>
|
|
||||||
where T1: unmanaged, INumber<T1>
|
|
||||||
where T2: unmanaged, INumber<T2>
|
|
||||||
where T3: unmanaged, INumber<T3>
|
|
||||||
where T4: unmanaged, INumber<T4>
|
|
||||||
where T5: unmanaged, INumber<T5>
|
|
||||||
{
|
|
||||||
packet->GetScalerRef<T0>(0) = s0;
|
|
||||||
packet->GetScalerRef<T1>(1) = s1;
|
|
||||||
packet->GetScalerRef<T2>(2) = s2;
|
|
||||||
packet->GetScalerRef<T3>(3) = s3;
|
|
||||||
packet->GetScalerRef<T4>(4) = s4;
|
|
||||||
packet->GetScalerRef<T5>(5) = s5;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static void InitializePacket<T0, T1, T2, T3, T4, T5, T6>(
|
|
||||||
ScalarDataPacket* packet,
|
|
||||||
T0 s0,
|
|
||||||
T1 s1,
|
|
||||||
T2 s2,
|
|
||||||
T3 s3,
|
|
||||||
T4 s4,
|
|
||||||
T5 s5,
|
|
||||||
T6 s6)
|
|
||||||
where T0: unmanaged, INumber<T0>
|
|
||||||
where T1: unmanaged, INumber<T1>
|
|
||||||
where T2: unmanaged, INumber<T2>
|
|
||||||
where T3: unmanaged, INumber<T3>
|
|
||||||
where T4: unmanaged, INumber<T4>
|
|
||||||
where T5: unmanaged, INumber<T5>
|
|
||||||
where T6: unmanaged, INumber<T6>
|
|
||||||
{
|
|
||||||
packet->GetScalerRef<T0>(0) = s0;
|
|
||||||
packet->GetScalerRef<T1>(1) = s1;
|
|
||||||
packet->GetScalerRef<T2>(2) = s2;
|
|
||||||
packet->GetScalerRef<T3>(3) = s3;
|
|
||||||
packet->GetScalerRef<T4>(4) = s4;
|
|
||||||
packet->GetScalerRef<T5>(5) = s5;
|
|
||||||
packet->GetScalerRef<T6>(6) = s6;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static void InitializePacket<T0, T1, T2, T3, T4, T5, T6, T7>(
|
|
||||||
ScalarDataPacket* packet,
|
|
||||||
T0 s0,
|
|
||||||
T1 s1,
|
|
||||||
T2 s2,
|
|
||||||
T3 s3,
|
|
||||||
T4 s4,
|
|
||||||
T5 s5,
|
|
||||||
T6 s6,
|
|
||||||
T7 s7)
|
|
||||||
where T0: unmanaged, INumber<T0>
|
|
||||||
where T1: unmanaged, INumber<T1>
|
|
||||||
where T2: unmanaged, INumber<T2>
|
|
||||||
where T3: unmanaged, INumber<T3>
|
|
||||||
where T4: unmanaged, INumber<T4>
|
|
||||||
where T5: unmanaged, INumber<T5>
|
|
||||||
where T6: unmanaged, INumber<T6>
|
|
||||||
where T7: unmanaged, INumber<T7>
|
|
||||||
{
|
|
||||||
packet->GetScalerRef<T0>(0) = s0;
|
|
||||||
packet->GetScalerRef<T1>(1) = s1;
|
|
||||||
packet->GetScalerRef<T2>(2) = s2;
|
|
||||||
packet->GetScalerRef<T3>(3) = s3;
|
|
||||||
packet->GetScalerRef<T4>(4) = s4;
|
|
||||||
packet->GetScalerRef<T5>(5) = s5;
|
|
||||||
packet->GetScalerRef<T6>(6) = s6;
|
|
||||||
packet->GetScalerRef<T7>(7) = s7;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Task handle containing both task and scalar packet pointers
|
|
||||||
/// </summary>
|
|
||||||
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;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Release the allocated resources back to pools
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (IsValid)
|
|
||||||
{
|
|
||||||
TaskAllocator.Free((nuint)TaskPtr);
|
|
||||||
if (HasScalarPacket && ScalarPacketPtr != null) {
|
|
||||||
ScalarPacketAllocator.Free((nuint)ScalarPacketPtr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Execute the task
|
|
||||||
/// </summary>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public readonly void Execute()
|
|
||||||
{
|
|
||||||
if (!IsValid) {
|
|
||||||
throw new InvalidOperationException("Invalid task handle");
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskPtr->Execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Execute the task and automatically dispose the handle
|
|
||||||
/// </summary>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void ExecuteAndDispose()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Execute();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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<ScalarDataPacket> _scalarAllocator = SlabAllocator<ScalarDataPacket>.Create(64, SlabBufferLayout.Chunked, true);
|
||||||
|
|
||||||
|
private static readonly SlabAllocator<MatrixParallelTaskWrap> _wrapAllocator = SlabAllocator<MatrixParallelTaskWrap>.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,23 +45,24 @@ namespace StgSharp.Mathematics
|
|||||||
internal static class MatrixParallel
|
internal static class MatrixParallel
|
||||||
{
|
{
|
||||||
|
|
||||||
private static Thread[] _threads;
|
private static readonly Channel<IntPtr> _taskChannel = Channel.CreateUnbounded<IntPtr>();
|
||||||
private static Channel<IntPtr> _taskChannel = Channel.CreateUnbounded<IntPtr>();
|
|
||||||
private static int _paraState;
|
private static int _paraState;
|
||||||
|
|
||||||
|
private static IReadOnlyList<Thread> _threads;
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
int count = Environment.ProcessorCount - 4;
|
int count = Environment.ProcessorCount - 4;
|
||||||
count = count < 0 ? 1 : count;
|
count = count < 0 ? 1 : count;
|
||||||
_threads = new Thread[count];
|
List<Thread> _t = new(count);
|
||||||
Interlocked.Exchange(ref _paraState, 1);
|
_threads = _t;
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_threads[i] = new(MatrixParallelCycle)
|
_t.Add(new(MatrixParallelCycle)
|
||||||
{
|
{
|
||||||
IsBackground = true
|
IsBackground = true
|
||||||
};
|
});
|
||||||
_threads[i].Start();
|
_t[i].Start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,13 +76,8 @@ namespace StgSharp.Mathematics
|
|||||||
private static unsafe void MatrixParallelCycle()
|
private static unsafe void MatrixParallelCycle()
|
||||||
{
|
{
|
||||||
Thread t_cur = Thread.CurrentThread;
|
Thread t_cur = Thread.CurrentThread;
|
||||||
while (_taskChannel.Reader.TryRead(out IntPtr ptr))
|
int index = _threads.ToList().IndexOf(t_cur);
|
||||||
{
|
while (_taskChannel.Reader.TryRead(out IntPtr ptr)) { }
|
||||||
MatrixParallelTask* taskHandle = (MatrixParallelTask*)ptr;
|
|
||||||
|
|
||||||
// Execute the task directly
|
|
||||||
taskHandle->Execute();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
//-----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// file="ACos.cs"
|
// file="ACos.cs"
|
||||||
// Project: StgSharp
|
// Project: StgSharp
|
||||||
// AuthorGroup: Nitload Space
|
// AuthorGroup: Nitload Space
|
||||||
// Copyright (c) Nitload Space. All rights reserved.
|
// Copyright (c) Nitload Space. All rights reserved.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person
|
// Permission is hereby granted, free of charge, to any person
|
||||||
// obtaining a copy of this software and associated documentation
|
// obtaining a copy of this software and associated documentation
|
||||||
// files (the “Software”), to deal in the Software without restriction,
|
// files (the “Software”), to deal in the Software without restriction,
|
||||||
// including without limitation the rights to use, copy, modify, merge,
|
// including without limitation the rights to use, copy, modify, merge,
|
||||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
// and to permit persons to whom the Software is furnished to do so,
|
// and to permit persons to whom the Software is furnished to do so,
|
||||||
// subject to the following conditions:
|
// subject to the following conditions:
|
||||||
//
|
//
|
||||||
// The above copyright notice and
|
// The above copyright notice and
|
||||||
// this permission notice shall be included in all copies
|
// this permission notice shall be included in all copies
|
||||||
// or substantial portions of the Software.
|
// or substantial portions of the Software.
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
// 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,
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
//-----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
@@ -36,10 +36,10 @@ namespace StgSharp.Mathematics
|
|||||||
public static unsafe partial class Scaler
|
public static unsafe partial class Scaler
|
||||||
{
|
{
|
||||||
|
|
||||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static unsafe float ACos( float x )
|
public static unsafe float ACos(float x)
|
||||||
{
|
{
|
||||||
return MathF.Acos( x );
|
return MathF.Acos(x);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
int sign = 1;
|
int sign = 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user