time service contains bug, it cannot stop after edge

This commit is contained in:
Youmu Liu
2025-12-08 18:02:09 +08:00
parent 588fa867af
commit f960982bd3
17 changed files with 313 additions and 188 deletions
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Root Type="DevExpress.CodeRush.VisualizePlugins.StructuralHighlighting.Options.StructuralHighlightingOptions">
<Options Language="Neutral">
<Enabled>False</Enabled>
</Options>
</Root>
@@ -38,16 +38,19 @@ namespace StgSharp.Internal.Intrinsic
internal unsafe struct IntrinsicContext internal unsafe struct IntrinsicContext
{ {
public delegate* unmanaged[Cdecl]<char*, int, int> city_hash_simplify; public delegate* unmanaged[Cdecl]<char*, int, int> city_hash_simplify; //city_hash_simplify
public delegate* unmanaged[Cdecl]<void*, void*, void*, long, void> f32_add; public delegate* unmanaged[Cdecl]<void*, void*, void*, long, void> f32_buffer_add; //f32_buffer_add
public delegate* unmanaged[Cdecl]<void*, ScalarPacket*,long, void> f32_fill; public delegate* unmanaged[Cdecl]<void*, ScalarPacket*,long, void> f32_buffer_fill; //f32_buffer_fill
public delegate* unmanaged[Cdecl]<void*, void*, void*, void> f32_fma; public delegate* unmanaged[Cdecl]<void*, void*, ScalarPacket*, long, void> f32_buffer_scalar_mul; //f32_buffer_s_m
public delegate* unmanaged[Cdecl]<void*, void*, ScalarPacket*, long, void> f32_scalar_mul; public delegate* unmanaged[Cdecl]<void*, void*, void*, long, void> f32_buffer_sub; //f32_kernel_sub
public delegate* unmanaged[Cdecl]<void*, void*, void*, long, void> f32_sub; public delegate* unmanaged[Cdecl]<void*, void*, void> f32_buffer_transpose; //f32_kernel_transpose
public delegate* unmanaged[Cdecl]<void*, void*, void> f32_transpose; public delegate* unmanaged[Cdecl]<void*, void*, int, int, int, int, void> f32_build_panel; //f32_build_panel
public delegate* unmanaged[Cdecl]<int, ulong> factorial_simd; public delegate* unmanaged[Cdecl]<Vector4*, Vector4*, void> f32_normalize_3; //f32_normalize_3
public delegate* unmanaged[Cdecl]<char*, int, int, int> index_pair; public delegate* unmanaged[Cdecl]<void*, void*, void*, void> f32_panel_fma; //f32_panel_fma
public delegate* unmanaged[Cdecl]<Vector4*, Vector4*, void> normalize_3; public delegate* unmanaged[Cdecl]<void*, void*, int, int, int, int, void> f32_store_panel; //f32_store_panel
public delegate* unmanaged[Cdecl]<int, ulong> factorial_simd; //factorial_simd
public delegate* unmanaged[Cdecl]<char*, int, int, int> index_pair; //index_pair
public delegate* unmanaged[Cdecl]<void*, void*, ScalarPacket*, long, void> variant ; //variant
public IntrinsicContext() public IntrinsicContext()
{ {
@@ -185,7 +185,7 @@ namespace StgSharp.Mathematics.Graphic
mat.transpose.colum2 = rowSpan[2].vec; mat.transpose.colum2 = rowSpan[2].vec;
mat.transpose.colum3 = rowSpan[3].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; mat.isTransposed = false;
return mat; return mat;
} }
@@ -208,7 +208,7 @@ namespace StgSharp.Mathematics.Graphic
if (!isTransposed) if (!isTransposed)
{ {
fixed (ColumnSet4* source = &mat, target = &transpose) { fixed (ColumnSet4* source = &mat, target = &transpose) {
NativeIntrinsic.Intrinsic.f32_transpose(source, target); NativeIntrinsic.Intrinsic.f32_buffer_transpose(source, target);
} }
isTransposed = true; isTransposed = true;
} }
@@ -218,7 +218,7 @@ namespace StgSharp.Mathematics.Graphic
public static unsafe Matrix44 operator -(Matrix44 left, Matrix44 right) public static unsafe Matrix44 operator -(Matrix44 left, Matrix44 right)
{ {
Matrix44 ret = new(); Matrix44 ret = new();
NativeIntrinsic.Intrinsic.f32_sub(&left, &right, &ret, 1); NativeIntrinsic.Intrinsic.f32_buffer_sub(&left, &right, &ret, 1);
return ret; return ret;
} }
@@ -260,7 +260,7 @@ namespace StgSharp.Mathematics.Graphic
public static unsafe Matrix44 operator +(Matrix44 left, Matrix44 right) public static unsafe Matrix44 operator +(Matrix44 left, Matrix44 right)
{ {
Matrix44 ret = new(); Matrix44 ret = new();
NativeIntrinsic.Intrinsic.f32_add(&left, &right, &ret, 1); NativeIntrinsic.Intrinsic.f32_buffer_add(&left, &right, &ret, 1);
return ret; return ret;
} }
+1
View File
@@ -119,6 +119,7 @@ namespace StgSharp
{ {
if (!_subscribers[i].OnSpanTick(elapsedTicks)) if (!_subscribers[i].OnSpanTick(elapsedTicks))
{ {
Console.WriteLine("removed");
_subscribers.RemoveAt(i); _subscribers.RemoveAt(i);
i--; // adjust index after removal i--; // adjust index after removal
} }
+54 -45
View File
@@ -46,8 +46,10 @@ namespace StgSharp.Common.Timing
double initialSliceSeconds, double initialSliceSeconds,
double totalSeconds, double totalSeconds,
double growthMultiplier, double growthMultiplier,
double minSliceSeconds) => new LogTimeSequence(initialSliceSeconds, totalSeconds, double minSliceSeconds) => new LogTimeSequence(initialSliceSeconds,
growthMultiplier, minSliceSeconds); totalSeconds,
growthMultiplier,
minSliceSeconds);
public abstract bool EndsAt(long currentTick); public abstract bool EndsAt(long currentTick);
@@ -71,7 +73,6 @@ namespace StgSharp.Common.Timing
if (frameSeconds > totalSeconds) { if (frameSeconds > totalSeconds) {
throw new ArgumentException("Frame length greater than total length."); throw new ArgumentException("Frame length greater than total length.");
} }
_totalSeconds = totalSeconds; _totalSeconds = totalSeconds;
_frameSeconds = frameSeconds; _frameSeconds = frameSeconds;
} }
@@ -85,7 +86,7 @@ namespace StgSharp.Common.Timing
long span = currentTick - PreviousFrameTick; long span = currentTick - PreviousFrameTick;
if (span >= _frameLengthTicks && currentTick < EndingTick) if (span >= _frameLengthTicks && currentTick < EndingTick)
{ {
PreviousFrameTick += _frameLengthTicks; // advance start of next frame PreviousFrameTick += _frameLengthTicks;
return true; return true;
} }
return false; return false;
@@ -105,25 +106,21 @@ namespace StgSharp.Common.Timing
} }
/// <summary> /// <summary>
/// Logarithmic time sequence with growth factor. Boundaries (cumulative times since start) /// Logarithmic time sequence with growth factor and minimum slice length enforcement.
/// 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).
/// </summary> /// </summary>
internal sealed class LogTimeSequence : TimeSequence internal sealed class LogTimeSequence : TimeSequence
{ {
private bool _finalEmitted;
private readonly double _initialSeconds; 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 _minSliceSeconds;
private readonly double _multiplier; private readonly double _multiplier;
private double _nextBoundarySecondsAdjusted; // adjusted cumulative seconds for next boundary private double _nextBoundarySecondsAdjusted;
private readonly double _totalSeconds; private readonly double _totalSeconds;
private int _sliceIndex;
private int _sliceIndex; // index of next boundary (0 => first boundary at initialSeconds)
private long _freq; private long _freq;
private long _nextBoundaryTick; // absolute tick for next boundary private long _nextBoundaryTick;
private long _totalTicks; private long _totalTicks;
public LogTimeSequence( public LogTimeSequence(
@@ -139,11 +136,9 @@ namespace StgSharp.Common.Timing
if (growthMultiplier < 1.0) { if (growthMultiplier < 1.0) {
throw new ArgumentException("growthMultiplier must be >= 1"); throw new ArgumentException("growthMultiplier must be >= 1");
} }
if (initialSliceSeconds > totalSeconds) { if (initialSliceSeconds > totalSeconds) {
throw new ArgumentException("Initial slice length greater than total length."); throw new ArgumentException("Initial slice length greater than total length.");
} }
_initialSeconds = initialSliceSeconds; _initialSeconds = initialSliceSeconds;
_totalSeconds = totalSeconds; _totalSeconds = totalSeconds;
_multiplier = growthMultiplier; _multiplier = growthMultiplier;
@@ -151,49 +146,62 @@ namespace StgSharp.Common.Timing
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool EndsAt(long currentTick) => currentTick >= EndingTick || public override bool EndsAt(long currentTick)
_nextBoundarySecondsAdjusted >= _totalSeconds; {
if (currentTick >= EndingTick)
{
Console.WriteLine("Ended");
return true;
}
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool IsNextFrameReady(long currentTick) 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; return false;
} }
// Emit frame: update previous frame tick and prepare next boundary. PreviousFrameTick = EndingTick;
PreviousFrameTick = _nextBoundaryTick; // boundary just reached _finalEmitted = true;
return true;
}
// Not reached end: only when we cross the next boundary tick do we emit.
if (currentTick < _nextBoundaryTick)
{
return false;
}
// Advance to this boundary.
PreviousFrameTick = _nextBoundaryTick;
_lastBoundarySecondsAdjusted = _nextBoundarySecondsAdjusted; _lastBoundarySecondsAdjusted = _nextBoundarySecondsAdjusted;
_sliceIndex++; _sliceIndex++;
// Compute original (unadjusted) next cumulative boundary in seconds. // Compute next cumulative boundary seconds with multiplier, then enforce min-slice and total cap.
double originalNext = _initialSeconds * Math.Pow(_multiplier, _sliceIndex); double next = _initialSeconds * Math.Pow(_multiplier, _sliceIndex);
if (next > _totalSeconds) {
// Enforce total cap. next = _totalSeconds;
if (originalNext > _totalSeconds)
{
originalNext = _totalSeconds;
} }
// Compute slice duration based on adjusted previous boundary. double delta = next - _lastBoundarySecondsAdjusted;
double delta = originalNext - _lastBoundarySecondsAdjusted; if (delta < _minSliceSeconds)
if (_sliceIndex > 0 && delta < _minSliceSeconds)
{ {
// Enforce minimum (except for first slice which uses initial value) next = _lastBoundarySecondsAdjusted + _minSliceSeconds;
originalNext = _lastBoundarySecondsAdjusted + _minSliceSeconds; if (next > _totalSeconds) {
if (originalNext > _totalSeconds) { next = _totalSeconds;
originalNext = _totalSeconds;
} }
} }
_nextBoundarySecondsAdjusted = originalNext;
if (_nextBoundarySecondsAdjusted >= _totalSeconds) _nextBoundarySecondsAdjusted = next;
{ _nextBoundaryTick = (_nextBoundarySecondsAdjusted >= _totalSeconds) ?
_nextBoundaryTick = EndingTick; // sequence will end after this boundary EndingTick :
} else BeginningTick + SecondsToTicks(_nextBoundarySecondsAdjusted);
{
_nextBoundaryTick = BeginningTick + SecondsToTicks(_nextBoundarySecondsAdjusted);
}
return true; return true;
} }
@@ -205,9 +213,10 @@ namespace StgSharp.Common.Timing
EndingTick = BeginningTick + _totalTicks; EndingTick = BeginningTick + _totalTicks;
_sliceIndex = 0; _sliceIndex = 0;
_lastBoundarySecondsAdjusted = 0.0; _lastBoundarySecondsAdjusted = 0.0;
_nextBoundarySecondsAdjusted = _initialSeconds; // first boundary uses exact initial length _nextBoundarySecondsAdjusted = _initialSeconds;
_nextBoundaryTick = BeginningTick + SecondsToTicks(_nextBoundarySecondsAdjusted); _nextBoundaryTick = BeginningTick + SecondsToTicks(_nextBoundarySecondsAdjusted);
PreviousFrameTick = BeginningTick; // start point PreviousFrameTick = BeginningTick;
_finalEmitted = false;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -86,11 +86,7 @@ namespace StgSharp.Timing
public void Dispose() public void Dispose()
{ {
// mark provider as ended so external users can observe terminal state // mark provider as ended so external users can observe terminal state
try
{
Volatile.Write(ref _endedFlag, 1); Volatile.Write(ref _endedFlag, 1);
}
catch { }
s_unusedID.Push(TokenID); s_unusedID.Push(TokenID);
_event.Dispose(); _event.Dispose();
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
@@ -211,6 +207,7 @@ namespace StgSharp.Timing
{ {
// mark ended due to sequence timeout, then dispose // mark ended due to sequence timeout, then dispose
Volatile.Write(ref _endedFlag, 1); Volatile.Write(ref _endedFlag, 1);
Console.WriteLine("Time span ended.");
Dispose(); Dispose();
return false; return false;
} }
@@ -238,9 +235,6 @@ namespace StgSharp.Timing
return true; return true;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void Refresh() => _refreshHandler?.Invoke(this, EventArgs.Empty); // Legacy compatibility.
~TimeSpanProvider() => Dispose(); ~TimeSpanProvider() => Dispose();
} }
+16 -7
View File
@@ -39,15 +39,18 @@ namespace StgSharp.Timing
public partial class TimeSpanProvider public partial class TimeSpanProvider
{ {
private bool _subscribed; // private bool _subscribed;
private int _emittedSpanCount; // legacy counter private int _emittedSpanCount; // legacy counter
// internal ended flag (0 = running, 1 = ended) // internal ended flag (0 = running, 1 = ended)
private int _endedFlag = 0; private int _endedFlag;
private readonly TimeSequence _sequence; private readonly TimeSequence _sequence;
private readonly TimeSourceProviderBase _timeSource; 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(provider);
ArgumentNullException.ThrowIfNull(sequence); ArgumentNullException.ThrowIfNull(sequence);
@@ -55,8 +58,10 @@ namespace StgSharp.Timing
_sequence = sequence; _sequence = sequence;
_sequence.StartFrom(provider); _sequence.StartFrom(provider);
provider.AddSubscriber(this); 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); id = Interlocked.Increment(ref s_maxID);
} }
TokenID = id; TokenID = id;
@@ -70,16 +75,20 @@ namespace StgSharp.Timing
/// </summary> /// </summary>
public bool IsEnded => Volatile.Read(ref _endedFlag) != 0; public bool IsEnded => Volatile.Read(ref _endedFlag) != 0;
/// <summary>
/// Current emitted time in seconds relative to the sequence beginning.
/// </summary>
public double CurrentSecond public double CurrentSecond
{ {
get => (double)_sequence.PreviousFrameTick / _timeSource.Frequency; get => (double)(_sequence.PreviousFrameTick - _sequence.BeginningTick) / _timeSource.Frequency;
} }
public int CurrentSpan => _emittedSpanCount; public int CurrentSpan => _emittedSpanCount;
public static TimeSourceProviderBase DefaultProvider => World.MainTimeProvider; 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;
} }
} }
@@ -58,7 +58,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel<float>* leftPtr = left.Buffer; MatrixKernel<float>* leftPtr = left.Buffer;
MatrixKernel<float>* rightPtr = right.Buffer; MatrixKernel<float>* rightPtr = right.Buffer;
MatrixKernel<float>* ansPtr = ans.Buffer; MatrixKernel<float>* ansPtr = ans.Buffer;
NativeIntrinsic.Intrinsic.f32_add(leftPtr, rightPtr, ansPtr, count); NativeIntrinsic.Intrinsic.f32_buffer_add(leftPtr, rightPtr, ansPtr, count);
return ans; return ans;
} else if (count <= 1024) } else if (count <= 1024)
@@ -68,7 +68,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel<float>* leftPtr = left.Buffer; MatrixKernel<float>* leftPtr = left.Buffer;
MatrixKernel<float>* rightPtr = right.Buffer; MatrixKernel<float>* rightPtr = right.Buffer;
MatrixKernel<float>* ansPtr = ans.Buffer; MatrixKernel<float>* ansPtr = ans.Buffer;
NativeIntrinsic.Intrinsic.f32_add(leftPtr, rightPtr, ansPtr, count); NativeIntrinsic.Intrinsic.f32_buffer_add(leftPtr, rightPtr, ansPtr, count);
MatrixParallel.ReturnParallelResources(ref pool); MatrixParallel.ReturnParallelResources(ref pool);
return ans; return ans;
@@ -81,7 +81,7 @@ namespace StgSharp.Mathematics.Numeric
package->PrimCount = left.KernelColumnLength; package->PrimCount = left.KernelColumnLength;
package->SecCount = left.KernelRowLength; package->SecCount = left.KernelRowLength;
package->ComputeMode = new MatrixOpMode(MatrixOperationStyle.BUFFER_OP, MatrixOperationParam.LEFT_RIGHT_ANS_PARAM); 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); MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package);
MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep); MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep);
@@ -96,12 +96,12 @@ namespace StgSharp.Mathematics.Numeric
scalar->Data<float>(0) = value; scalar->Data<float>(0) = value;
if (count <= 256) if (count <= 256)
{ {
NativeIntrinsic.Intrinsic.f32_fill(ans.Buffer, scalar, count); NativeIntrinsic.Intrinsic.f32_buffer_fill(ans.Buffer, scalar, count);
return; return;
} else if (count <= 1024) } else if (count <= 1024)
{ {
MatrixParallelThread[] pool = MatrixParallel.LeadParallel(1); 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); MatrixParallel.ReturnParallelResources(ref pool);
return; return;
} }
@@ -111,7 +111,7 @@ namespace StgSharp.Mathematics.Numeric
package->PrimCount = ans.KernelColumnLength; package->PrimCount = ans.KernelColumnLength;
package->SecCount = ans.KernelRowLength; package->SecCount = ans.KernelRowLength;
package->ComputeMode = new MatrixOpMode(MatrixOperationStyle.BUFFER_OP, MatrixOperationParam.ANS_SCALAR_PARAM); 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; package->Scalar = scalar;
MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package); MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package);
MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep); MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep);
@@ -144,7 +144,7 @@ namespace StgSharp.Mathematics.Numeric
{ {
MatrixKernel<float>* leftPtr = left.Buffer; MatrixKernel<float>* leftPtr = left.Buffer;
MatrixKernel<float>* ansPtr = ans.Buffer; MatrixKernel<float>* ansPtr = ans.Buffer;
NativeIntrinsic.Intrinsic.f32_scalar_mul(leftPtr, ansPtr, scalar, count); NativeIntrinsic.Intrinsic.f32_buffer_scalar_mul(leftPtr, ansPtr, scalar, count);
return ans; return ans;
} else if (count <= 1024) } else if (count <= 1024)
@@ -153,7 +153,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel<float>* leftPtr = left.Buffer; MatrixKernel<float>* leftPtr = left.Buffer;
MatrixKernel<float>* ansPtr = ans.Buffer; MatrixKernel<float>* 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); MatrixParallel.ReturnParallelResources(ref pool);
return ans; return ans;
@@ -166,7 +166,7 @@ namespace StgSharp.Mathematics.Numeric
package->SecCount = left.KernelRowLength; package->SecCount = left.KernelRowLength;
package->Scalar = scalar; package->Scalar = scalar;
package->ComputeMode = new MatrixOpMode(MatrixOperationStyle.BUFFER_OP, MatrixOperationParam.RIGHT_ANS_SCALAR_PARAM); 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); MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package);
MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep); MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep);
@@ -192,7 +192,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel<float>* leftPtr = left.Buffer; MatrixKernel<float>* leftPtr = left.Buffer;
MatrixKernel<float>* rightPtr = right.Buffer; MatrixKernel<float>* rightPtr = right.Buffer;
MatrixKernel<float>* ansPtr = ans.Buffer; MatrixKernel<float>* ansPtr = ans.Buffer;
NativeIntrinsic.Intrinsic.f32_sub(leftPtr, rightPtr, ansPtr, count); NativeIntrinsic.Intrinsic.f32_buffer_sub(leftPtr, rightPtr, ansPtr, count);
return ans; return ans;
} else if (count <= 1024) } else if (count <= 1024)
@@ -202,7 +202,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel<float>* leftPtr = left.Buffer; MatrixKernel<float>* leftPtr = left.Buffer;
MatrixKernel<float>* rightPtr = right.Buffer; MatrixKernel<float>* rightPtr = right.Buffer;
MatrixKernel<float>* ansPtr = ans.Buffer; MatrixKernel<float>* ansPtr = ans.Buffer;
NativeIntrinsic.Intrinsic.f32_sub(leftPtr, rightPtr, ansPtr, count); NativeIntrinsic.Intrinsic.f32_buffer_sub(leftPtr, rightPtr, ansPtr, count);
MatrixParallel.ReturnParallelResources(ref pool); MatrixParallel.ReturnParallelResources(ref pool);
return ans; return ans;
@@ -215,7 +215,7 @@ namespace StgSharp.Mathematics.Numeric
package->PrimCount = left.KernelColumnLength; package->PrimCount = left.KernelColumnLength;
package->SecCount = left.KernelRowLength; package->SecCount = left.KernelRowLength;
package->ComputeMode = new MatrixOpMode(MatrixOperationStyle.BUFFER_OP, MatrixOperationParam.LEFT_RIGHT_ANS_PARAM); 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); MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package);
MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep); MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep);
+2 -2
View File
@@ -148,7 +148,7 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="sn-src\k_build_panel.c" /> <ClCompile Include="sn-src\k_panel.c" />
<ClCompile Include="sn-src\k_basicop.c" /> <ClCompile Include="sn-src\k_basicop.c" />
<ClCompile Include="sn-src\dllmain.c" /> <ClCompile Include="sn-src\dllmain.c" />
<ClCompile Include="sn-src\k_bufop.c" /> <ClCompile Include="sn-src\k_bufop.c" />
@@ -156,7 +156,7 @@
<ClCompile Include="sn-src\k_fma.c" /> <ClCompile Include="sn-src\k_fma.c" />
<ClCompile Include="sn-src\str_hash.c" /> <ClCompile Include="sn-src\str_hash.c" />
<ClCompile Include="sn-src\load_intrinsic.c"> <ClCompile Include="sn-src\load_intrinsic.c">
<FileType>CppCode</FileType> <FileType>CCode</FileType>
</ClCompile> </ClCompile>
<ClCompile Include="sn-src\load_glfw.c" /> <ClCompile Include="sn-src\load_glfw.c" />
<ClCompile Include="sn-src\sn_native.c" /> <ClCompile Include="sn-src\sn_native.c" />
@@ -51,7 +51,7 @@
<ClCompile Include="sn-src\k_bufop.c"> <ClCompile Include="sn-src\k_bufop.c">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="sn-src\k_build_panel.c"> <ClCompile Include="sn-src\k_panel.c">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
+16 -15
View File
@@ -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 #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_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_RA)(mat_panel *right, mat_panel *ans);
typedef void(SN_DECL *PNL_PROC_LRAS)(mat_panel *left, 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 #pragma endregion
typedef void(SN_DECL *BUILD_PANEL_PROC)(mat_panel *panel, mat_kernel *kernel, int col_length, // Mirrors C# IntrinsicContext field order so managed/unmanaged layouts stay in sync.
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
typedef struct sn_intrinsic { typedef struct sn_intrinsic {
HASH city_hash_simplify; // city_hash_simplify HASH city_hash_simplify;
BUF_PROC_LRA f32_buffer_add; // f32_add BUF_PROC_LRA f32_buffer_add;
BUF_PROC_AS f32_buffer_fill; // f32_fill BUF_PROC_AS f32_buffer_fill;
PNL_PROC_LRA f32_panel_fma; // f32_fma (panel variant) BUF_PROC_RAS f32_buffer_scalar_mul;
BUF_PROC_LRA f32_kernel_scalar_mul; // f32_scalar_mul (right+ans+scalar variant mapped here) BUF_PROC_LRA f32_buffer_sub;
BUF_PROC_LRA f32_kernel_sub; // f32_sub KER_PROC_RA f32_buffer_transpose;
KER_PROC_RA f32_kernel_transpose; // f32_transpose PANEL_PROC f32_build_panel;
FACTORIALROC factorial_simd; // factorial_simd VECTORNORMALIZEPROC f32_normalize_3;
INDEX_PAIR index_pair; // index_pair PNL_PROC_LRA f32_panel_fma;
VECTORNORMALIZEPROC f32_normalize_3; // normalize_3 PANEL_PROC f32_store_panel;
FACTORIALROC factorial_simd;
INDEX_PAIR index_pair;
BUF_PROC_RAS variant;
} sn_intrinsic; } sn_intrinsic;
typedef enum most_advanced_instruction { typedef enum most_advanced_instruction {
+36 -23
View File
@@ -1,14 +1,17 @@
#ifndef SN_MATKERNEL #ifndef SN_MATKERNEL
#define 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 <immintrin.h> #include <immintrin.h>
#include <stdint.h> #include <stdint.h>
#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) \ #define MAT_KERNEL(T) \
union { \ union { \
__m128 xmm[XMMCOUNT(T) / 4]; \ __m128 xmm[XMMCOUNT(T) / 4]; \
@@ -25,7 +28,8 @@
T v[4]; \ 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): */ /* Helpers (all compile-time): */
#define SN_LANES(T_VEC, T) (sizeof(T_VEC) / sizeof(T)) #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 - SIMD view remains integer-typed; cast inside micro-kernels to the
appropriate floating-point/integer vector type on demand. appropriate floating-point/integer vector type on demand.
*/ */
#define MAT_PANEL_SQ_MIN(T, T_VEC, MINQ) \ #define MAT_PANEL_SQ_MIN_NOALIGN(T, T_VEC, MINQ) \
SN_ALIGNAS(sizeof(T_VEC)) union { \ union { \
T_VEC vec[PANEL_Q(T, T_VEC, MINQ)][PANEL_CHUNKS(T, T_VEC, MINQ)]; \ 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)]; \ 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. /* 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). 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. */ 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. /* 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. 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. */ 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. /* 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. 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. */ 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): /* Access helpers (all compile-time friendly):
Given Q = PANEL_Q(...), CH = PANEL_CHUNKS(...), R = lanes per vector: Given Q = PANEL_Q(...), CH = PANEL_CHUNKS(...), R = lanes per vector:
- Column c occupies vec[c][0..CH-1]. - Column c occupies vec[c][0..CH-1].
- Row r inside column c is located at vec[c][r / R] with lane (r % R). - 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)]) #define PANEL_COL_VEC(panel_obj, c, chunk) ((panel_obj).vec[(int)(c)][(int)(chunk)])
/* Scalar flat index helper for column-major addressing */ /* Scalar flat index helper for column-major addressing */
#define PANEL_ELEM(panel_obj, T, T_VEC, MINQ, r, c) \ #define PANEL_ELEM(panel_obj, T, T_VEC, MINQ, r, c) \
((panel_obj).flat[(int)(c) * PANEL_Q(T, T_VEC, MINQ) + (int)(r)]) ((panel_obj).flat[(int)(c) * PANEL_Q(T, T_VEC, MINQ) + (int)(r)])
/* API macros */
#define BUILD_PANEL(arch, element) build_panel_##arch##_##element #define BUILD_PANEL(arch, element) build_panel_##arch##_##element
#define STORE_PANEL(arch, element) store_panel_##arch##_##element
#include "sn_internal.h"
#define DECLARE_BUILD_PANEL(arch, element) \ #define DECLARE_BUILD_PANEL(arch, element) \
INTERNAL void SN_DECL BUILD_PANEL(arch, element)( \ INTERNAL void SN_DECL BUILD_PANEL(arch, element)( \
MAT_PANEL_##arch(element) *restrict panel, \ MAT_PANEL_##arch(element) *restrict panel, \
MAT_KERNEL(element) const *const matrix, int col_length, int row_length, \ MAT_KERNEL(element) const *const matrix, int col_length, int row_length, \
int col_index, int row_index) 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_BUILD_PANEL(AVX, float);
DECLARE_STORE_PANEL(AVX, float);
#endif /* SN_MATKERNEL */
+9 -2
View File
@@ -1,16 +1,23 @@
#include "StgSharpNative.h" #include "StgSharpNative.h"
#include "sn_matkernel.h" #include "sn_matkernel.h"
#include <stdint.h>
#ifdef _WIN32 #ifdef _WIN32
/* Define and initialize a global zero kernel aligned to 64 bytes for universal ISA usage */ /* 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) static void init_zero_kernel(void)
{ {
for (int c = 0; c < 4; ++c) { for (int c = 0; c < 4; ++c) {
for (int r = 0; r < 4; ++r) { for (int r = 0; r < 4; ++r) {
SN_ZERO_KERNEL.m[r][c] = 0.0; SN_ZERO_KERNEL.m[r][c] = 0;
} }
} }
} }
-42
View File
@@ -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;
}
}
+98
View File
@@ -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;
}
}
+12 -9
View File
@@ -68,9 +68,10 @@ void load_intrinsic_sse(sn_intrinsic *context)
context->f32_buffer_add = BUF_PROC(float, sse, add); context->f32_buffer_add = BUF_PROC(float, sse, add);
context->f32_panel_fma = KER_PROC(float, sse, fma); context->f32_panel_fma = KER_PROC(float, sse, fma);
context->f32_buffer_fill = BUF_PROC(float, sse, fill); context->f32_buffer_fill = BUF_PROC(float, sse, fill);
context->f32_kernel_scalar_mul = BUF_PROC(float, sse, scalar_mul); context->variant = BUF_PROC(float, sse, scalar_mul);
context->f32_kernel_sub = BUF_PROC(float, sse, sub); context->f32_buffer_sub = BUF_PROC(float, sse, sub);
context->f32_kernel_transpose = KER_PROC(float, sse, transpose); 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; 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_buffer_add = BUF_PROC(float, avx, add);
context->f32_panel_fma = KER_PROC(float, sse, fma); context->f32_panel_fma = KER_PROC(float, sse, fma);
context->f32_buffer_fill = BUF_PROC(float, avx, fill); context->f32_buffer_fill = BUF_PROC(float, avx, fill);
context->f32_kernel_scalar_mul = BUF_PROC(float, avx, scalar_mul); context->variant = BUF_PROC(float, avx, scalar_mul);
context->f32_kernel_sub = BUF_PROC(float, avx, sub); context->f32_buffer_sub = BUF_PROC(float, avx, sub);
context->f32_kernel_transpose = KER_PROC(float, avx, transpose); 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; 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_buffer_add = BUF_PROC(float, 512, add);
context->f32_panel_fma = KER_PROC(float, sse, fma); context->f32_panel_fma = KER_PROC(float, sse, fma);
context->f32_buffer_fill = BUF_PROC(float, 512, fill); context->f32_buffer_fill = BUF_PROC(float, 512, fill);
context->f32_kernel_scalar_mul = BUF_PROC(float, 512, scalar_mul); context->variant = BUF_PROC(float, 512, scalar_mul);
context->f32_kernel_sub = BUF_PROC(float, 512, sub); context->f32_buffer_sub = BUF_PROC(float, 512, sub);
context->f32_kernel_transpose = KER_PROC(float, 512, transpose); 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; context->f32_normalize_3 = f32_normalize;
} }
+37 -2
View File
@@ -25,10 +25,12 @@
// //
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
using StgSharp.Common.Timing;
using StgSharp.HighPerformance; using StgSharp.HighPerformance;
using StgSharp.HighPerformance.Memory; using StgSharp.HighPerformance.Memory;
using StgSharp.Internal; using StgSharp.Internal;
using StgSharp.Mathematics.Numeric; using StgSharp.Mathematics.Numeric;
using StgSharp.Timing;
namespace StgSharp namespace StgSharp
{ {
@@ -49,9 +51,9 @@ namespace StgSharp
// TestRender(); // TestRender();
// TestHlsf(); // TestHlsf();
// HlsfStressTest.Run(); // HlsfStressTest.Run();
M128 v = new M128(); /*
/**/
HybridLayerSegregatedFitAllocator hlsf; HybridLayerSegregatedFitAllocator hlsf;
unchecked { unchecked {
hlsf = new((nuint)(64 * (ulong)10000 * 10000)); hlsf = new((nuint)(64 * (ulong)10000 * 10000));
@@ -84,7 +86,40 @@ namespace StgSharp
Console.WriteLine(); 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) catch (Exception ex)
{ {