switch root namespace name to NITLOAD
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="MatrixOperatorPolicy"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric.Runtime
|
||||
{
|
||||
internal enum MatrixCachePolicy : short
|
||||
{
|
||||
|
||||
None = 0,
|
||||
|
||||
#region usage
|
||||
|
||||
Left = 1,
|
||||
Right = 2,
|
||||
Ans = 3,
|
||||
|
||||
#endregion
|
||||
|
||||
#region index direction
|
||||
|
||||
RowMajor = 4,
|
||||
ColMajor = 5,
|
||||
Sequential = 6,
|
||||
|
||||
#endregion
|
||||
|
||||
#region shape
|
||||
|
||||
Square = 8,
|
||||
UpperTriangle = 9,
|
||||
LowerTriangle = 10,
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="MatrixParallel.Await"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric
|
||||
{
|
||||
public static partial class MatrixParallel
|
||||
{
|
||||
|
||||
private static AwaitingQueue _awaitingLeaderHandle;
|
||||
|
||||
private static volatile int _createGeneration;
|
||||
private static int _sortState;
|
||||
|
||||
public static MatrixParallelThread[] LeadParallel(
|
||||
long recommendCount
|
||||
)
|
||||
{
|
||||
int recommend = (recommendCount > int.MaxValue) ? int.MaxValue : ((int)recommendCount);
|
||||
int min = (int)long.Min(recommend, _threads.Capacity);
|
||||
min /= 2;
|
||||
MatrixParallelThread[] ret;
|
||||
if (_threads.Count < min)
|
||||
{
|
||||
WaitHandle handle = new(
|
||||
_createGeneration,
|
||||
min,
|
||||
recommend
|
||||
);
|
||||
do
|
||||
{
|
||||
if (Interlocked.Exchange(ref _sortState, 1) == 0)
|
||||
{
|
||||
_awaitingLeaderHandle.Enqueue(handle);
|
||||
_ = Interlocked.Exchange(ref _sortState, 0);
|
||||
_ = Interlocked.Increment(ref _createGeneration);
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
int cycleGeneration = _createGeneration;
|
||||
do
|
||||
{
|
||||
Thread.Sleep(0);
|
||||
|
||||
if (_createGeneration != cycleGeneration)
|
||||
{
|
||||
if (Interlocked.Exchange(ref _sortState, 1) == 0)
|
||||
{
|
||||
if (_awaitingLeaderHandle.TryPopIfRefEqual(cycleGeneration, in handle))
|
||||
{
|
||||
// Sort is implemented in TryPopIfRefEqual
|
||||
ret = _threads.PopRange(handle.BestCount);
|
||||
_createGeneration++;
|
||||
_ = Interlocked.Exchange(ref _sortState, 0);
|
||||
return ret;
|
||||
}
|
||||
_ = Interlocked.Exchange(ref _sortState, 0);
|
||||
} else
|
||||
{
|
||||
cycleGeneration = _createGeneration;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
} else
|
||||
{
|
||||
// directly get the leader
|
||||
while (true)
|
||||
{
|
||||
if (Interlocked.Exchange(ref _sortState, 1) == 0)
|
||||
{
|
||||
ret = _threads.PopRange(recommend);
|
||||
_createGeneration++;
|
||||
_ = Interlocked.Exchange(ref _sortState, 0);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return ret;
|
||||
}
|
||||
|
||||
public static void ReturnParallelResources(
|
||||
ref MatrixParallelThread[] pool
|
||||
)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (Interlocked.Exchange(ref _sortState, 1) == 0)
|
||||
{
|
||||
_threads.PushRange(pool);
|
||||
_ = Interlocked.Exchange(ref _sortState, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pool = null!;
|
||||
}
|
||||
|
||||
private record class WaitHandle(
|
||||
int generation,
|
||||
int least,
|
||||
int best
|
||||
)
|
||||
{
|
||||
|
||||
public int CreateGeneration { get; init; } = generation;
|
||||
|
||||
public int LeastCount { get; init; } = least;
|
||||
|
||||
public int BestCount { get; init; } = best;
|
||||
|
||||
public int Priority { get; private set; }
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void UpdatePriority(
|
||||
int currentGeneration
|
||||
)
|
||||
{
|
||||
Priority = (currentGeneration - CreateGeneration) * (MatrixParallel._threads.Capacity - LeastCount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="MatrixParallel.AwaitingQueue"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric
|
||||
{
|
||||
public static partial class MatrixParallel
|
||||
{
|
||||
/*
|
||||
* Because caller of this class has its own sync object
|
||||
* this queue will use no sync object internally.
|
||||
*/
|
||||
|
||||
private class AwaitingQueue
|
||||
{
|
||||
|
||||
private Element _quickElements;
|
||||
private volatile int _count;
|
||||
private readonly Queue<WaitHandle> _fallback = [];
|
||||
|
||||
public AwaitingQueue() { }
|
||||
|
||||
public void Enqueue(
|
||||
WaitHandle handle
|
||||
)
|
||||
{
|
||||
if (_count > 7)
|
||||
{
|
||||
_fallback.Enqueue(handle);
|
||||
_ = Interlocked.Increment(ref _count);
|
||||
return;
|
||||
}
|
||||
_quickElements[_count] = handle;
|
||||
_ = Interlocked.Increment(ref _count);
|
||||
}
|
||||
|
||||
public bool TryDequeue(
|
||||
int generation,
|
||||
out WaitHandle handle
|
||||
)
|
||||
{
|
||||
if (_count == 0)
|
||||
{
|
||||
handle = null!;
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < _count; i++) {
|
||||
_quickElements[i].UpdatePriority(generation);
|
||||
}
|
||||
Element.Sort(ref _quickElements);
|
||||
handle = _quickElements[0];
|
||||
_count--;
|
||||
_quickElements[0] = default!;
|
||||
if (_count > 7) {
|
||||
_ = _fallback.TryDequeue(out _quickElements[0]!);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryPeek(
|
||||
int generation,
|
||||
out WaitHandle handle
|
||||
)
|
||||
{
|
||||
if (_count == 0)
|
||||
{
|
||||
handle = null!;
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < _count; i++) {
|
||||
_quickElements[i].UpdatePriority(generation);
|
||||
}
|
||||
|
||||
Element.Sort(ref _quickElements);
|
||||
handle = _quickElements[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryPopIfRefEqual(
|
||||
int generation,
|
||||
in WaitHandle handle
|
||||
)
|
||||
{
|
||||
if (_count == 0) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < _count; i++) {
|
||||
_quickElements[i].UpdatePriority(generation);
|
||||
}
|
||||
Element.Sort(ref _quickElements);
|
||||
if (!ReferenceEquals(_quickElements[0], handle)) {
|
||||
return false;
|
||||
}
|
||||
_count--;
|
||||
_quickElements[0] = null!;
|
||||
if (_count > 7) {
|
||||
_ = _fallback.TryDequeue(out _quickElements[0]!);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[InlineArray(8)]
|
||||
private struct Element
|
||||
{
|
||||
|
||||
private WaitHandle value;
|
||||
|
||||
public static void Sort(
|
||||
ref Element e
|
||||
)
|
||||
{
|
||||
int maxIdx = 0;
|
||||
WaitHandle first = e[0];
|
||||
int maxPr = first?.Priority ?? int.MinValue;
|
||||
|
||||
for (int i = 1; i < 8; i++)
|
||||
{
|
||||
WaitHandle cur = e[i];
|
||||
int p = cur?.Priority ?? int.MinValue;
|
||||
if (p > maxPr)
|
||||
{
|
||||
maxPr = p;
|
||||
maxIdx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxIdx != 0) {
|
||||
(e[0], e[maxIdx]) = (e[maxIdx], e[0]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="MatrixParallel.Numa"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using Nitload.Common.Collections;
|
||||
using Nitload.Common.HighPerformance.Memory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric
|
||||
{
|
||||
public static unsafe partial class MatrixParallel
|
||||
{
|
||||
|
||||
private static L4[] _numaBuffer;
|
||||
private static NumaMeasurement[] _numaMeasurements;
|
||||
|
||||
private static int[] _numaPayload;
|
||||
private static MatrixParallelThread[][] _numaSyncHeavy;
|
||||
private static MatrixParallelThread[][] _numaWaveFront;
|
||||
private static MatrixParallelThread[] _threads;
|
||||
|
||||
private static void UpdateThreadPayload()
|
||||
{
|
||||
for (int i = 0; i < _numaPayload.Length; i++) { }
|
||||
}
|
||||
|
||||
private struct NumaMeasurement
|
||||
{
|
||||
|
||||
public uint ActivePredictors;
|
||||
public uint ActiveThreadCount;
|
||||
public ulong ActiveTasks;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="MatrixParallel.Publish"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using Nitload.Common.Collections;
|
||||
using Nitload.Common.HighPerformance.Memory;
|
||||
using Nitload.Mathematics;
|
||||
using Nitload.Mathematics.Numeric.Runtime;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric
|
||||
{
|
||||
public static partial class MatrixParallel
|
||||
{
|
||||
|
||||
private const int MIN_TASK_PER_THREAD = 256;
|
||||
private const int REC_TASK_PER_THREAD = 1024;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
||||
internal static unsafe MatrixParallelWrap ScheduleTask<TTaskQueue>(
|
||||
MatrixParallelTask* package
|
||||
)
|
||||
|
||||
{
|
||||
/*
|
||||
int primCount = package->PrimCount;
|
||||
int secCount = package->SecCount;
|
||||
long count = (long)primCount * secCount;
|
||||
/**/
|
||||
|
||||
// Console.WriteLine($"amount of kernels is {count}");
|
||||
long payload = 0;
|
||||
int payloadIndex = 0;
|
||||
ulong additionalPayload = 0;
|
||||
for (int i = 0; i < _numaMeasurements.Length; i++)
|
||||
{
|
||||
MatrixParallelThread[] numa = _numaWaveFront[i];
|
||||
if ((numa is null) || (numa.Length == 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ulong total = (ulong)_numaWaveFront[i].Length;
|
||||
NumaMeasurement measure = _numaMeasurements[i];
|
||||
ulong numaPayload = measure.ActiveTasks;
|
||||
|
||||
// uint numaActive = measure.ActiveThreadCount;
|
||||
long curPayload = ((long)total) - (((long)(numaPayload + additionalPayload + 63)) / 64);
|
||||
if (curPayload < payload)
|
||||
{
|
||||
payload = curPayload;
|
||||
payloadIndex = i;
|
||||
}
|
||||
}
|
||||
L4 cache = _numaBuffer[payloadIndex];
|
||||
MatrixParallelThread[] selectedNuma = _numaWaveFront[payloadIndex];
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="MatrixParallel"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using Nitload.Common.Collections;
|
||||
using Nitload.Common.HighPerformance.ProcessorAbstraction;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric
|
||||
{
|
||||
public static unsafe partial class MatrixParallel
|
||||
{
|
||||
|
||||
private const int RESERVED_THREAD_COUNT = 4;
|
||||
|
||||
private static bool _meaningful;
|
||||
|
||||
private static CapacityFixedStack<MatrixParallelThread> _retiredThreads;
|
||||
|
||||
public static bool IsParallelSupported { get; } = Environment.ProcessorCount > 6;
|
||||
|
||||
public static bool IsParallelMeaningful => IsParallelSupported &&
|
||||
IsInitialized &&
|
||||
_meaningful;
|
||||
|
||||
public static int ContextCount { get; private set; }
|
||||
|
||||
private static bool IsInitialized { get; set; }
|
||||
|
||||
internal static void Deinit()
|
||||
{
|
||||
foreach (MatrixParallelThread t in _threads)
|
||||
{
|
||||
t.Pause();
|
||||
t.Dispose();
|
||||
}
|
||||
foreach (MatrixParallelThread t in _retiredThreads) {
|
||||
t.Dispose();
|
||||
}
|
||||
ContextCount = 0;
|
||||
IsInitialized = false;
|
||||
}
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
Dictionary<ulong, int> contextMap = [];
|
||||
|
||||
if (IsInitialized) {
|
||||
return;
|
||||
}
|
||||
if (!IsParallelSupported)
|
||||
{
|
||||
IsInitialized = true;
|
||||
return;
|
||||
}
|
||||
contextMap = [];
|
||||
int count = Environment.ProcessorCount;
|
||||
SIMDID globalSimd = new(0);
|
||||
_retiredThreads = new(RESERVED_THREAD_COUNT);
|
||||
|
||||
// init thread on all logical cores
|
||||
_numaWaveFront = Numa.CreateForeachThread<MatrixParallelThread>(
|
||||
core => {
|
||||
MatrixParallelThread thread = new(core);
|
||||
SpinWait.SpinUntil(() => thread.State == MatrixThreadState.Ready);
|
||||
|
||||
SIMDID simd = thread.Simd;
|
||||
ulong mask = simd.Mask;
|
||||
contextMap[mask] = contextMap.TryGetValue(mask, out int contextCount) ?
|
||||
(contextCount + 1) :
|
||||
1;
|
||||
globalSimd = (globalSimd.Mask != 0) ? UniteSIMDID(globalSimd, simd) : simd;
|
||||
return thread;
|
||||
});
|
||||
|
||||
// make global simd context
|
||||
IntrinsicContext globalContext = new();
|
||||
LoadIntrinsicFunction(&globalContext, globalSimd.Mask);
|
||||
NumericalModule.GlobalContext = globalContext;
|
||||
NumericalModule.GlobalIntrinsicMask = globalSimd;
|
||||
ContextCount = contextMap.Count;
|
||||
|
||||
// retire threads
|
||||
if (ContextCount == 1)
|
||||
{
|
||||
MatrixParallelThread[] threadArr = _numaWaveFront[0];
|
||||
int retireCount = Math.Min(RESERVED_THREAD_COUNT, Math.Max(0, threadArr.Length));
|
||||
for (int i = 1; i <= retireCount; i++) {
|
||||
RetireThread(threadArr[^i]);
|
||||
}
|
||||
_numaWaveFront[0] = threadArr[0..^retireCount];
|
||||
} else
|
||||
{
|
||||
RetireWhenMultipleSIMDID(_numaWaveFront);
|
||||
}
|
||||
_meaningful = _threads.Length > 1;
|
||||
|
||||
// _awaitingLeaderHandle = new AwaitingQueue();
|
||||
IsInitialized = true;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void RetireThread(
|
||||
MatrixParallelThread thread
|
||||
)
|
||||
{
|
||||
thread.Pause();
|
||||
thread.Dispose();
|
||||
_retiredThreads.Push(thread);
|
||||
}
|
||||
|
||||
private static void RetireWhenMultipleSIMDID(
|
||||
MatrixParallelThread[][] threads
|
||||
)
|
||||
{
|
||||
MatrixParallelThread[] allThreads = new MatrixParallelThread[Environment.ProcessorCount];
|
||||
int offset = 0;
|
||||
foreach (MatrixParallelThread[] threadArr in threads)
|
||||
{
|
||||
Array.Copy(threadArr, 0, allThreads, offset, threadArr.Length);
|
||||
offset += threadArr.Length;
|
||||
}
|
||||
Array.Sort(allThreads, static(
|
||||
left,
|
||||
right
|
||||
) => CompareSIMDID(left.Simd, right.Simd));
|
||||
int retireCount = Math.Min(RESERVED_THREAD_COUNT, Math.Max(0, allThreads.Length));
|
||||
|
||||
MatrixParallelThread[] retireArr = new MatrixParallelThread[retireCount];
|
||||
for (int i = 0; i < retireCount; i++)
|
||||
{
|
||||
MatrixParallelThread thread = allThreads[i];
|
||||
retireArr[i] = thread;
|
||||
RetireThread(thread);
|
||||
}
|
||||
|
||||
// rebuild numa active arrays
|
||||
for (int numa = 0; numa < _numaWaveFront.Length; numa++)
|
||||
{
|
||||
MatrixParallelThread[] source = threads[numa];
|
||||
int keepCount = 0;
|
||||
|
||||
for (int i = 0; i < source.Length; i++)
|
||||
{
|
||||
if (!retireArr.Contains(source[i])) {
|
||||
keepCount++;
|
||||
}
|
||||
}
|
||||
|
||||
MatrixParallelThread[] active = new MatrixParallelThread[keepCount];
|
||||
int index = 0;
|
||||
for (int i = 0; i < source.Length; i++)
|
||||
{
|
||||
MatrixParallelThread thread = source[i];
|
||||
if (!retireArr.Contains(thread)) {
|
||||
active[index++] = thread;
|
||||
}
|
||||
}
|
||||
|
||||
_numaWaveFront[numa] = active;
|
||||
}
|
||||
|
||||
_threads = allThreads[retireCount..];
|
||||
}
|
||||
|
||||
#region C invoke
|
||||
|
||||
[LibraryImport(Native.LibName, EntryPoint = "sn_compare_simd")]
|
||||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
|
||||
private static partial int CompareSIMDID(
|
||||
SIMDID left,
|
||||
SIMDID right
|
||||
);
|
||||
|
||||
[LibraryImport(Native.LibName, EntryPoint = "load_intrinsic_function")]
|
||||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
|
||||
private static partial void LoadIntrinsicFunction(
|
||||
IntrinsicContext* context,
|
||||
ulong id
|
||||
);
|
||||
|
||||
[LibraryImport(Native.LibName, EntryPoint = "sn_get_unite_simd")]
|
||||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
|
||||
private static partial SIMDID UniteSIMDID(
|
||||
SIMDID left,
|
||||
SIMDID right
|
||||
);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="MatrixParallelQueue"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using Microsoft.VisualBasic.FileIO;
|
||||
using Nitload.Common.HighPerformance.Memory;
|
||||
using Nitload.Mathematics.Numeric.Runtime;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices.JavaScript;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric
|
||||
{
|
||||
internal unsafe class MatrixParallelQueue : IDisposable
|
||||
{
|
||||
|
||||
private MatrixParallelTask[] _currentPack;
|
||||
private MatrixParallelTask[] _predictBuffer;
|
||||
private bool disposedValue;
|
||||
|
||||
private int _currentCapacity;
|
||||
private int _cursor;
|
||||
private int _predictCapacity;
|
||||
|
||||
private ManualResetEventSlim _exchangeLock = new();
|
||||
|
||||
public MatrixParallelQueue()
|
||||
{
|
||||
_currentPack = new MatrixParallelTask[512];
|
||||
_predictBuffer = new MatrixParallelTask[512];
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing:true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public bool TryGetTask(
|
||||
out MatrixParallelTask task
|
||||
)
|
||||
{
|
||||
if (_cursor >= _currentCapacity)
|
||||
{
|
||||
task = default;
|
||||
return false;
|
||||
}
|
||||
task = _currentPack[_cursor++];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual void Dispose(
|
||||
bool disposing
|
||||
)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing) {
|
||||
_exchangeLock.Dispose();
|
||||
}
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="MatrixParallelTask"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using Nitload.Common.HighPerformance.Memory;
|
||||
using Nitload.Common.HighPerformance.ProcessorAbstraction;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric.Runtime
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct MatrixParallelSource
|
||||
{
|
||||
|
||||
public MatrixParallelTask Task;
|
||||
public ulong Count;
|
||||
public ulong Cursor;
|
||||
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = 128)]
|
||||
internal unsafe struct MatrixParallelTask
|
||||
{
|
||||
|
||||
[FieldOffset(104)] private ulong _reserved0;
|
||||
|
||||
[FieldOffset(0)] public L4.Handle Buffer0;
|
||||
[FieldOffset(16)] public L4.Handle Buffer1;
|
||||
[FieldOffset(32)] public L4.Handle Buffer2;
|
||||
[FieldOffset(48)] public L4.Handle Buffer3;
|
||||
[FieldOffset(112)] public M128 ScalarPack;
|
||||
[FieldOffset(64)] public M512 Profile;
|
||||
[FieldOffset(64)] public MatrixElementType ElementType; //记录了类型掩码的类型位宽的union,大小4byte
|
||||
[FieldOffset(68)] public MatrixIntrinsicHandle ComputeHandle; //记录了函数指针在类型组中的索引,实际就是int,但是为每一个索引起了名字,于是变成了enum,大小4byte
|
||||
|
||||
public MatrixParallelTask()
|
||||
{
|
||||
Unsafe.SkipInit(out this);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Copy(
|
||||
MatrixParallelTask* source,
|
||||
MatrixParallelTask* target
|
||||
)
|
||||
{
|
||||
Buffer.MemoryCopy(source, target, sizeof(MatrixParallelTask),
|
||||
sizeof(MatrixParallelTask));
|
||||
}
|
||||
|
||||
#region offset and length settings
|
||||
|
||||
[FieldOffset(72)] public int Offset0;
|
||||
[FieldOffset(76)] public int Count0;
|
||||
[FieldOffset(80)] public int Offset1;
|
||||
[FieldOffset(84)] public int Count1;
|
||||
[FieldOffset(88)] public int Offset2;
|
||||
[FieldOffset(92)] public int Count2;
|
||||
[FieldOffset(96)] public int Offset3;
|
||||
[FieldOffset(100)] public int Count3;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="MatrixParallelThread.Fma"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using Nitload.Common.Internal;
|
||||
using Nitload.Mathematics;
|
||||
using Nitload.Mathematics.Internal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric
|
||||
{
|
||||
public partial class MatrixParallelThread
|
||||
{
|
||||
|
||||
internal static unsafe void ComputeFmaPanelF32(
|
||||
MatrixParallelTask* p
|
||||
)
|
||||
{
|
||||
int f32 = MatrixElementType.F32.IntrinsicNode;
|
||||
MatrixKernel* leftBuffer = (MatrixKernel*)p->Left;
|
||||
MatrixKernel* rightBuffer = (MatrixKernel*)p->Right;
|
||||
MatrixKernel* ansBuffer = (MatrixKernel*)p->Answer;
|
||||
ref long offsetRef = ref Unsafe.As<int, long>(ref p->PrimTileOffset);
|
||||
ref long lengthRef = ref Unsafe.As<int, long>(ref p->PrimCount);
|
||||
int ansWidth = p->AnsPrimOffset;
|
||||
int ansHeight = p->AnsSecOffset;
|
||||
int commonK = p->LeftPrimOffset;
|
||||
|
||||
M128* enumeration = stackalloc M128[1];
|
||||
enumeration->Member<int>(2) = commonK;
|
||||
enumeration->Member<int>(3) = ansHeight;
|
||||
|
||||
// in this occasion size must be 1
|
||||
for (long c = offsetRef; c < offsetRef + lengthRef; c++)
|
||||
{
|
||||
int i = (int)(c / ansHeight);
|
||||
int j = (int)(c % ansHeight);
|
||||
enumeration->Member<int>(0) = i;
|
||||
enumeration->Member<int>(1) = j;
|
||||
NumericalModule.GlobalContext.mat_sk[f32].kernel_tile_fma(leftBuffer, rightBuffer,
|
||||
ansBuffer, enumeration);
|
||||
}
|
||||
}
|
||||
|
||||
internal static unsafe void ComputeFmaPanelF64(
|
||||
MatrixParallelTask* p
|
||||
)
|
||||
{
|
||||
int f64 = MatrixElementType.F64.IntrinsicNode;
|
||||
|
||||
// int size = 1;
|
||||
MatrixKernel* leftBuffer = (MatrixKernel*)p->Left;
|
||||
MatrixKernel* rightBuffer = (MatrixKernel*)p->Right;
|
||||
MatrixKernel* ansBuffer = (MatrixKernel*)p->Answer;
|
||||
ref long offsetRef = ref Unsafe.As<int, long>(ref p->PrimTileOffset);
|
||||
ref long lengthRef = ref Unsafe.As<int, long>(ref p->PrimCount);
|
||||
int ansWidth = p->AnsPrimOffset;
|
||||
int ansHeight = p->AnsSecOffset;
|
||||
int commonK = p->LeftPrimOffset;
|
||||
|
||||
M128* enumeration = stackalloc M128[1];
|
||||
enumeration->Member<int>(2) = commonK;
|
||||
enumeration->Member<int>(3) = ansHeight;
|
||||
|
||||
// in this occasion size must be 1
|
||||
for (long c = offsetRef; c < offsetRef + lengthRef; c++)
|
||||
{
|
||||
int i = (int)(c / ansHeight);
|
||||
int j = (int)(c % ansHeight);
|
||||
enumeration->Member<int>(0) = i;
|
||||
enumeration->Member<int>(1) = j;
|
||||
NumericalModule.GlobalContext.mat_sk[f64].kernel_tile_fma(leftBuffer, rightBuffer,
|
||||
ansBuffer, enumeration);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="MatrixParallelThread.Model"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using Nitload.Mathematics;
|
||||
using Nitload.Mathematics.Internal;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric
|
||||
{
|
||||
public partial class MatrixParallelThread
|
||||
{
|
||||
|
||||
private const int KernelStealCount = 64;
|
||||
|
||||
internal unsafe void BufferCompute(
|
||||
MatrixParallelTask* p
|
||||
)
|
||||
{
|
||||
// while () { }
|
||||
int size = p->ElementSize * 16;
|
||||
long count = Unsafe.As<int, long>(ref p->PrimCount);
|
||||
long offset = Unsafe.As<int, long>(ref p->PrimTileOffset) * size;
|
||||
ScalarPacket* scalar = p->Scalar;
|
||||
IntPtr computeHandle = _context[p->ComputeHandle];
|
||||
((delegate* unmanaged[Cdecl]<void*, void*, void*, void*, long, void>)computeHandle)((void*)(p->Left + offset),
|
||||
(void*)(p->Right + offset),
|
||||
(void*)(p->Answer + offset),
|
||||
scalar,
|
||||
count);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal unsafe void SpecialBufferCompute(
|
||||
MatrixParallelTask* p
|
||||
)
|
||||
{
|
||||
switch ((MatrixElementType)p->ElementSize)
|
||||
{
|
||||
case MatrixElementType.F64:
|
||||
ComputeFmaPanelF64(p);
|
||||
return;
|
||||
case MatrixElementType.F32:
|
||||
ComputeFmaPanelF32(p);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="MatrixParallelThread.Sequential"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric.Runtime
|
||||
{
|
||||
internal class MatrixParallelThread { }
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="MatrixParallelThread"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using Nitload.Common.HighPerformance.ProcessorAbstraction;
|
||||
using Nitload.Common.Internal;
|
||||
using Nitload.Mathematics.Numeric.Runtime;
|
||||
using Nitload.Threading;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric
|
||||
{
|
||||
internal enum MatrixThreadState : int
|
||||
{
|
||||
|
||||
Born = 0,
|
||||
Ready = 1,
|
||||
Running = 2,
|
||||
Idle = 4,
|
||||
Retired = 8,
|
||||
|
||||
}
|
||||
|
||||
public unsafe partial class MatrixParallelThread : IEquatable<MatrixParallelThread>, IDisposable
|
||||
{
|
||||
|
||||
private IntrinsicContext* _context;
|
||||
private readonly MatrixParallelTask* _currentTask;
|
||||
private volatile bool _disposed;
|
||||
private readonly ManualResetEventSlim _resetEvent;
|
||||
|
||||
private volatile MatrixThreadState _target;
|
||||
private Thread _managedThread;
|
||||
|
||||
internal MatrixParallelThread(
|
||||
LogicalCore binded
|
||||
)
|
||||
{
|
||||
_resetEvent = new ManualResetEventSlim(false);
|
||||
_managedThread = new Thread(MatrixParallelWorkLoad);
|
||||
_managedThread.Start();
|
||||
BindedLogicalCore = binded;
|
||||
}
|
||||
|
||||
public LogicalCore BindedLogicalCore { get; init; }
|
||||
|
||||
public ThreadPriority AfterWork { get; set; }
|
||||
|
||||
internal MatrixThreadState State { get; private set; }
|
||||
|
||||
internal SIMDID Simd { get; private set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing:true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Restart()
|
||||
{
|
||||
_resetEvent.Set();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void Pause()
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, nameof(MatrixParallelThread));
|
||||
if (State == MatrixThreadState.Idle) {
|
||||
return;
|
||||
}
|
||||
_resetEvent.Set();
|
||||
SpinWait.SpinUntil(() => State == MatrixThreadState.Idle);
|
||||
_managedThread.Join();
|
||||
}
|
||||
|
||||
protected virtual void Dispose(
|
||||
bool disposing
|
||||
)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_disposed = true;
|
||||
_resetEvent.Set();
|
||||
_managedThread.Join();
|
||||
_resetEvent.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void MatrixParallelWorkLoad()
|
||||
{
|
||||
State = MatrixThreadState.Born;
|
||||
|
||||
// Bind OS-thread affinity once when the worker starts running
|
||||
ThreadHelper.BindToLogicalCore(BindedLogicalCore);
|
||||
_ = Thread.Yield();
|
||||
if (Simd.Mask != 0)
|
||||
{
|
||||
SIMDID feature = new(GetSimdId());
|
||||
IntrinsicContext* contextPtr = stackalloc IntrinsicContext[1];
|
||||
LoadIntrinsicFunction(contextPtr, feature.Mask);
|
||||
Simd = feature;
|
||||
_context = contextPtr;
|
||||
}
|
||||
MatrixParallelTask* taskPtr = stackalloc MatrixParallelTask[4];
|
||||
State = MatrixThreadState.Ready;
|
||||
while (true)
|
||||
{
|
||||
// Thread self = Thread.CurrentThread;
|
||||
_resetEvent.Wait();
|
||||
_resetEvent.Reset();
|
||||
if (_disposed)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (_target == MatrixThreadState.Idle)
|
||||
{
|
||||
State = MatrixThreadState.Idle;
|
||||
continue;
|
||||
}
|
||||
State = MatrixThreadState.Idle;
|
||||
State = MatrixThreadState.Running;
|
||||
_managedThread.Priority = ThreadPriority.Highest;
|
||||
|
||||
|
||||
// MatrixParallelQueue taskQueue = BindedWrap.TaskQueue;
|
||||
/*
|
||||
if (0 > (int)p ->ComputeHandle) {
|
||||
SpecialBufferCompute(p);
|
||||
}
|
||||
switch (p->ComputeMode)
|
||||
{
|
||||
case MatrixIndexStyle.BUFFER_INDEX:
|
||||
BufferCompute(p);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/**/
|
||||
|
||||
_managedThread.Priority = AfterWork;
|
||||
State = MatrixThreadState.Idle;
|
||||
}
|
||||
State = MatrixThreadState.Retired;
|
||||
}
|
||||
|
||||
#pragma warning disable CA5393
|
||||
[LibraryImport(Native.LibName, EntryPoint = "sn_get_simd_level_local")]
|
||||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
|
||||
internal static partial ulong GetSimdId();
|
||||
|
||||
[LibraryImport(Native.LibName, EntryPoint = "load_intrinsic_function")]
|
||||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
|
||||
private static unsafe partial void LoadIntrinsicFunction(
|
||||
IntrinsicContext* context,
|
||||
ulong id
|
||||
);
|
||||
|
||||
public bool Equals(
|
||||
MatrixParallelThread? other
|
||||
)
|
||||
{
|
||||
return (other is not null) && ReferenceEquals(this, other);
|
||||
}
|
||||
#pragma warning restore CA5393
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="MatrixParallelWrap"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using Nitload.Common.Collections;
|
||||
using Nitload.Common.HighPerformance.Memory;
|
||||
using Nitload.Mathematics.Numeric.Runtime;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric
|
||||
{
|
||||
public enum SleepMode : int
|
||||
{
|
||||
|
||||
QuickWakeup = ThreadPriority.AboveNormal,
|
||||
NormalSleep = ThreadPriority.BelowNormal,
|
||||
DeepSleep = ThreadPriority.Lowest,
|
||||
|
||||
}
|
||||
|
||||
public class MatrixParallelWrap : IDisposable
|
||||
{
|
||||
|
||||
private MatrixParallelThread[] _threads;
|
||||
private bool _disposed;
|
||||
private readonly CountdownEvent _countdownEvent;
|
||||
|
||||
internal MatrixParallelWrap(
|
||||
MatrixParallelThread[] threadArray
|
||||
)
|
||||
{
|
||||
_threads = threadArray;
|
||||
_countdownEvent = new CountdownEvent(threadArray.Length);
|
||||
}
|
||||
|
||||
public ReadOnlySpan<MatrixParallelThread> Threads => _disposed ? [] : _threads;
|
||||
|
||||
public ThreadPriority AfterWork { get; private set; }
|
||||
|
||||
internal L4 DataCache { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void LaunchParallel(
|
||||
SleepMode afterWork
|
||||
)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, nameof(MatrixParallelWrap));
|
||||
AfterWork = (ThreadPriority)afterWork;
|
||||
foreach (MatrixParallelThread thread in _threads)
|
||||
{
|
||||
thread.AfterWork = AfterWork;
|
||||
|
||||
// thread.BindedWrap = this;
|
||||
}
|
||||
WaitAllWraps();
|
||||
}
|
||||
|
||||
public void WaitAllWraps()
|
||||
{
|
||||
if (_disposed) {
|
||||
return;
|
||||
}
|
||||
_countdownEvent.Wait();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void ReportThreadAccomplished()
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, nameof(MatrixParallelWrap));
|
||||
_ = _countdownEvent.Signal();
|
||||
}
|
||||
|
||||
private void Dispose(
|
||||
bool disposing
|
||||
)
|
||||
{
|
||||
if (_disposed) {
|
||||
return;
|
||||
}
|
||||
if (disposing)
|
||||
{
|
||||
// MatrixParallel.ReturnParallelResources(ref _threads);
|
||||
_countdownEvent.Dispose();
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="QueueFactory"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric
|
||||
{
|
||||
internal interface IMatrixQueueFactory
|
||||
{
|
||||
|
||||
// IMatrixParallelQueue<IMatrixParallelQueue> CreateSequential();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user