From 06e3aa119b6816483e5c5f749499ad6d20bd1136 Mon Sep 17 00:00:00 2001 From: Youmu Liu <105042599+Nitload-NSI@users.noreply.github.com> Date: Thu, 26 Mar 2026 18:02:13 +0800 Subject: [PATCH] mat --- .../HighPerformance/Memory/L4.Predict.cs | 43 ++++++-- .../HighPerformance/Memory/L4.Prefetch.cs | 6 +- StgSharp.Common/HighPerformance/Memory/L4.cs | 99 ++++++++++--------- StgSharp.Mathematics/Numeric/Linear/Matrix.cs | 30 +++--- .../Linear/MatrixCompute.Sequential.cs | 32 ++++-- .../Runtime/MatrixParallel.AwaitingQueue.cs | 2 +- .../Numeric/Runtime/MatrixParallel.Publish.cs | 2 +- .../Numeric/Runtime/MatrixParallel.Source.cs | 17 ---- .../Runtime/MatrixParallelQueue.Predictor.cs | 14 ++- .../Numeric/Runtime/MatrixParallelQueue.cs | 9 +- .../Numeric/Runtime/MatrixParallelThread.cs | 26 +++-- .../Numeric/Runtime/MatrixParallelWrap.cs | 21 ++-- StgSharp.Native/StgSharp.Native.vcxproj | 2 +- .../StgSharp.Native.vcxproj.filters | 2 +- .../{m.basic.x86.c => m.transpose.x86.c} | 0 StgSharp.Native/sn-src/simdid.x86.c | 21 +--- .../View/PresentorDescription.cs | 4 +- StgSharpDebug/TestL4.cs | 4 +- StgSharpDebug/TestL4Behaviour.cs | 17 ++-- StgSharpDebug/TestL4Prefetch.cs | 16 +-- 20 files changed, 198 insertions(+), 169 deletions(-) delete mode 100644 StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.Source.cs rename StgSharp.Native/sn-src/{m.basic.x86.c => m.transpose.x86.c} (100%) diff --git a/StgSharp.Common/HighPerformance/Memory/L4.Predict.cs b/StgSharp.Common/HighPerformance/Memory/L4.Predict.cs index 388f7fa3..7497b0f6 100644 --- a/StgSharp.Common/HighPerformance/Memory/L4.Predict.cs +++ b/StgSharp.Common/HighPerformance/Memory/L4.Predict.cs @@ -33,9 +33,11 @@ using System.Threading.Tasks; namespace StgSharp.HighPerformance.Memory { - public interface IPrefetchPredict + public interface IL4Predict { + bool IsExhausted { get; } + /// /// Writes predicted cache line descriptors into . /// @@ -43,17 +45,20 @@ namespace StgSharp.HighPerformance.Memory /// Prediction output buffer. /// /// - /// When this method returns, contains the number of valid entries written to . The value must not exceed .Length. /// /// /// if any prediction data was produced; otherwise, . /// - bool Predict(Span node, out int count); + bool Predict( + Span node, + out int count + ); /// - /// Materializes the cache line identified by into into . /// /// @@ -65,7 +70,11 @@ namespace StgSharp.HighPerformance.Memory /// /// Destination cache line buffer. /// - void Prefetch(nuint origin, ulong policy, Span cache); + void Prefetch( + nuint origin, + ulong policy, + Span cache + ); /// /// Writes the cache line in back to . @@ -79,21 +88,29 @@ namespace StgSharp.HighPerformance.Memory /// /// Source cache line buffer. /// - void WriteBack(nuint origin, ulong policy, ReadOnlySpan cache); + void WriteBack( + nuint origin, + ulong policy, + ReadOnlySpan cache + ); } public struct CacheLinePrediction : IEquatable { - public override readonly bool Equals(object? obj) + public override readonly bool Equals( + object? obj + ) { return obj is CacheLinePrediction prediction && Address.Equals(prediction.Address) && MapPolicy == prediction.MapPolicy; } - public readonly bool Equals(CacheLinePrediction other) + public readonly bool Equals( + CacheLinePrediction other + ) { return Address == other.Address && MapPolicy == other.MapPolicy; @@ -104,11 +121,17 @@ namespace StgSharp.HighPerformance.Memory return HashCode.Combine(Address, MapPolicy); } - public static bool operator !=(CacheLinePrediction left, CacheLinePrediction right) + public static bool operator !=( + CacheLinePrediction left, + CacheLinePrediction right + ) { return !(left == right); } - public static bool operator ==(CacheLinePrediction left, CacheLinePrediction right) + public static bool operator ==( + CacheLinePrediction left, + CacheLinePrediction right + ) { return left.Equals(right); } diff --git a/StgSharp.Common/HighPerformance/Memory/L4.Prefetch.cs b/StgSharp.Common/HighPerformance/Memory/L4.Prefetch.cs index 540d5a48..52204682 100644 --- a/StgSharp.Common/HighPerformance/Memory/L4.Prefetch.cs +++ b/StgSharp.Common/HighPerformance/Memory/L4.Prefetch.cs @@ -43,7 +43,9 @@ namespace StgSharp.HighPerformance.Memory throw new OverflowException("Too many activated cache line in external reference."); } Span span = new(_prediction, PredictionCount); - if (!(PrefetchPredict.Predict(span, out int actualCount) && actualCount > 0)) { + if (!PrefetchPredict.Predict(span, out int actualCount) && (actualCount <= 0)) + { + _exhausted = true; return; } int missIndex = 0; @@ -85,7 +87,7 @@ namespace StgSharp.HighPerformance.Memory head->_origin = address; head->_profile = handle.MapPolicy; head->_refCount = 0; - head->_address = (nuint)(&_data[index]); + head->_address = nuint & _data[index]; // pre fetch them here PrefetchPredict.Prefetch(head->_origin, head->_profile, new Span((byte*)head->_address, Unsafe.SizeOf())); diff --git a/StgSharp.Common/HighPerformance/Memory/L4.cs b/StgSharp.Common/HighPerformance/Memory/L4.cs index 734e113f..92bbd0b8 100644 --- a/StgSharp.Common/HighPerformance/Memory/L4.cs +++ b/StgSharp.Common/HighPerformance/Memory/L4.cs @@ -39,7 +39,6 @@ namespace StgSharp.HighPerformance.Memory private const int PredictionLeastAhead = 1024; private readonly CacheLineData* _data; - private readonly EvictionArray* _eviction; private readonly CacheLineHead* _head; private readonly CacheLinePrediction* _prediction; @@ -57,12 +56,12 @@ namespace StgSharp.HighPerformance.Memory public L4() { // init order is fallow by align requirement of each component. - nuint cacheSize = (nuint)Unsafe.SizeOf() * CacheLineCount; // SIMDID, no less than 16 byte bit - nuint entrySize = (nuint)Unsafe.SizeOf() * CacheLineCount; // 16 byte align - nuint predictionSize = (nuint)Unsafe.SizeOf() * PredictionCount; //16 byte align + nuint cacheSize = ((nuint)Unsafe.SizeOf()) * CacheLineCount; // SIMDID, no less than 16 byte bit + nuint entrySize = ((nuint)Unsafe.SizeOf()) * CacheLineCount; // 16 byte align + nuint predictionSize = ((nuint)Unsafe.SizeOf()) * PredictionCount; //16 byte align nuint mapSize = (nuint)SwissTable.RequestedNativeMemorySize; // 16 byte align nuint rrpvSize = (nuint)Unsafe.SizeOf(); // 16 byte align - nuint stackSize = (nuint)sizeof(int) * CacheLineCount; // int align + nuint stackSize = ((nuint)sizeof(int)) * CacheLineCount; // int align // malloc all memory at once, and free at once in Dispose. // This is to avoid fragmentation and improve performance. @@ -85,7 +84,17 @@ namespace StgSharp.HighPerformance.Memory ptr += stackSize; } - public IPrefetchPredict PrefetchPredict { get; set; } + public IL4Predict PrefetchPredict { get; set; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ContinueOnce( + L4CacheLine line + ) + { + if (line.Address > 0) { + _ = Interlocked.Decrement(ref _aheadCount); + } + } [System.Diagnostics.CodeAnalysis.SuppressMessage( "Design", @@ -108,11 +117,11 @@ namespace StgSharp.HighPerformance.Memory } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CacheLine Map( - nuint origin + public L4CacheLine Map( + nuint origin ) { - if (_aheadCount < PredictionLeastAhead) + if ((_aheadCount < PredictionLeastAhead) && !PrefetchPredict.IsExhausted) { if (Interlocked.CompareExchange(ref _prefetching, 1, 0) == 0) { @@ -141,7 +150,7 @@ namespace StgSharp.HighPerformance.Memory (*_eviction)[entry->_id] = 0; _ = Interlocked.Increment(ref _activeCount); _ = Interlocked.Decrement(ref _aheadCount); - return new CacheLine(entry->_address, ref _activeCount, ref entry->_refCount); + return new L4CacheLine(entry->_address, ref _activeCount, ref entry->_refCount); } else { _ = Interlocked.Decrement(ref entry->_refCount); @@ -157,41 +166,6 @@ namespace StgSharp.HighPerformance.Memory nuint origin ); - public ref struct CacheLine : IDisposable - { - - private ref int _activeCount; - private ref int _refCount; - private nuint _handle; - - internal CacheLine( - nuint handle, - ref int activeCount, - ref int cacheRefCount - ) - { - _handle = handle; - _refCount = ref cacheRefCount; - _activeCount = ref activeCount; - } - - [Obsolete("You should not create a CacheLineHandle outside a L4", true)] - public CacheLine() { } - - public nuint Address => _handle; - - public void Dispose() - { - if (_handle == 0) { - return; - } - _handle = 0; - _ = Interlocked.Decrement(ref _activeCount); - _ = Interlocked.Decrement(ref _refCount); - } - - } - private struct CacheLineData { @@ -200,4 +174,39 @@ namespace StgSharp.HighPerformance.Memory } } + + public ref struct L4CacheLine : IDisposable + { + + private ref int _activeCount; + private ref int _refCount; + private nuint _handle; + + internal L4CacheLine( + nuint handle, + ref int activeCount, + ref int cacheRefCount + ) + { + _handle = handle; + _refCount = ref cacheRefCount; + _activeCount = ref activeCount; + } + + [Obsolete("You should not create a CacheLineHandle outside a L4", true)] + public L4CacheLine() { } + + public readonly nuint Address => _handle; + + public void Dispose() + { + if (_handle == 0) { + return; + } + _handle = 0; + _ = Interlocked.Decrement(ref _activeCount); + _ = Interlocked.Decrement(ref _refCount); + } + + } } diff --git a/StgSharp.Mathematics/Numeric/Linear/Matrix.cs b/StgSharp.Mathematics/Numeric/Linear/Matrix.cs index 7a084c8b..d584c84a 100644 --- a/StgSharp.Mathematics/Numeric/Linear/Matrix.cs +++ b/StgSharp.Mathematics/Numeric/Linear/Matrix.cs @@ -64,7 +64,10 @@ namespace StgSharp.Mathematics.Numeric { get { - if (y < 0 || y > _size.ElementColumnLength || x < 0 || x > _size.ElementRowLength) { + if ((y < 0) || + (y > _size.ElementColumnLength) || + (x < 0) || + (x > _size.ElementRowLength)) { throw new ArgumentOutOfRangeException($"Index [{x},{y}] is out of matrix index range."); } long offset = GetElementOffset(x, y); @@ -75,7 +78,10 @@ namespace StgSharp.Mathematics.Numeric } set { - if (y < 0 || y > _size.ElementColumnLength || x < 0 || x > _size.ElementRowLength) { + if ((y < 0) || + (y > _size.ElementColumnLength) || + (x < 0) || + (x > _size.ElementRowLength)) { throw new ArgumentOutOfRangeException($"Index [{x},{y}] is out of matrix index range."); } long offset = GetElementOffset(x, y); @@ -106,8 +112,8 @@ namespace StgSharp.Mathematics.Numeric ReadOnlySpan row ] { - get { throw new NotImplementedException(); } - set { throw new NotImplementedException(); } + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); } /// @@ -122,11 +128,7 @@ namespace StgSharp.Mathematics.Numeric public MatrixLayout Layout { get; init; } - internal MatrixKernel* Buffer - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => (MatrixKernel*)_buffer.BufferPointer; - } + internal MatrixKernel* Buffer => (MatrixKernel*)_buffer.BufferPointer; protected internal int KernelColumnLength => _size.KernelColumnLength; @@ -138,9 +140,9 @@ namespace StgSharp.Mathematics.Numeric int y ) { - return ref _boarder.IsInBuffer(x, y, in _size) ? - ref _buffer[_boarder.GetIndexOffset(x, y, in _size)] : - ref Unsafe.NullRef>(); + return ref (_boarder.IsInBuffer(x, y, in _size) ? + ref _buffer[_boarder.GetIndexOffset(x, y, in _size)] : + ref Unsafe.NullRef>()); } internal long GetElementOffset( @@ -158,7 +160,7 @@ namespace StgSharp.Mathematics.Numeric } long kernelOffset = _boarder.GetIndexOffset(k_r, k_c, in _size); - return kernelOffset * 16 + 4 * r + c; + return (kernelOffset * 16) + (4 * r) + c; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -195,8 +197,6 @@ namespace StgSharp.Mathematics.Numeric // Caller guarantees: indices in range, layout is dense square. int k_c = y / 4; int k_r = x / 4; - int c = y % 4; - int r = x % 4; return ref _buffer[_boarder.GetIndexOffset(k_c, k_r, in _size)]; } diff --git a/StgSharp.Mathematics/Numeric/Linear/MatrixCompute.Sequential.cs b/StgSharp.Mathematics/Numeric/Linear/MatrixCompute.Sequential.cs index f9078d74..3b3c4be5 100644 --- a/StgSharp.Mathematics/Numeric/Linear/MatrixCompute.Sequential.cs +++ b/StgSharp.Mathematics/Numeric/Linear/MatrixCompute.Sequential.cs @@ -30,6 +30,7 @@ using StgSharp.Mathematics.Numeric.Runtime; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; @@ -71,34 +72,45 @@ namespace StgSharp.Mathematics.Numeric.Linear t->Mat1 = (MatrixKernel*)leftPtr; t->Mat2 = (MatrixKernel*)rightPtr; t->Mat3 = (MatrixKernel*)ansPtr; - t->ElementType = MatrixElementType.F64; + t->ElementType = f32; + t->ComputeHandle = MatrixIntrinsicHandle.Add; t->Scalar.Data(0) = count; + SequentialOperation(t, count); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void SequentialOperation( + MatrixParallelTask* task, + long count + ) + { + MatrixElementType elementType = task->ElementType; MatrixParallelThread[] pool; + MkProc op = (MkProc)NumericalModule.GlobalContext. + mat_mk[elementType.IntrinsicNode]. + Get(task->ComputeHandle); if (count <= 256) { - add(t); - - // .buffer_add(leftPtr, rightPtr, ansPtr, count); - + op(task); return; } else if (count <= 1024) { pool = MatrixParallel.LeadParallel(1); - add(t); + op(task); MatrixParallel.ReturnParallelResources(ref pool); return; } - pool = MatrixParallel.LeadParallel((int)(count / 1024)); - MatrixParallelWrap taskGroup = MatrixParallel.ScheduleTask(pool, t); - + pool = MatrixParallel.LeadParallel(count / 1024); + MatrixParallelWrap taskGroup = MatrixParallel.ScheduleTask(pool, task); taskGroup.LaunchParallel(SleepMode.DeepSleep); taskGroup.Dispose(); - return; } private struct SequentialPredictor : IMatrixPredictor { + public static PredictPolicy Policy => PredictPolicy.Sequential; + public bool Predict( Span node, out int count diff --git a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.AwaitingQueue.cs b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.AwaitingQueue.cs index fbbcc8e1..e82be8a3 100644 --- a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.AwaitingQueue.cs +++ b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.AwaitingQueue.cs @@ -45,7 +45,7 @@ namespace StgSharp.Mathematics.Numeric private class AwaitingQueue { - private Element _quickElements = new(); + private Element _quickElements; private volatile int _count; private readonly Queue _fallback = []; diff --git a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.Publish.cs b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.Publish.cs index 7a1c9d65..c170defe 100644 --- a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.Publish.cs +++ b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.Publish.cs @@ -51,7 +51,7 @@ namespace StgSharp.Mathematics.Numeric internal static unsafe MatrixParallelWrap ScheduleTask( MatrixParallelThread[] workers, MatrixParallelTask* package - ) where TTask : IPrefetchPredict + ) where TTask : IL4Predict { /* int primCount = package->PrimCount; diff --git a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.Source.cs b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.Source.cs deleted file mode 100644 index 7939a38b..00000000 --- a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallel.Source.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace StgSharp.Mathematics.Numeric.Runtime -{ - internal class MatrixParallel - { - - - public MatrixParallelTask BaseTask { get; set; } - public - - } -} diff --git a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelQueue.Predictor.cs b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelQueue.Predictor.cs index 0575feb1..a96ef1d5 100644 --- a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelQueue.Predictor.cs +++ b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelQueue.Predictor.cs @@ -34,6 +34,16 @@ using System.Threading.Tasks; namespace StgSharp.Mathematics.Numeric.Runtime { - internal interface IMatrixPredictor : IPrefetchPredict - where TSelf : unmanaged, IMatrixPredictor { } + internal interface IMatrixPredictor : IL4Predict + where TSelf : unmanaged, IMatrixPredictor + { + static abstract PredictPolicy Policy { get; } + + } + + internal enum PredictPolicy + { + Transparent = 0, + Sequential = 1, + } } diff --git a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelQueue.cs b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelQueue.cs index 362c618c..94de2561 100644 --- a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelQueue.cs +++ b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelQueue.cs @@ -43,22 +43,23 @@ namespace StgSharp.Mathematics.Numeric { private static readonly ConcurrentStack _recycle = []; - private ulong _cursor; - private ulong _maxCount; + private long _cursor; + private long _maxCount; private MatrixParallelQueue() { } public MatrixParallelTask* BaseTask { get; private set; } public static MatrixParallelQueue Rent( - MatrixParallelTask* pack + MatrixParallelTask* pack, + long count ) { if (!_recycle.TryPop(out MatrixParallelQueue? queue)) { queue = new MatrixParallelQueue(); } queue.BaseTask = pack; - queue._maxCount = ((ulong)pack->CommonX) * ((ulong)pack->CommonY); + queue._maxCount = count; queue._cursor = 0; return queue; } diff --git a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelThread.cs b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelThread.cs index c4c0aa52..2aa539f7 100644 --- a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelThread.cs +++ b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelThread.cs @@ -49,7 +49,8 @@ namespace StgSharp.Mathematics.Numeric { private IntrinsicContext* _context; - private volatile bool _disposed, _isRetireRequested = false; + private MatrixParallelTask* _currentTask; + private volatile bool _disposed, _isRetireRequested ; private readonly ManualResetEventSlim _resetEvent; private readonly Thread _managedThread; @@ -67,8 +68,6 @@ namespace StgSharp.Mathematics.Numeric public ThreadPriority AfterWork { get; set; } - internal ManualResetEventSlim? LeaderEvent { get; set; } - internal ref readonly IntrinsicContext Intrinsic => ref (*_context); internal bool IsSingle { get; set; } @@ -91,6 +90,16 @@ namespace StgSharp.Mathematics.Numeric _resetEvent.Set(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void SetSingleThreadTask( + ref MatrixParallelTask task + ) + { + if (IsSingle) { + *_currentTask = task; + } + } + protected virtual void Dispose( bool disposing ) @@ -117,6 +126,7 @@ namespace StgSharp.Mathematics.Numeric _ = Thread.Yield(); SIMDID feature = new(GetSimdId()); IntrinsicContext* contextPtr = stackalloc IntrinsicContext[1]; + MatrixParallelTask* taskPtr = stackalloc MatrixParallelTask[4]; LoadIntrinsicFunction(contextPtr, feature.Mask); _context = contextPtr; State = MatrixThreadState.Ready; @@ -134,11 +144,11 @@ namespace StgSharp.Mathematics.Numeric _managedThread.Priority = ThreadPriority.Highest; if (IsSingle) { - // TODO 将外部线程绑定到当前线程上,并执行任务包 + MatrixParallelTask* outer = _currentTask; + IsSingle = false; } else { MatrixParallelQueue taskQueue = BindedWrap.TaskQueue; - MatrixParallelTask* p = taskQueue.BaseTask; /* if (0 > (int)p ->ComputeHandle) { SpecialBufferCompute(p); @@ -162,19 +172,19 @@ namespace StgSharp.Mathematics.Numeric #pragma warning disable CA5393 [LibraryImport(Native.LibName, EntryPoint = "sn_get_simd_level_local")] - [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvCdecl) ])] [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)] internal static partial ulong GetSimdId(); [LibraryImport(Native.LibName, EntryPoint = "sn_set_thread_affinity")] - [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvCdecl) ])] [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)] internal static partial void SetThreadAffinity( int coreId ); [LibraryImport(Native.LibName, EntryPoint = "load_intrinsic_function")] - [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] + [UnmanagedCallConv(CallConvs = [ typeof(CallConvCdecl) ])] [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)] private static unsafe partial void LoadIntrinsicFunction( IntrinsicContext* context, diff --git a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelWrap.cs b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelWrap.cs index c6f8f51a..b4daf9da 100644 --- a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelWrap.cs +++ b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelWrap.cs @@ -26,6 +26,7 @@ // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- using StgSharp.Collections; +using StgSharp.HighPerformance.Memory; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; @@ -59,25 +60,16 @@ namespace StgSharp.Mathematics.Numeric ) { _threads = threadArray; - IsMultithread = threadArray.Length > 1; _countdownEvent = new CountdownEvent(threadArray.Length); } - public ReadOnlySpan Threads - { - get - { - ObjectDisposedException.ThrowIf(_disposed, nameof(MatrixParallelWrap)); - - return _threads; - } - } + public ReadOnlySpan Threads => _disposed ? [] : _threads; public ThreadPriority AfterWork { get; private set; } - internal MatrixParallelQueue TaskQueue { get; set; } + internal L4 DataCache { get; set; } - private bool IsMultithread { get; init; } + internal MatrixParallelQueue TaskQueue { get; set; } public void Dispose() { @@ -90,6 +82,7 @@ namespace StgSharp.Mathematics.Numeric SleepMode afterWork ) { + ObjectDisposedException.ThrowIf(_disposed, nameof(MatrixParallelWrap)); AfterWork = (ThreadPriority)afterWork; foreach (MatrixParallelThread thread in _threads) { @@ -101,7 +94,9 @@ namespace StgSharp.Mathematics.Numeric public void WaitAllWraps() { - ObjectDisposedException.ThrowIf(_disposed, nameof(MatrixParallelWrap)); + if (_disposed) { + return; + } _countdownEvent.Wait(); } diff --git a/StgSharp.Native/StgSharp.Native.vcxproj b/StgSharp.Native/StgSharp.Native.vcxproj index 215167c9..65b3a599 100644 --- a/StgSharp.Native/StgSharp.Native.vcxproj +++ b/StgSharp.Native/StgSharp.Native.vcxproj @@ -172,7 +172,7 @@ - + diff --git a/StgSharp.Native/StgSharp.Native.vcxproj.filters b/StgSharp.Native/StgSharp.Native.vcxproj.filters index b2ea2a86..f0b379d9 100644 --- a/StgSharp.Native/StgSharp.Native.vcxproj.filters +++ b/StgSharp.Native/StgSharp.Native.vcxproj.filters @@ -39,7 +39,7 @@ 源文件 - + 源文件 diff --git a/StgSharp.Native/sn-src/m.basic.x86.c b/StgSharp.Native/sn-src/m.transpose.x86.c similarity index 100% rename from StgSharp.Native/sn-src/m.basic.x86.c rename to StgSharp.Native/sn-src/m.transpose.x86.c diff --git a/StgSharp.Native/sn-src/simdid.x86.c b/StgSharp.Native/sn-src/simdid.x86.c index 84dacc9c..f35f350b 100644 --- a/StgSharp.Native/sn-src/simdid.x86.c +++ b/StgSharp.Native/sn-src/simdid.x86.c @@ -141,7 +141,7 @@ SN_API SIMDID SN_DECL sn_get_simd_level_local() const int is_amd = (strcmp(vendor, "AuthenticAMD") == 0); const int is_hygon = (strcmp(vendor, "HygonGenuine") == 0); const int is_centaur = (strcmp(vendor, "CentaurHauls") == 0); - const int is_zhaoxin = (memcmp(vendor, " Shanghai ", 12) == 0); + const int is_zhaoxin = (strcmp(vendor, " Shanghai ") == 0); const int is_via = is_centaur || is_zhaoxin; get_cpuid(1, 0, &eax, &ebx, &ecx, &edx); @@ -350,23 +350,4 @@ SN_API SIMDID SN_DECL sn_get_simd_level_global() return global_simdid; } -#else - -SN_API SIMDID SN_DECL sn_get_simd_level_local() -{ - SIMDID simdid; - simdid.mask = 0; - return simdid; -} - -SN_API SIMDID SN_DECL sn_get_simd_level_global() -{ - if (global_simdid.mask) { - return global_simdid; - } - - global_simdid = sn_get_simd_level_local(); - return global_simdid; -} - #endif diff --git a/StgSharp.UserInterface/View/PresentorDescription.cs b/StgSharp.UserInterface/View/PresentorDescription.cs index f4139202..0925443c 100644 --- a/StgSharp.UserInterface/View/PresentorDescription.cs +++ b/StgSharp.UserInterface/View/PresentorDescription.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace StgSharp.UnserInterface.View { - internal class PresentorDescription + internal class PresenterDescription { } } diff --git a/StgSharpDebug/TestL4.cs b/StgSharpDebug/TestL4.cs index 4c3134fd..315a9c6c 100644 --- a/StgSharpDebug/TestL4.cs +++ b/StgSharpDebug/TestL4.cs @@ -38,7 +38,7 @@ namespace StgSharp // 仅供 L4 内存安全测试使用。 // ==================================================================== - internal sealed unsafe class SequentialPredictor : IPrefetchPredict + internal sealed unsafe class SequentialPredictor : IL4Predict { private readonly nuint[] _addresses; @@ -313,7 +313,7 @@ namespace StgSharp { nuint[] result = new nuint[count]; for (int i = 0; i < count; i++) { - result[i] = (nuint)(0x1_0000_0000UL + (ulong)i * 0x1000); + result[i] = (nuint)(0x1_0000_0000UL + (((ulong)i) * 0x1000)); } return result; } diff --git a/StgSharpDebug/TestL4Behaviour.cs b/StgSharpDebug/TestL4Behaviour.cs index fe8002ae..c01acba1 100644 --- a/StgSharpDebug/TestL4Behaviour.cs +++ b/StgSharpDebug/TestL4Behaviour.cs @@ -40,7 +40,7 @@ namespace StgSharp // WriteBack 记录被回写的 origin,供驱逐测试断言。 // ==================================================================== - internal sealed unsafe class TrackingPredictor : IPrefetchPredict + internal sealed unsafe class TrackingPredictor : IL4Predict { private readonly nuint[] _addresses; @@ -128,7 +128,10 @@ namespace StgSharp private static unsafe byte L4ReadFirstByte( L4.CacheLine line - ) => *(byte*)line.Address; + ) + { + return *(byte*)line.Address; + } // ================================================================ // P1-2 AgeAll_SaturatesAt3 @@ -168,7 +171,7 @@ namespace StgSharp for (int i = 0; i < snap.MaxId; i++) { L4Assert( snap.RrpvSnapshot[i] == 0, - $"RrpvSnapshot[{i}] should be 0 right after Map, " + $"got {snap.RrpvSnapshot[i]}"); + $"{$"RrpvSnapshot[{i}] should be 0 right after Map, "}{$"got {snap.RrpvSnapshot[i]}"}"); } } @@ -191,7 +194,7 @@ namespace StgSharp if (snap.RrpvSnapshot[i] != 3) { L4Assert(false, - $"RrpvSnapshot[{i}] == {snap.RrpvSnapshot[i]}, " + "expected 3 after 4x AgeAll (saturation failure or overflow)"); + $"{$"RrpvSnapshot[{i}] == {snap.RrpvSnapshot[i]}, "}expected 3 after 4x AgeAll (saturation failure or overflow)"); allSaturated = false; } } @@ -305,7 +308,7 @@ namespace StgSharp } L4Assert( evictedOrigin != nuint.Zero, - $"WriteBack origin should be a batch1 address, " + $"WriteBackLog=[{string.Join(", ", predictor2.WriteBackLog)}]"); + $"{$"WriteBack origin should be a batch1 address, "}{($"WriteBackLog=[{string.Join(", ", predictor2.WriteBackLog)}]")}"); // 断言 c: SwissTable 中已不含该 origin L4Assert( @@ -320,11 +323,11 @@ namespace StgSharp remapped.Dispose(); L4Assert( refill == 0xCC, - $"Re-mapped evicted line should be re-prefetched with 0xCC, " + $"got 0x{refill:X2} (0xAA = stale data not evicted)"); + $"{$"Re-mapped evicted line should be re-prefetched with 0xCC, "}{($"got 0x{refill:X2} (0xAA = stale data not evicted)")}"); if (_l4FailCount == 0) { Console.WriteLine( - $"PASS (evicted 0x{evictedOrigin:X}, remain={remain}, " + $"WriteBack×{predictor2.WriteBackLog.Count})"); + $"{($"PASS (evicted 0x{evictedOrigin:X}, remain={remain}, ")}{$"WriteBack×{predictor2.WriteBackLog.Count})"}"); } } catch (Exception ex) diff --git a/StgSharpDebug/TestL4Prefetch.cs b/StgSharpDebug/TestL4Prefetch.cs index 9b8af875..4868ae8d 100644 --- a/StgSharpDebug/TestL4Prefetch.cs +++ b/StgSharpDebug/TestL4Prefetch.cs @@ -40,7 +40,7 @@ namespace StgSharp // 用于 P2-2 验证"预填充后 Map 命中不触发二次 Prefetch"。 // ==================================================================== - internal sealed class CountingPredictor : IPrefetchPredict + internal sealed class CountingPredictor : IL4Predict { private readonly nuint[] _addresses; @@ -158,7 +158,7 @@ namespace StgSharp L4.DebugSnapshot snap = l4.GetDebugSnapshot(); Console.WriteLine(); Console.WriteLine( - $" [diag] after warm-up: MaxId={snap.MaxId}, " + $"AheadCount={snap.AheadCount}, " + $"Predict×{predictAfterWarmup}, " + $"Prefetch×{prefetchAfterWarmup}"); + $"{$" [diag] after warm-up: MaxId={snap.MaxId}, "}{$"AheadCount={snap.AheadCount}, "}{$"Predict×{predictAfterWarmup}, "}{$"Prefetch×{prefetchAfterWarmup}"}"); } // 断言 c(warm-up 后):所有 K 条地址均在缓存中 @@ -195,7 +195,7 @@ namespace StgSharp { L4.DebugSnapshot snap = l4.GetDebugSnapshot(); Console.WriteLine( - $" [diag] after {K}x Map: AheadCount={snap.AheadCount}, " + $"Predict×{predictAfterMaps}, " + $"Prefetch×{prefetchAfterMaps}"); + $"{$" [diag] after {K}x Map: AheadCount={snap.AheadCount}, "}{$"Predict×{predictAfterMaps}, "}{$"Prefetch×{prefetchAfterMaps}"}"); } // 断言 b: 已缓存的行不会被重新装填(Prefetch(line) 调用次数不增加) @@ -204,15 +204,15 @@ namespace StgSharp // 这是预期行为,不断言 Predict 次数。 L4Assert( prefetchAfterMaps == prefetchAfterWarmup, - $"Prefetch(line) should not be called again for already-cached addresses, " + $"was {prefetchAfterWarmup} after warm-up, now {prefetchAfterMaps}"); + $"{$"Prefetch(line) should not be called again for already-cached addresses, "}{$"was {prefetchAfterWarmup} after warm-up, now {prefetchAfterMaps}"}"); // Predict 增加是正常的,仅打印供参考 Console.WriteLine( - $" [info] Predict called {predictAfterMaps - predictAfterWarmup} " + $"extra time(s) during {K}x Map " + $"(aheadCount stays below threshold=1024 " + $"because K={K} << 1024, re-prediction is expected)"); + $"{$" [info] Predict called {predictAfterMaps - predictAfterWarmup} "}{$"extra time(s) during {K}x Map "}{$"(aheadCount stays below threshold=1024 "}{$"because K={K} << 1024, re-prediction is expected)"}"); if (_l4FailCount == 0) { Console.WriteLine( - $"PASS (K={K}, all hits, no re-prefetch, " + $"Prefetch×{prefetchAfterMaps})"); + $"{$"PASS (K={K}, all hits, no re-prefetch, "}{$"Prefetch×{prefetchAfterMaps})"}"); } } catch (Exception ex) @@ -284,7 +284,7 @@ namespace StgSharp // 此处仅记录行为,不判定 FAIL——但打印出来供后续决策参考。 Console.WriteLine( evictThrew ? - "PASS (DebugEvict with null Predictor threw NullRef as expected " + "— caller is responsible for null check per trusted-call model)" : + ("PASS (DebugEvict with null Predictor threw NullRef as expected " + "— caller is responsible for null check per trusted-call model)") : "PASS (DebugEvict with null Predictor did not throw)"); // 核心断言:Prefetch() 本身在 null Predictor 时不崩溃 @@ -300,7 +300,7 @@ namespace StgSharp L4.DebugSnapshot snap = l4b.GetDebugSnapshot(); Console.WriteLine( - $" [info] AheadCount after warm-up = {snap.AheadCount} " + $"(Prefetch triggers when < 1024)"); + $"{$" [info] AheadCount after warm-up = {snap.AheadCount} "}{$"(Prefetch triggers when < 1024)"}"); // Prefetch 的 null 检查测试:直接调用 DebugPrefetch(如已暴露) // 当前 Debug 接口未暴露 DebugPrefetch,改为间接验证: