time service contains bug, it cannot stop after edge
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user