back to matrix
This commit is contained in:
@@ -42,6 +42,13 @@ namespace StgSharp.Mathematics.Internal
|
||||
[FieldOffset(0)]public fixed byte MaskByte[16];
|
||||
[FieldOffset(0)]public ulong Mask;
|
||||
|
||||
internal SIMDID(
|
||||
ulong data
|
||||
)
|
||||
{
|
||||
Mask = data;
|
||||
}
|
||||
|
||||
public SIMDID()
|
||||
{
|
||||
Unsafe.SkipInit(out this);
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// file="MatrixCompute.Sequential"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
// 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
|
||||
@@ -40,7 +40,11 @@ namespace StgSharp.Mathematics.Numeric.Linear
|
||||
public static unsafe partial class MatrixCompute
|
||||
{
|
||||
|
||||
public static void Add(Matrix<float> left, Matrix<float> right, Matrix<float> ans)
|
||||
public static void Add(
|
||||
Matrix<float> left,
|
||||
Matrix<float> right,
|
||||
Matrix<float> ans
|
||||
)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(left, nameof(left));
|
||||
ArgumentNullException.ThrowIfNull(right, nameof(right));
|
||||
@@ -69,6 +73,7 @@ namespace StgSharp.Mathematics.Numeric.Linear
|
||||
t->Mat3 = (MatrixKernel*)ansPtr;
|
||||
t->ElementType = MatrixElementType.F64;
|
||||
t->Scalar.Data<long>(0) = count;
|
||||
MatrixParallelThread[] pool;
|
||||
if (count <= 256)
|
||||
{
|
||||
add(t);
|
||||
@@ -78,32 +83,44 @@ namespace StgSharp.Mathematics.Numeric.Linear
|
||||
return;
|
||||
} else if (count <= 1024)
|
||||
{
|
||||
MatrixParallelThread[] pool = MatrixParallel.LeadParallel(1);
|
||||
pool = MatrixParallel.LeadParallel(1);
|
||||
add(t);
|
||||
MatrixParallel.ReturnParallelResources(ref pool);
|
||||
return;
|
||||
}
|
||||
MatrixParallelWrap taskGroup = MatrixParallel.ScheduleTask<SequentialPredictor>((nuint)add, t);
|
||||
pool = MatrixParallel.LeadParallel((int)(count / 1024));
|
||||
MatrixParallelWrap taskGroup = MatrixParallel.ScheduleTask<SequentialPredictor>(pool, t);
|
||||
|
||||
taskGroup.LaunchParallel(SleepMode.DeepSleep);
|
||||
taskGroup.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
private sealed class SequentialPredictor : MatrixPredictor<SequentialPredictor>
|
||||
private struct SequentialPredictor : IMatrixPredictor<SequentialPredictor>
|
||||
{
|
||||
|
||||
public override bool Predict(Span<CacheLinePrediction> node, out int count)
|
||||
public bool Predict(
|
||||
Span<CacheLinePrediction> node,
|
||||
out int count
|
||||
)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Prefetch(nuint origin, ulong policy, Span<byte> cache)
|
||||
public void Prefetch(
|
||||
nuint origin,
|
||||
ulong policy,
|
||||
Span<byte> cache
|
||||
)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void WriteBack(nuint origin, ulong policy, ReadOnlySpan<byte> cache)
|
||||
public void WriteBack(
|
||||
nuint origin,
|
||||
ulong policy,
|
||||
ReadOnlySpan<byte> cache
|
||||
)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -41,23 +41,23 @@ namespace StgSharp.Mathematics.Numeric
|
||||
|
||||
private static AwaitingQueue _awaitingLeaderHandle;
|
||||
|
||||
private static volatile int _createGeneration = 0;
|
||||
private static volatile int _createGeneration;
|
||||
private static int _sortState;
|
||||
|
||||
public static MatrixParallelThread[] LeadParallel(
|
||||
int recommendCount
|
||||
long recommendCount
|
||||
)
|
||||
{
|
||||
int min = int.Min(recommendCount, _threads.Capacity);
|
||||
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 WaitHandle
|
||||
(
|
||||
WaitHandle handle = new(
|
||||
_createGeneration,
|
||||
min,
|
||||
recommendCount
|
||||
recommend
|
||||
);
|
||||
do
|
||||
{
|
||||
@@ -65,7 +65,7 @@ namespace StgSharp.Mathematics.Numeric
|
||||
{
|
||||
_awaitingLeaderHandle.Enqueue(handle);
|
||||
_ = Interlocked.Exchange(ref _sortState, 0);
|
||||
Interlocked.Increment(ref _createGeneration);
|
||||
_ = Interlocked.Increment(ref _createGeneration);
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
@@ -100,7 +100,7 @@ namespace StgSharp.Mathematics.Numeric
|
||||
{
|
||||
if (Interlocked.Exchange(ref _sortState, 1) == 0)
|
||||
{
|
||||
ret = _threads.PopRange(recommendCount);
|
||||
ret = _threads.PopRange(recommend);
|
||||
_createGeneration++;
|
||||
_ = Interlocked.Exchange(ref _sortState, 0);
|
||||
return ret;
|
||||
@@ -120,7 +120,7 @@ namespace StgSharp.Mathematics.Numeric
|
||||
if (Interlocked.Exchange(ref _sortState, 1) == 0)
|
||||
{
|
||||
_threads.PushRange(pool);
|
||||
Interlocked.Exchange(ref _sortState, 0);
|
||||
_ = Interlocked.Exchange(ref _sortState, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// file="MatrixParallel.Publish"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
// 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
|
||||
@@ -48,8 +48,10 @@ namespace StgSharp.Mathematics.Numeric
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
||||
internal static unsafe MatrixParallelWrap ScheduleTask<TTask>(nuint computeHandle, MatrixParallelTask* package)
|
||||
where TTask: IPrefetchPredict
|
||||
internal static unsafe MatrixParallelWrap ScheduleTask<TTask>(
|
||||
MatrixParallelThread[] workers,
|
||||
MatrixParallelTask* package
|
||||
) where TTask : IPrefetchPredict
|
||||
{
|
||||
/*
|
||||
int primCount = package->PrimCount;
|
||||
@@ -59,13 +61,10 @@ namespace StgSharp.Mathematics.Numeric
|
||||
|
||||
// Console.WriteLine($"amount of kernels is {count}");
|
||||
|
||||
long recommendCount = /*count / /**/ 1024;
|
||||
MatrixParallelThread[] pool = LeadParallel((int)recommendCount);
|
||||
MatrixParallelWrap wrap = new(pool)
|
||||
return new(workers)
|
||||
{
|
||||
TaskQueue = MatrixParallelQueue.Rent(package)
|
||||
};
|
||||
return wrap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -49,36 +49,16 @@ namespace StgSharp.Mathematics.Numeric
|
||||
|
||||
private static CapacityFixedStack<MatrixParallelThread> _threads;
|
||||
|
||||
private static ConcurrentDictionary<SIMDID, nint> contextMap;
|
||||
|
||||
private static SlabAllocator<IntrinsicContext> contextAllocator;
|
||||
|
||||
public static bool IsParallelSupported { get; } = Environment.ProcessorCount > 6;
|
||||
|
||||
public static bool IsParallelMeaningful => Environment.ProcessorCount > 6 && IsInitialized;
|
||||
public static bool IsParallelMeaningful => (Environment.ProcessorCount > 6) && IsInitialized;
|
||||
|
||||
private static bool IsInitialized { get; set; } = false;
|
||||
|
||||
internal static unsafe IntrinsicContext* GetContext(
|
||||
SIMDID simd
|
||||
)
|
||||
{
|
||||
if (!IsParallelSupported) {
|
||||
return null;
|
||||
}
|
||||
if (contextMap.TryGetValue(simd, out nint handle))
|
||||
{
|
||||
return (IntrinsicContext*)handle;
|
||||
} else
|
||||
{
|
||||
IntrinsicContext* context = (IntrinsicContext*)contextAllocator.Allocate();
|
||||
|
||||
return context;
|
||||
}
|
||||
}
|
||||
private static bool IsInitialized { get; set; }
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
Dictionary<SIMDID, int> contextMap = [];
|
||||
|
||||
if (IsInitialized) {
|
||||
return;
|
||||
}
|
||||
@@ -87,16 +67,15 @@ namespace StgSharp.Mathematics.Numeric
|
||||
IsInitialized = true;
|
||||
return;
|
||||
}
|
||||
MatrixParallelFactory.Init();
|
||||
contextAllocator = SlabAllocator.Create<IntrinsicContext>(4, SlabBufferLayout.Chunked, false);
|
||||
contextMap = [];
|
||||
int count = Environment.ProcessorCount;
|
||||
_threads = new(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
MatrixParallelThread thread = new MatrixParallelThread(i);
|
||||
MatrixParallelThread thread = new(i);
|
||||
_threads.Push(thread);
|
||||
SpinWait.SpinUntil(() => thread.State == MatrixThreadState.Ready);
|
||||
var index = (IsParallelSupported && contextMap.TryGetValue(simd, out int index)) ? index : (-1);
|
||||
}
|
||||
|
||||
// TODO 构建全局的保底上下文
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="MatrixParallelQueue.Concurrent"
|
||||
// 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.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Mathematics.Numeric.Runtime
|
||||
{
|
||||
internal unsafe class ConcurrentPointerQueue
|
||||
{
|
||||
|
||||
private nuint* _current;
|
||||
private int[] _length;
|
||||
private nuint[] _queue;
|
||||
private int _bucketIndex;
|
||||
private int _head;
|
||||
private int _tail;
|
||||
|
||||
public ConcurrentPointerQueue()
|
||||
{
|
||||
_queue = new nuint[8];
|
||||
}
|
||||
|
||||
public void Enqueue(
|
||||
nuint* pointer,
|
||||
int count
|
||||
)
|
||||
{
|
||||
_head++;
|
||||
_head %= _queue.Length;
|
||||
_bucketIndex = 0;
|
||||
_queue[_head] = (nuint)pointer;
|
||||
_length[_head] = count;
|
||||
}
|
||||
|
||||
public int TryDequeue(
|
||||
Span<nuint> span
|
||||
)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="MatrixPredictor"
|
||||
// file="MatrixParallelQueue.Predictor"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
// 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
|
||||
@@ -34,16 +34,6 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Mathematics.Numeric.Runtime
|
||||
{
|
||||
public abstract class MatrixPredictor<TSelf> : IPrefetchPredict where TSelf: MatrixPredictor<TSelf>
|
||||
{
|
||||
|
||||
protected MatrixPredictor() { }
|
||||
|
||||
public abstract bool Predict(Span<CacheLinePrediction> node, out int count);
|
||||
|
||||
public abstract void Prefetch(nuint origin, ulong policy, Span<byte> cache);
|
||||
|
||||
public abstract void WriteBack(nuint origin, ulong policy, ReadOnlySpan<byte> cache);
|
||||
|
||||
}
|
||||
internal interface IMatrixPredictor<TSelf> : IPrefetchPredict
|
||||
where TSelf : unmanaged, IMatrixPredictor<TSelf> { }
|
||||
}
|
||||
|
||||
@@ -50,13 +50,7 @@ namespace StgSharp.Mathematics.Numeric
|
||||
|
||||
public MatrixParallelTask* BaseTask { get; private set; }
|
||||
|
||||
public MatrixElementType ElementType { get; private set; }
|
||||
|
||||
public MatrixIntrinsicHandle Handle { get; private set; }
|
||||
|
||||
public static MatrixParallelQueue Rent(
|
||||
MatrixElementType elementType,
|
||||
MatrixIntrinsicHandle handle,
|
||||
MatrixParallelTask* pack
|
||||
)
|
||||
{
|
||||
@@ -66,8 +60,6 @@ namespace StgSharp.Mathematics.Numeric
|
||||
queue.BaseTask = pack;
|
||||
queue._maxCount = ((ulong)pack->CommonX) * ((ulong)pack->CommonY);
|
||||
queue._cursor = 0;
|
||||
queue.ElementType = elementType;
|
||||
queue.Handle = handle;
|
||||
return queue;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// file="MatrixParallelTask"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
// 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
|
||||
@@ -36,17 +36,18 @@ namespace StgSharp.Mathematics.Numeric.Runtime
|
||||
internal unsafe struct MatrixParallelTask
|
||||
{
|
||||
|
||||
[FieldOffset(0)] public MatrixKernel* Mat1; // 8
|
||||
[FieldOffset(8)] public MatrixKernel* Mat2; // 8
|
||||
[FieldOffset(16)] public MatrixKernel* Mat3; // 16
|
||||
[FieldOffset(40)] public int CommonK;
|
||||
[FieldOffset(32)] public int CommonX;
|
||||
[FieldOffset(36)] public int CommonY;
|
||||
[FieldOffset(44)] public int i;
|
||||
[FieldOffset(48)] public int j;
|
||||
[FieldOffset(52)] public int k;
|
||||
[FieldOffset(56)] public MatrixElementType ElementType; // 56
|
||||
[FieldOffset(24)] public nint Span; // 24
|
||||
[FieldOffset(0)] public MatrixKernel* Mat1;
|
||||
[FieldOffset(8)] public MatrixKernel* Mat2;
|
||||
[FieldOffset(16)] public MatrixKernel* Mat3;
|
||||
[FieldOffset(24)] public int CacheIndex;
|
||||
[FieldOffset(28)] public int CacheLength;
|
||||
[FieldOffset(32)] public int CommonK;
|
||||
[FieldOffset(36)] public int CommonX;
|
||||
[FieldOffset(40)] public int CommonY;
|
||||
[FieldOffset(44)] public int SpanLength;
|
||||
[FieldOffset(48)] public MatrixElementType ElementType;
|
||||
[FieldOffset(52)] public MatrixIntrinsicHandle ComputeHandle;
|
||||
[FieldOffset(56)] public nint Span;
|
||||
[FieldOffset(64)] public ScalarPacket Scalar;
|
||||
|
||||
public MatrixParallelTask()
|
||||
@@ -55,9 +56,13 @@ namespace StgSharp.Mathematics.Numeric.Runtime
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Copy(MatrixParallelTask* source, MatrixParallelTask* target)
|
||||
public static void Copy(
|
||||
MatrixParallelTask* source,
|
||||
MatrixParallelTask* target
|
||||
)
|
||||
{
|
||||
Buffer.MemoryCopy(source, target, sizeof(MatrixParallelTask), sizeof(MatrixParallelTask));
|
||||
Buffer.MemoryCopy(source, target, sizeof(MatrixParallelTask),
|
||||
sizeof(MatrixParallelTask));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -69,10 +69,10 @@ namespace StgSharp.Mathematics.Numeric
|
||||
|
||||
internal ManualResetEventSlim? LeaderEvent { get; set; }
|
||||
|
||||
internal IntrinsicContext* Intrinsic { get; set; }
|
||||
|
||||
internal bool IsSingle { get; set; }
|
||||
|
||||
internal IntrinsicContext Intrinsic { get; private set; }
|
||||
|
||||
internal MatrixParallelWrap BindedWrap { get; set; }
|
||||
|
||||
internal MatrixThreadState State { get; set; }
|
||||
@@ -91,16 +91,6 @@ namespace StgSharp.Mathematics.Numeric
|
||||
_resetEvent.Set();
|
||||
}
|
||||
|
||||
[LibraryImport(Native.LibName, EntryPoint = "sn_get_simd_level_local")]
|
||||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
|
||||
internal static partial ulong GetSimdId();
|
||||
|
||||
[LibraryImport(Native.LibName, EntryPoint = "sn_set_thread_affinity")]
|
||||
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
|
||||
internal static partial void SetThreadAffinity(
|
||||
int coreId
|
||||
);
|
||||
|
||||
protected virtual void Dispose(
|
||||
bool disposing
|
||||
)
|
||||
@@ -125,11 +115,10 @@ namespace StgSharp.Mathematics.Numeric
|
||||
// Bind OS-thread affinity once when the worker starts running
|
||||
SetThreadAffinity(PoolId);
|
||||
_ = Thread.Yield();
|
||||
SIMDID feature = new()
|
||||
{
|
||||
Mask = GetSimdId()
|
||||
};
|
||||
_context = (nint*)MatrixParallel.GetContext(feature);
|
||||
SIMDID feature = new(GetSimdId());
|
||||
int index = MatrixParallel.GetContext(feature);
|
||||
Intrinsic = new IntrinsicContext();
|
||||
if (index > 0) { }
|
||||
State = MatrixThreadState.Ready;
|
||||
while (true)
|
||||
{
|
||||
@@ -171,5 +160,19 @@ namespace StgSharp.Mathematics.Numeric
|
||||
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 = "sn_set_thread_affinity")]
|
||||
[UnmanagedCallConv(CallConvs = [ typeof(CallConvCdecl) ])]
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
|
||||
internal static partial void SetThreadAffinity(
|
||||
int coreId
|
||||
);
|
||||
|
||||
#pragma warning restore CA5393
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user