back to matrix

This commit is contained in:
Youmu Liu
2026-03-23 20:11:08 +08:00
parent 0ac7b2b71f
commit eee88e1098
10 changed files with 100 additions and 179 deletions
+7
View File
@@ -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
}
}