diff --git a/.cr/personal/Editor/Painting/Structural Highlighting.xml b/.cr/personal/Editor/Painting/Structural Highlighting.xml deleted file mode 100644 index 347228e8..00000000 --- a/.cr/personal/Editor/Painting/Structural Highlighting.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - False - - \ No newline at end of file diff --git a/StgSharp.Common/Internal/Intrinsic/IntrinsicContext.cs b/StgSharp.Common/Internal/Intrinsic/IntrinsicContext.cs index 2ae48623..e3830279 100644 --- a/StgSharp.Common/Internal/Intrinsic/IntrinsicContext.cs +++ b/StgSharp.Common/Internal/Intrinsic/IntrinsicContext.cs @@ -38,16 +38,19 @@ namespace StgSharp.Internal.Intrinsic internal unsafe struct IntrinsicContext { - public delegate* unmanaged[Cdecl] city_hash_simplify; - public delegate* unmanaged[Cdecl] f32_add; - public delegate* unmanaged[Cdecl] f32_fill; - public delegate* unmanaged[Cdecl] f32_fma; - public delegate* unmanaged[Cdecl] f32_scalar_mul; - public delegate* unmanaged[Cdecl] f32_sub; - public delegate* unmanaged[Cdecl] f32_transpose; - public delegate* unmanaged[Cdecl] factorial_simd; - public delegate* unmanaged[Cdecl] index_pair; - public delegate* unmanaged[Cdecl] normalize_3; + public delegate* unmanaged[Cdecl] city_hash_simplify; //city_hash_simplify + public delegate* unmanaged[Cdecl] f32_buffer_add; //f32_buffer_add + public delegate* unmanaged[Cdecl] f32_buffer_fill; //f32_buffer_fill + public delegate* unmanaged[Cdecl] f32_buffer_scalar_mul; //f32_buffer_s_m + public delegate* unmanaged[Cdecl] f32_buffer_sub; //f32_kernel_sub + public delegate* unmanaged[Cdecl] f32_buffer_transpose; //f32_kernel_transpose + public delegate* unmanaged[Cdecl] f32_build_panel; //f32_build_panel + public delegate* unmanaged[Cdecl] f32_normalize_3; //f32_normalize_3 + public delegate* unmanaged[Cdecl] f32_panel_fma; //f32_panel_fma + public delegate* unmanaged[Cdecl] f32_store_panel; //f32_store_panel + public delegate* unmanaged[Cdecl] factorial_simd; //factorial_simd + public delegate* unmanaged[Cdecl] index_pair; //index_pair + public delegate* unmanaged[Cdecl] variant ; //variant public IntrinsicContext() { diff --git a/StgSharp.Common/Mathematics/Graphic/Matrix44.cs b/StgSharp.Common/Mathematics/Graphic/Matrix44.cs index 194f4f09..48c55340 100644 --- a/StgSharp.Common/Mathematics/Graphic/Matrix44.cs +++ b/StgSharp.Common/Mathematics/Graphic/Matrix44.cs @@ -185,7 +185,7 @@ namespace StgSharp.Mathematics.Graphic mat.transpose.colum2 = rowSpan[2].vec; mat.transpose.colum3 = rowSpan[3].vec; - NativeIntrinsic.Intrinsic.f32_transpose(&mat.transpose, &mat.mat); + NativeIntrinsic.Intrinsic.f32_buffer_transpose(&mat.transpose, &mat.mat); mat.isTransposed = false; return mat; } @@ -208,7 +208,7 @@ namespace StgSharp.Mathematics.Graphic if (!isTransposed) { fixed (ColumnSet4* source = &mat, target = &transpose) { - NativeIntrinsic.Intrinsic.f32_transpose(source, target); + NativeIntrinsic.Intrinsic.f32_buffer_transpose(source, target); } isTransposed = true; } @@ -218,7 +218,7 @@ namespace StgSharp.Mathematics.Graphic public static unsafe Matrix44 operator -(Matrix44 left, Matrix44 right) { Matrix44 ret = new(); - NativeIntrinsic.Intrinsic.f32_sub(&left, &right, &ret, 1); + NativeIntrinsic.Intrinsic.f32_buffer_sub(&left, &right, &ret, 1); return ret; } @@ -260,7 +260,7 @@ namespace StgSharp.Mathematics.Graphic public static unsafe Matrix44 operator +(Matrix44 left, Matrix44 right) { Matrix44 ret = new(); - NativeIntrinsic.Intrinsic.f32_add(&left, &right, &ret, 1); + NativeIntrinsic.Intrinsic.f32_buffer_add(&left, &right, &ret, 1); return ret; } diff --git a/StgSharp.Common/Timing/StgSharpTime.cs b/StgSharp.Common/Timing/StgSharpTime.cs index f08f06fc..aa407735 100644 --- a/StgSharp.Common/Timing/StgSharpTime.cs +++ b/StgSharp.Common/Timing/StgSharpTime.cs @@ -119,6 +119,7 @@ namespace StgSharp { if (!_subscribers[i].OnSpanTick(elapsedTicks)) { + Console.WriteLine("removed"); _subscribers.RemoveAt(i); i--; // adjust index after removal } diff --git a/StgSharp.Common/Timing/TimeSequence.cs b/StgSharp.Common/Timing/TimeSequence.cs index fba82b03..9dc446be 100644 --- a/StgSharp.Common/Timing/TimeSequence.cs +++ b/StgSharp.Common/Timing/TimeSequence.cs @@ -46,8 +46,10 @@ namespace StgSharp.Common.Timing double initialSliceSeconds, double totalSeconds, double growthMultiplier, - double minSliceSeconds) => new LogTimeSequence(initialSliceSeconds, totalSeconds, - growthMultiplier, minSliceSeconds); + double minSliceSeconds) => new LogTimeSequence(initialSliceSeconds, + totalSeconds, + growthMultiplier, + minSliceSeconds); public abstract bool EndsAt(long currentTick); @@ -71,7 +73,6 @@ namespace StgSharp.Common.Timing if (frameSeconds > totalSeconds) { throw new ArgumentException("Frame length greater than total length."); } - _totalSeconds = totalSeconds; _frameSeconds = frameSeconds; } @@ -85,7 +86,7 @@ namespace StgSharp.Common.Timing long span = currentTick - PreviousFrameTick; if (span >= _frameLengthTicks && currentTick < EndingTick) { - PreviousFrameTick += _frameLengthTicks; // advance start of next frame + PreviousFrameTick += _frameLengthTicks; return true; } return false; @@ -105,25 +106,21 @@ namespace StgSharp.Common.Timing } /// - /// Logarithmic time sequence with growth factor. Boundaries (cumulative times since start) - /// follow initial * multiplier^k, but each slice duration (difference between adjusted - /// boundaries) is at least minSliceSeconds. First slice uses the exact initial length even if - /// below minSliceSeconds, subsequent slices enforce minimum. Example: initial=2, - /// multiplier=2, total>=8, min=3 => boundaries: 2,5,8 (durations:2,3,3). + /// Logarithmic time sequence with growth factor and minimum slice length enforcement. /// internal sealed class LogTimeSequence : TimeSequence { + private bool _finalEmitted; private readonly double _initialSeconds; - private double _lastBoundarySecondsAdjusted; // adjusted cumulative seconds of last emitted boundary (0 at start) + private double _lastBoundarySecondsAdjusted; private readonly double _minSliceSeconds; private readonly double _multiplier; - private double _nextBoundarySecondsAdjusted; // adjusted cumulative seconds for next boundary + private double _nextBoundarySecondsAdjusted; private readonly double _totalSeconds; - - private int _sliceIndex; // index of next boundary (0 => first boundary at initialSeconds) + private int _sliceIndex; private long _freq; - private long _nextBoundaryTick; // absolute tick for next boundary + private long _nextBoundaryTick; private long _totalTicks; public LogTimeSequence( @@ -139,11 +136,9 @@ namespace StgSharp.Common.Timing if (growthMultiplier < 1.0) { throw new ArgumentException("growthMultiplier must be >= 1"); } - if (initialSliceSeconds > totalSeconds) { throw new ArgumentException("Initial slice length greater than total length."); } - _initialSeconds = initialSliceSeconds; _totalSeconds = totalSeconds; _multiplier = growthMultiplier; @@ -151,49 +146,62 @@ namespace StgSharp.Common.Timing } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override bool EndsAt(long currentTick) => currentTick >= EndingTick || - _nextBoundarySecondsAdjusted >= _totalSeconds; + public override bool EndsAt(long currentTick) + { + if (currentTick >= EndingTick) + { + Console.WriteLine("Ended"); + return true; + } + return false; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public override bool IsNextFrameReady(long currentTick) { - if (currentTick < _nextBoundaryTick || currentTick >= EndingTick) { + // Emit final once when reaching or passing end. + if (currentTick >= EndingTick) + { + if (_finalEmitted) { + return false; + } + + PreviousFrameTick = EndingTick; + _finalEmitted = true; + return true; + } + + // Not reached end: only when we cross the next boundary tick do we emit. + if (currentTick < _nextBoundaryTick) + { return false; } - // Emit frame: update previous frame tick and prepare next boundary. - PreviousFrameTick = _nextBoundaryTick; // boundary just reached + // Advance to this boundary. + PreviousFrameTick = _nextBoundaryTick; _lastBoundarySecondsAdjusted = _nextBoundarySecondsAdjusted; _sliceIndex++; - // Compute original (unadjusted) next cumulative boundary in seconds. - double originalNext = _initialSeconds * Math.Pow(_multiplier, _sliceIndex); - - // Enforce total cap. - if (originalNext > _totalSeconds) - { - originalNext = _totalSeconds; + // Compute next cumulative boundary seconds with multiplier, then enforce min-slice and total cap. + double next = _initialSeconds * Math.Pow(_multiplier, _sliceIndex); + if (next > _totalSeconds) { + next = _totalSeconds; } - // Compute slice duration based on adjusted previous boundary. - double delta = originalNext - _lastBoundarySecondsAdjusted; - if (_sliceIndex > 0 && delta < _minSliceSeconds) + double delta = next - _lastBoundarySecondsAdjusted; + if (delta < _minSliceSeconds) { - // Enforce minimum (except for first slice which uses initial value) - originalNext = _lastBoundarySecondsAdjusted + _minSliceSeconds; - if (originalNext > _totalSeconds) { - originalNext = _totalSeconds; + next = _lastBoundarySecondsAdjusted + _minSliceSeconds; + if (next > _totalSeconds) { + next = _totalSeconds; } } - _nextBoundarySecondsAdjusted = originalNext; - if (_nextBoundarySecondsAdjusted >= _totalSeconds) - { - _nextBoundaryTick = EndingTick; // sequence will end after this boundary - } else - { - _nextBoundaryTick = BeginningTick + SecondsToTicks(_nextBoundarySecondsAdjusted); - } + _nextBoundarySecondsAdjusted = next; + _nextBoundaryTick = (_nextBoundarySecondsAdjusted >= _totalSeconds) ? + EndingTick : + BeginningTick + SecondsToTicks(_nextBoundarySecondsAdjusted); + return true; } @@ -205,9 +213,10 @@ namespace StgSharp.Common.Timing EndingTick = BeginningTick + _totalTicks; _sliceIndex = 0; _lastBoundarySecondsAdjusted = 0.0; - _nextBoundarySecondsAdjusted = _initialSeconds; // first boundary uses exact initial length + _nextBoundarySecondsAdjusted = _initialSeconds; _nextBoundaryTick = BeginningTick + SecondsToTicks(_nextBoundarySecondsAdjusted); - PreviousFrameTick = BeginningTick; // start point + PreviousFrameTick = BeginningTick; + _finalEmitted = false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/StgSharp.Common/Timing/TimeSpanProvider.Awaiting.cs b/StgSharp.Common/Timing/TimeSpanProvider.Awaiting.cs index 128c6ab1..398d500e 100644 --- a/StgSharp.Common/Timing/TimeSpanProvider.Awaiting.cs +++ b/StgSharp.Common/Timing/TimeSpanProvider.Awaiting.cs @@ -86,11 +86,7 @@ namespace StgSharp.Timing public void Dispose() { // mark provider as ended so external users can observe terminal state - try - { - Volatile.Write(ref _endedFlag, 1); - } - catch { } + Volatile.Write(ref _endedFlag, 1); s_unusedID.Push(TokenID); _event.Dispose(); GC.SuppressFinalize(this); @@ -211,6 +207,7 @@ namespace StgSharp.Timing { // mark ended due to sequence timeout, then dispose Volatile.Write(ref _endedFlag, 1); + Console.WriteLine("Time span ended."); Dispose(); return false; } @@ -238,9 +235,6 @@ namespace StgSharp.Timing return true; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void Refresh() => _refreshHandler?.Invoke(this, EventArgs.Empty); // Legacy compatibility. - ~TimeSpanProvider() => Dispose(); } diff --git a/StgSharp.Common/Timing/TimeSpanProvider.cs b/StgSharp.Common/Timing/TimeSpanProvider.cs index 67a1d741..f847b1f5 100644 --- a/StgSharp.Common/Timing/TimeSpanProvider.cs +++ b/StgSharp.Common/Timing/TimeSpanProvider.cs @@ -39,15 +39,18 @@ namespace StgSharp.Timing public partial class TimeSpanProvider { - private bool _subscribed; + // private bool _subscribed; private int _emittedSpanCount; // legacy counter // internal ended flag (0 = running, 1 = ended) - private int _endedFlag = 0; + private int _endedFlag; private readonly TimeSequence _sequence; private readonly TimeSourceProviderBase _timeSource; - public TimeSpanProvider(TimeSequence sequence, TimeSourceProviderBase provider, int maxWaitCount = 1) + public TimeSpanProvider( + TimeSequence sequence, + TimeSourceProviderBase provider, + int maxWaitCount = 1) { ArgumentNullException.ThrowIfNull(provider); ArgumentNullException.ThrowIfNull(sequence); @@ -55,8 +58,10 @@ namespace StgSharp.Timing _sequence = sequence; _sequence.StartFrom(provider); provider.AddSubscriber(this); - _subscribed = true; - if (!s_unusedID.TryPop(out int id)) { + + // _subscribed = true; + if (!s_unusedID.TryPop(out int id)) + { id = Interlocked.Increment(ref s_maxID); } TokenID = id; @@ -70,16 +75,20 @@ namespace StgSharp.Timing /// public bool IsEnded => Volatile.Read(ref _endedFlag) != 0; + /// + /// Current emitted time in seconds relative to the sequence beginning. + /// public double CurrentSecond { - get => (double)_sequence.PreviousFrameTick / _timeSource.Frequency; + get => (double)(_sequence.PreviousFrameTick - _sequence.BeginningTick) / _timeSource.Frequency; } public int CurrentSpan => _emittedSpanCount; public static TimeSourceProviderBase DefaultProvider => World.MainTimeProvider; - public static explicit operator int(TimeSpanProvider provider) => provider?._emittedSpanCount ?? 0; + public static explicit operator int(TimeSpanProvider provider) => provider?._emittedSpanCount ?? + 0; } } \ No newline at end of file diff --git a/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs b/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs index 7d76854d..52cec027 100644 --- a/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs +++ b/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs @@ -58,7 +58,7 @@ namespace StgSharp.Mathematics.Numeric MatrixKernel* leftPtr = left.Buffer; MatrixKernel* rightPtr = right.Buffer; MatrixKernel* ansPtr = ans.Buffer; - NativeIntrinsic.Intrinsic.f32_add(leftPtr, rightPtr, ansPtr, count); + NativeIntrinsic.Intrinsic.f32_buffer_add(leftPtr, rightPtr, ansPtr, count); return ans; } else if (count <= 1024) @@ -68,7 +68,7 @@ namespace StgSharp.Mathematics.Numeric MatrixKernel* leftPtr = left.Buffer; MatrixKernel* rightPtr = right.Buffer; MatrixKernel* ansPtr = ans.Buffer; - NativeIntrinsic.Intrinsic.f32_add(leftPtr, rightPtr, ansPtr, count); + NativeIntrinsic.Intrinsic.f32_buffer_add(leftPtr, rightPtr, ansPtr, count); MatrixParallel.ReturnParallelResources(ref pool); return ans; @@ -81,7 +81,7 @@ namespace StgSharp.Mathematics.Numeric package->PrimCount = left.KernelColumnLength; package->SecCount = left.KernelRowLength; package->ComputeMode = new MatrixOpMode(MatrixOperationStyle.BUFFER_OP, MatrixOperationParam.LEFT_RIGHT_ANS_PARAM); - package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_add; + package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_buffer_add; MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package); MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep); @@ -96,12 +96,12 @@ namespace StgSharp.Mathematics.Numeric scalar->Data(0) = value; if (count <= 256) { - NativeIntrinsic.Intrinsic.f32_fill(ans.Buffer, scalar, count); + NativeIntrinsic.Intrinsic.f32_buffer_fill(ans.Buffer, scalar, count); return; } else if (count <= 1024) { MatrixParallelThread[] pool = MatrixParallel.LeadParallel(1); - NativeIntrinsic.Intrinsic.f32_fill(ans.Buffer, scalar, count); + NativeIntrinsic.Intrinsic.f32_buffer_fill(ans.Buffer, scalar, count); MatrixParallel.ReturnParallelResources(ref pool); return; } @@ -111,7 +111,7 @@ namespace StgSharp.Mathematics.Numeric package->PrimCount = ans.KernelColumnLength; package->SecCount = ans.KernelRowLength; package->ComputeMode = new MatrixOpMode(MatrixOperationStyle.BUFFER_OP, MatrixOperationParam.ANS_SCALAR_PARAM); - package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_fill; + package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_buffer_fill; package->Scalar = scalar; MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package); MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep); @@ -144,7 +144,7 @@ namespace StgSharp.Mathematics.Numeric { MatrixKernel* leftPtr = left.Buffer; MatrixKernel* ansPtr = ans.Buffer; - NativeIntrinsic.Intrinsic.f32_scalar_mul(leftPtr, ansPtr, scalar, count); + NativeIntrinsic.Intrinsic.f32_buffer_scalar_mul(leftPtr, ansPtr, scalar, count); return ans; } else if (count <= 1024) @@ -153,7 +153,7 @@ namespace StgSharp.Mathematics.Numeric MatrixKernel* leftPtr = left.Buffer; MatrixKernel* ansPtr = ans.Buffer; - NativeIntrinsic.Intrinsic.f32_scalar_mul(leftPtr, ansPtr, scalar, count); + NativeIntrinsic.Intrinsic.f32_buffer_scalar_mul(leftPtr, ansPtr, scalar, count); MatrixParallel.ReturnParallelResources(ref pool); return ans; @@ -166,7 +166,7 @@ namespace StgSharp.Mathematics.Numeric package->SecCount = left.KernelRowLength; package->Scalar = scalar; package->ComputeMode = new MatrixOpMode(MatrixOperationStyle.BUFFER_OP, MatrixOperationParam.RIGHT_ANS_SCALAR_PARAM); - package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_scalar_mul; + package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_buffer_scalar_mul; MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package); MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep); @@ -192,7 +192,7 @@ namespace StgSharp.Mathematics.Numeric MatrixKernel* leftPtr = left.Buffer; MatrixKernel* rightPtr = right.Buffer; MatrixKernel* ansPtr = ans.Buffer; - NativeIntrinsic.Intrinsic.f32_sub(leftPtr, rightPtr, ansPtr, count); + NativeIntrinsic.Intrinsic.f32_buffer_sub(leftPtr, rightPtr, ansPtr, count); return ans; } else if (count <= 1024) @@ -202,7 +202,7 @@ namespace StgSharp.Mathematics.Numeric MatrixKernel* leftPtr = left.Buffer; MatrixKernel* rightPtr = right.Buffer; MatrixKernel* ansPtr = ans.Buffer; - NativeIntrinsic.Intrinsic.f32_sub(leftPtr, rightPtr, ansPtr, count); + NativeIntrinsic.Intrinsic.f32_buffer_sub(leftPtr, rightPtr, ansPtr, count); MatrixParallel.ReturnParallelResources(ref pool); return ans; @@ -215,7 +215,7 @@ namespace StgSharp.Mathematics.Numeric package->PrimCount = left.KernelColumnLength; package->SecCount = left.KernelRowLength; package->ComputeMode = new MatrixOpMode(MatrixOperationStyle.BUFFER_OP, MatrixOperationParam.LEFT_RIGHT_ANS_PARAM); - package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_sub; + package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_buffer_sub; MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package); MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep); diff --git a/StgSharp.Native/StgSharp.Native.vcxproj b/StgSharp.Native/StgSharp.Native.vcxproj index 47d66f39..81129ad1 100644 --- a/StgSharp.Native/StgSharp.Native.vcxproj +++ b/StgSharp.Native/StgSharp.Native.vcxproj @@ -148,7 +148,7 @@ - + @@ -156,7 +156,7 @@ - CppCode + CCode diff --git a/StgSharp.Native/StgSharp.Native.vcxproj.filters b/StgSharp.Native/StgSharp.Native.vcxproj.filters index 3abc766e..92bd11f3 100644 --- a/StgSharp.Native/StgSharp.Native.vcxproj.filters +++ b/StgSharp.Native/StgSharp.Native.vcxproj.filters @@ -51,7 +51,7 @@ 源文件 - + 源文件 diff --git a/StgSharp.Native/sn-head/sn_intrinsic.h b/StgSharp.Native/sn-head/sn_intrinsic.h index 0ccff731..e16df462 100644 --- a/StgSharp.Native/sn-head/sn_intrinsic.h +++ b/StgSharp.Native/sn-head/sn_intrinsic.h @@ -131,6 +131,8 @@ typedef void(SN_DECL *BUF_PROC_LRA)(mat_kernel *left, mat_kernel *right, mat_ker #pragma region matrix panel function type +typedef void(SN_DECL *PANEL_PROC)(mat_panel *panel, mat_kernel *kernel, int col_length, + int row_length, int col_index, int row_index); typedef void(SN_DECL *PNL_PROC_LRA)(mat_panel *left, mat_panel *right, mat_panel *ans); typedef void(SN_DECL *PNL_PROC_RA)(mat_panel *right, mat_panel *ans); typedef void(SN_DECL *PNL_PROC_LRAS)(mat_panel *left, mat_panel *right, mat_panel *ans, @@ -250,22 +252,21 @@ INTERNAL int SN_DECL index_pair_sse(short const *str, uint32_t target, int lengt #pragma endregion -typedef void(SN_DECL *BUILD_PANEL_PROC)(mat_panel *panel, mat_kernel *kernel, int col_length, - int row_length, int col_index, int row_index); - -// Reordered to match C# IntrinsicContext field order -// C# order: city_hash_simplify, f32_add, f32_fill, f32_fma, f32_scalar_mul, f32_sub, f32_transpose, factorial_simd, index_pair, normalize_3 +// Mirrors C# IntrinsicContext field order so managed/unmanaged layouts stay in sync. typedef struct sn_intrinsic { - HASH city_hash_simplify; // city_hash_simplify - BUF_PROC_LRA f32_buffer_add; // f32_add - BUF_PROC_AS f32_buffer_fill; // f32_fill - PNL_PROC_LRA f32_panel_fma; // f32_fma (panel variant) - BUF_PROC_LRA f32_kernel_scalar_mul; // f32_scalar_mul (right+ans+scalar variant mapped here) - BUF_PROC_LRA f32_kernel_sub; // f32_sub - KER_PROC_RA f32_kernel_transpose; // f32_transpose - FACTORIALROC factorial_simd; // factorial_simd - INDEX_PAIR index_pair; // index_pair - VECTORNORMALIZEPROC f32_normalize_3; // normalize_3 + HASH city_hash_simplify; + BUF_PROC_LRA f32_buffer_add; + BUF_PROC_AS f32_buffer_fill; + BUF_PROC_RAS f32_buffer_scalar_mul; + BUF_PROC_LRA f32_buffer_sub; + KER_PROC_RA f32_buffer_transpose; + PANEL_PROC f32_build_panel; + VECTORNORMALIZEPROC f32_normalize_3; + PNL_PROC_LRA f32_panel_fma; + PANEL_PROC f32_store_panel; + FACTORIALROC factorial_simd; + INDEX_PAIR index_pair; + BUF_PROC_RAS variant; } sn_intrinsic; typedef enum most_advanced_instruction { diff --git a/StgSharp.Native/sn-head/sn_matkernel.h b/StgSharp.Native/sn-head/sn_matkernel.h index 42803f48..857b7af7 100644 --- a/StgSharp.Native/sn-head/sn_matkernel.h +++ b/StgSharp.Native/sn-head/sn_matkernel.h @@ -1,14 +1,17 @@ #ifndef SN_MATKERNEL #define SN_MATKERNEL -#define ELEMENTSIZE(T) sizeof(T) -#define XMMCOUNT(T) sizeof(T) -#define YMMCOUNT(T) sizeof(T) / 2 -#define ZMMCOUNT(T) sizeof(T) / 4 - #include #include +#include "sn_internal.h" + +/* Kernel storage unions for a fixed 4x4 block. */ +#define ELEMENTSIZE(T) sizeof(T) +#define XMMCOUNT(T) (sizeof(T)) +#define YMMCOUNT(T) (sizeof(T) / 2) +#define ZMMCOUNT(T) (sizeof(T) / 4) + #define MAT_KERNEL(T) \ union { \ __m128 xmm[XMMCOUNT(T) / 4]; \ @@ -25,7 +28,8 @@ T v[4]; \ } -#endif +/* Provide a named alias for the zero kernel type to ensure consistent linkage in C++. */ +typedef MAT_KERNEL(uint64_t) sn_zero_kernel_u64; /* Helpers (all compile-time): */ #define SN_LANES(T_VEC, T) (sizeof(T_VEC) / sizeof(T)) @@ -48,8 +52,8 @@ - SIMD view remains integer-typed; cast inside micro-kernels to the appropriate floating-point/integer vector type on demand. */ -#define MAT_PANEL_SQ_MIN(T, T_VEC, MINQ) \ - SN_ALIGNAS(sizeof(T_VEC)) union { \ +#define MAT_PANEL_SQ_MIN_NOALIGN(T, T_VEC, MINQ) \ + union { \ T_VEC vec[PANEL_Q(T, T_VEC, MINQ)][PANEL_CHUNKS(T, T_VEC, MINQ)]; \ T flat[PANEL_Q(T, T_VEC, MINQ) * PANEL_Q(T, T_VEC, MINQ)]; \ } @@ -63,44 +67,53 @@ /* SSE panel layout: column-major buffer holding 4 logical columns with MINQ=4. Columns: each column packs up to four scalars so ALIGN equals sizeof(__m128). Alignment: every column boundary lands on a 16-byte multiple for XMM loads. */ -#define MAT_PANEL_SSE(T) MAT_PANEL_SQ_MIN(T, __m128, 4) +#define MAT_PANEL_SSE(T) SN_ALIGNAS(16) MAT_PANEL_SQ_MIN_NOALIGN(T, __m128, 4) /* AVX2 panel layout: column-major buffer holding 8 logical columns with MINQ=8. Columns: each column stores eight elements via two 256-bit chunks when T is 32-bit. Alignment: column starts are 32-byte aligned so AVX2 loads/stores remain contiguous. */ -#define MAT_PANEL_AVX(T) MAT_PANEL_SQ_MIN(T, __m256, 8) +#define MAT_PANEL_AVX(T) SN_ALIGNAS(32) MAT_PANEL_SQ_MIN_NOALIGN(T, __m256, 8) /* AVX-512 panel layout: column-major buffer holding 8 or more columns depending on T. Columns: each column expands to ceil(Q/lanes) ZMM chunks; default MINQ=8 keeps double-wide tiles. Alignment: column starts sit on 64-byte boundaries to match AVX-512 streaming access. */ -#define MAT_PANEL_512(T) MAT_PANEL_SQ_MIN(T, __m512, 8) +#define MAT_PANEL_512(T) SN_ALIGNAS(64) MAT_PANEL_SQ_MIN_NOALIGN(T, __m512, 8) + +/* Global zero kernel declaration (defined in dllmain.c), aligned to 64 bytes */ +#ifdef __cplusplus +extern "C" { +#endif +extern __declspec(align(64)) sn_zero_kernel_u64 SN_ZERO_KERNEL; +#ifdef __cplusplus +} +#endif /* Access helpers (all compile-time friendly): Given Q = PANEL_Q(...), CH = PANEL_CHUNKS(...), R = lanes per vector: - Column c occupies vec[c][0..CH-1]. - Row r inside column c is located at vec[c][r / R] with lane (r % R). */ - -/* Global zero kernel declaration (defined in dllmain.c), aligned to 64 bytes */ -#ifdef __cplusplus -extern "C" { -#endif -__declspec(align(64)) extern MAT_KERNEL(uint64_t) SN_ZERO_KERNEL; -#ifdef __cplusplus -} -#endif - #define PANEL_COL_VEC(panel_obj, c, chunk) ((panel_obj).vec[(int)(c)][(int)(chunk)]) /* Scalar flat index helper for column-major addressing */ #define PANEL_ELEM(panel_obj, T, T_VEC, MINQ, r, c) \ ((panel_obj).flat[(int)(c) * PANEL_Q(T, T_VEC, MINQ) + (int)(r)]) +/* API macros */ #define BUILD_PANEL(arch, element) build_panel_##arch##_##element - -#include "sn_internal.h" +#define STORE_PANEL(arch, element) store_panel_##arch##_##element #define DECLARE_BUILD_PANEL(arch, element) \ INTERNAL void SN_DECL BUILD_PANEL(arch, element)( \ MAT_PANEL_##arch(element) *restrict panel, \ MAT_KERNEL(element) const *const matrix, int col_length, int row_length, \ int col_index, int row_index) +#define DECLARE_STORE_PANEL(arch, element) \ + INTERNAL void SN_DECL STORE_PANEL(arch, element)(MAT_KERNEL(element) *restrict matrix, \ + MAT_PANEL_##arch(element) \ + const *const panel, \ + int col_length, int row_length, \ + int col_index, int row_index) +/* Declarations for AVX float variant */ DECLARE_BUILD_PANEL(AVX, float); +DECLARE_STORE_PANEL(AVX, float); + +#endif /* SN_MATKERNEL */ diff --git a/StgSharp.Native/sn-src/dllmain.c b/StgSharp.Native/sn-src/dllmain.c index c4af815c..677a0b71 100644 --- a/StgSharp.Native/sn-src/dllmain.c +++ b/StgSharp.Native/sn-src/dllmain.c @@ -1,16 +1,23 @@ #include "StgSharpNative.h" #include "sn_matkernel.h" +#include #ifdef _WIN32 /* Define and initialize a global zero kernel aligned to 64 bytes for universal ISA usage */ -__declspec(align(64)) MAT_KERNEL(uint64_t) SN_ZERO_KERNEL; +#ifdef __cplusplus +extern "C" { +#endif +__declspec(align(64)) sn_zero_kernel_u64 SN_ZERO_KERNEL; +#ifdef __cplusplus +} +#endif static void init_zero_kernel(void) { for (int c = 0; c < 4; ++c) { for (int r = 0; r < 4; ++r) { - SN_ZERO_KERNEL.m[r][c] = 0.0; + SN_ZERO_KERNEL.m[r][c] = 0; } } } diff --git a/StgSharp.Native/sn-src/k_build_panel.c b/StgSharp.Native/sn-src/k_build_panel.c deleted file mode 100644 index 7802efa4..00000000 --- a/StgSharp.Native/sn-src/k_build_panel.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "sn_matkernel.h" - -DECLARE_BUILD_PANEL(AVX, float) -{ - const int Q = 8; /* fixed for AVX float panel */ - - /* Neighbor kernels; substitute global zero kernel where out-of-bounds */ - const int has_right = (col_index + 1) < col_length; - const int has_bottom = (row_index + 1) < row_length; - - const MAT_KERNEL(float) *const k_lt = matrix + (col_index * row_length + row_index); - const MAT_KERNEL(float) *const k_rt = - has_right ? (matrix + ((col_index + 1) * row_length + row_index)) : - (const MAT_KERNEL(float) *)&SN_ZERO_KERNEL; - const MAT_KERNEL(float) *const k_lb = - has_bottom ? (matrix + (col_index * row_length + (row_index + 1))) : - (const MAT_KERNEL(float) *)&SN_ZERO_KERNEL; - const MAT_KERNEL(float) *const k_rb = - (has_right && has_bottom) ? - (matrix + ((col_index + 1) * row_length + (row_index + 1))) : - (const MAT_KERNEL(float) *)&SN_ZERO_KERNEL; - - register __m128 top128, bot128; - register __m256 col256; - - for (int pc = 0; pc < Q; ++pc) { - const int is_right_half = (pc >= 4); - const int kc_col = pc & 3; /* column index inside 4x4 kernel */ - - const MAT_KERNEL(float) *src_top = is_right_half ? k_rt : k_lt; - const MAT_KERNEL(float) *src_bot = is_right_half ? k_rb : k_lb; - - /* Vector loads: each kernel column is a compact __m128 */ - top128 = src_top->xmm[kc_col]; - bot128 = src_bot->xmm[kc_col]; - - /* Combine into an AVX column: low 128 = top, high 128 = bottom */ - col256 = _mm256_set_m128(bot128, top128); - - PANEL_COL_VEC((*panel), pc, 0) = col256; - } -} diff --git a/StgSharp.Native/sn-src/k_panel.c b/StgSharp.Native/sn-src/k_panel.c new file mode 100644 index 00000000..ae59bea7 --- /dev/null +++ b/StgSharp.Native/sn-src/k_panel.c @@ -0,0 +1,98 @@ +#include "sn_matkernel.h" + +DECLARE_BUILD_PANEL(AVX, float) +{ + const int Q = 8; /* fixed for AVX float panel */ + + /* Neighbor kernels; substitute global zero kernel where out-of-bounds */ + const int has_right = (col_index + 1) < col_length; + const int has_bottom = (row_index + 1) < row_length; + + const MAT_KERNEL(float) *const k_lt = matrix + (col_index * row_length + row_index); + const MAT_KERNEL(float) *const k_rt = + has_right ? (matrix + ((col_index + 1) * row_length + row_index)) : + (const MAT_KERNEL(float) *)&SN_ZERO_KERNEL; + const MAT_KERNEL(float) *const k_lb = + has_bottom ? (matrix + (col_index * row_length + (row_index + 1))) : + (const MAT_KERNEL(float) *)&SN_ZERO_KERNEL; + const MAT_KERNEL(float) *const k_rb = + (has_right && has_bottom) ? + (matrix + ((col_index + 1) * row_length + (row_index + 1))) : + (const MAT_KERNEL(float) *)&SN_ZERO_KERNEL; + + register __m128 top128, bot128; + register __m256 col256; + + for (int pc = 0; pc < Q; ++pc) { + const int is_right_half = (pc >= 4); + const int kc_col = pc & 3; /* column index inside 4x4 kernel */ + + const MAT_KERNEL(float) *src_top = is_right_half ? k_rt : k_lt; + const MAT_KERNEL(float) *src_bot = is_right_half ? k_rb : k_lb; + + /* Vector loads: each kernel column is a compact __m128 */ + top128 = src_top->xmm[kc_col]; + bot128 = src_bot->xmm[kc_col]; + + /* Combine into an AVX column: low 128 = top, high 128 = bottom */ + col256 = _mm256_set_m128(bot128, top128); + + PANEL_COL_VEC((*panel), pc, 0) = col256; + } +} + +DECLARE_STORE_PANEL(AVX, float) +{ + const int Q = 8; /* fixed for AVX float panel */ + + /* Local dummy kernel to swallow out-of-bounds writes; no init needed */ + MAT_KERNEL(float) zero; + + const int has_right = (col_index + 1) < col_length; + const int has_bottom = (row_index + 1) < row_length; + + MAT_KERNEL(float) *const k_lt = (col_index < col_length && row_index < row_length) ? + (matrix + (col_index * row_length + row_index)) : + &zero; + MAT_KERNEL(float) *const k_rt = + has_right && (row_index < row_length) ? + (matrix + ((col_index + 1) * row_length + row_index)) : + &zero; + MAT_KERNEL(float) *const k_lb = + has_bottom && (col_index < col_length) ? + (matrix + (col_index * row_length + (row_index + 1))) : + &zero; + MAT_KERNEL(float) *const k_rb = + (has_right && has_bottom) ? + (matrix + ((col_index + 1) * row_length + (row_index + 1))) : + &zero; + + register __m128 top128, bot128; + int i = 0; + for (; i < Q / 2; i++) { + const int kc_col = i; /* column index inside 4x4 kernel */ + + /* Load the panel column vector */ + const __m256 col256 = PANEL_COL_VEC((*panel), i, 0); + /* Split into top/bottom halves */ + top128 = _mm256_castps256_ps128(col256); /* low 128 */ + bot128 = _mm256_extractf128_ps(col256, 1); /* high 128 */ + + /* Store back into kernels directly (out-of-bounds writes go to dummy) */ + k_rt->xmm[kc_col] = top128; + k_rb->xmm[kc_col] = bot128; + } + for (; i < Q; i++) { + const int kc_col = i - 4; /* column index inside 4x4 kernel */ + + /* Load the panel column vector */ + const __m256 col256 = PANEL_COL_VEC((*panel), i, 0); + /* Split into top/bottom halves */ + top128 = _mm256_castps256_ps128(col256); /* low 128 */ + bot128 = _mm256_extractf128_ps(col256, 1); /* high 128 */ + + /* Store back into kernels directly (out-of-bounds writes go to dummy) */ + k_lt->xmm[kc_col] = top128; + k_lb->xmm[kc_col] = bot128; + } +} diff --git a/StgSharp.Native/sn-src/load_intrinsic.c b/StgSharp.Native/sn-src/load_intrinsic.c index 0e2b17d4..a13c8383 100644 --- a/StgSharp.Native/sn-src/load_intrinsic.c +++ b/StgSharp.Native/sn-src/load_intrinsic.c @@ -68,9 +68,10 @@ void load_intrinsic_sse(sn_intrinsic *context) context->f32_buffer_add = BUF_PROC(float, sse, add); context->f32_panel_fma = KER_PROC(float, sse, fma); context->f32_buffer_fill = BUF_PROC(float, sse, fill); - context->f32_kernel_scalar_mul = BUF_PROC(float, sse, scalar_mul); - context->f32_kernel_sub = BUF_PROC(float, sse, sub); - context->f32_kernel_transpose = KER_PROC(float, sse, transpose); + context->variant = BUF_PROC(float, sse, scalar_mul); + context->f32_buffer_sub = BUF_PROC(float, sse, sub); + context->f32_buffer_transpose = KER_PROC(float, sse, transpose); + context->f32_buffer_scalar_mul = BUF_PROC(float, sse, scalar_mul); context->f32_normalize_3 = f32_normalize; } @@ -82,9 +83,10 @@ void load_intrinsic_avx(sn_intrinsic *context) context->f32_buffer_add = BUF_PROC(float, avx, add); context->f32_panel_fma = KER_PROC(float, sse, fma); context->f32_buffer_fill = BUF_PROC(float, avx, fill); - context->f32_kernel_scalar_mul = BUF_PROC(float, avx, scalar_mul); - context->f32_kernel_sub = BUF_PROC(float, avx, sub); - context->f32_kernel_transpose = KER_PROC(float, avx, transpose); + context->variant = BUF_PROC(float, avx, scalar_mul); + context->f32_buffer_sub = BUF_PROC(float, avx, sub); + context->f32_buffer_transpose = KER_PROC(float, avx, transpose); + context->f32_buffer_scalar_mul = BUF_PROC(float, avx, scalar_mul); context->f32_normalize_3 = f32_normalize; } @@ -96,8 +98,9 @@ void load_intrinsic_512(sn_intrinsic *context) context->f32_buffer_add = BUF_PROC(float, 512, add); context->f32_panel_fma = KER_PROC(float, sse, fma); context->f32_buffer_fill = BUF_PROC(float, 512, fill); - context->f32_kernel_scalar_mul = BUF_PROC(float, 512, scalar_mul); - context->f32_kernel_sub = BUF_PROC(float, 512, sub); - context->f32_kernel_transpose = KER_PROC(float, 512, transpose); + context->variant = BUF_PROC(float, 512, scalar_mul); + context->f32_buffer_sub = BUF_PROC(float, 512, sub); + context->f32_buffer_transpose = KER_PROC(float, 512, transpose); + context->f32_buffer_scalar_mul = BUF_PROC(float, 512, scalar_mul); context->f32_normalize_3 = f32_normalize; } diff --git a/StgSharpDebug/Program.cs b/StgSharpDebug/Program.cs index d3b1c84a..85612843 100644 --- a/StgSharpDebug/Program.cs +++ b/StgSharpDebug/Program.cs @@ -25,10 +25,12 @@ // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- +using StgSharp.Common.Timing; using StgSharp.HighPerformance; using StgSharp.HighPerformance.Memory; using StgSharp.Internal; using StgSharp.Mathematics.Numeric; +using StgSharp.Timing; namespace StgSharp { @@ -49,9 +51,9 @@ namespace StgSharp // TestRender(); // TestHlsf(); + // HlsfStressTest.Run(); - M128 v = new M128(); - /**/ + /* HybridLayerSegregatedFitAllocator hlsf; unchecked { hlsf = new((nuint)(64 * (ulong)10000 * 10000)); @@ -84,7 +86,40 @@ namespace StgSharp Console.WriteLine(); } /**/ + + // --- Logarithmic time sequence test: print seconds at each emitted span --- + + // Configure a simple sequence: + // initial slice = 0.5s, total = 5s, growth multiplier = 2, min slice = 0.75s + TimeSequence seq = /* + TimeSequence.CreateLogarithmic(initialSliceSeconds:0.5, + totalSeconds:5.0, + growthMultiplier:2.0, + minSliceSeconds:0.75); + /**/ + TimeSequence.CreateLinear(5, 1); + /**/ + + // Bind to default time source provider. + TimeSpanProvider provider = new TimeSpanProvider(seq, TimeSpanProvider.DefaultProvider); + + // Print the second mark when a span is emitted. + provider.TimeSpanRefreshed += (s, e) => { + // CurrentSecond is PreviousFrameTick / Frequency + Console.WriteLine($"span @ {provider.CurrentSecond:0.000}s"); + }; + + // Start the time source and wait until sequence ends. + TimeSpanProvider.DefaultProvider.StartProvidingTime(); + + while (!provider.IsEnded) { + provider.WaitNextSpan(); + } + + TimeSpanProvider.DefaultProvider.StopProvidingTime(); + + // end of log-time sequence test } catch (Exception ex) {