rewrite of f32 fma, and other optmization of simd kernel ops
This commit is contained in:
@@ -91,7 +91,7 @@ namespace StgSharp.Collections
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ReadOnlySpan<T> PopRange(int count)
|
||||
public T[] PopRange(int count)
|
||||
{
|
||||
int i = int.Min(count, _index) - 1;
|
||||
return _values[0..i];
|
||||
|
||||
@@ -34,12 +34,65 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.HighPerformance
|
||||
{
|
||||
public interface IRegisterType
|
||||
/// <summary>
|
||||
/// Abstraction for a wide SIMD register or equivalent packed numeric storage. Provides raw
|
||||
/// reference access, broadcast initialization and element level access. Typical
|
||||
/// implementations map to 128/256/512-bit hardware registers or software emulated blocks.
|
||||
/// </summary>
|
||||
|
||||
public interface IRegisterPresentation
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Gets a reference to the first element of the register reinterpreted as type <typeparamref
|
||||
/// name="T" />.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// Unmanaged numeric element type implementing <see cref="INumber{T}" />.
|
||||
/// </typeparam>
|
||||
/// <returns>
|
||||
/// Writable reference to element 0 (lowest lane / lowest bits).
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Intended for treating the register as a contiguous block of elements. The returned reference
|
||||
/// must remain valid for the lifetime of the register and be identical to <see
|
||||
/// cref="Member{T}(int)" /> with index 0. Caller must choose a type layout compatible with the
|
||||
/// actual register representation.
|
||||
/// </remarks>
|
||||
ref T AsRef<T>() where T: unmanaged, INumber<T>;
|
||||
|
||||
/// <summary>
|
||||
/// Fills all elements (lanes) of the register with the provided scalar <paramref name="value" />.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// Unmanaged numeric element type implementing <see cref="INumber{T}" />.
|
||||
/// </typeparam>
|
||||
/// <param name="value">
|
||||
/// Scalar value to replicate to every element.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// Should map to a single broadcast/shuffle instruction where possible. After completion all
|
||||
/// lanes read back the same value.
|
||||
/// </remarks>
|
||||
void BroadCastFrom<T>(T value) where T: unmanaged, INumber<T>;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a writable reference to the element at the specified <paramref name="index" />.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// Unmanaged numeric element type implementing <see cref="INumber{T}" />.
|
||||
/// </typeparam>
|
||||
/// <param name="index">
|
||||
/// Zero-based lane index (range defined by implementation).
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Writable reference to the lane.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Enables scalar lane edits without unpacking the entire register. Implementations may omit
|
||||
/// bounds checks for performance. Caller is responsible for passing a valid index.
|
||||
/// </remarks>
|
||||
ref T Member<T>(int index) where T: unmanaged, INumber<T>;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,11 @@ namespace StgSharp.HighPerformance
|
||||
return Vec.AsVector4();
|
||||
}
|
||||
|
||||
public void BroadCastFrom<T>(T value) where T: unmanaged, INumber<T>
|
||||
{
|
||||
Vec = Vector128.CreateScalarUnsafe(value).As<T, float>();
|
||||
}
|
||||
|
||||
public override readonly bool Equals([NotNullWhen(true)] object obj)
|
||||
{
|
||||
return obj is M128 other && this == other;
|
||||
|
||||
@@ -31,6 +31,7 @@ using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -41,6 +42,7 @@ namespace StgSharp.HighPerformance
|
||||
{
|
||||
|
||||
[FieldOffset(0)] internal fixed byte Buffer[32];
|
||||
[FieldOffset(0)] internal Vector256<float> Vec;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref T AsRef<T>() where T: unmanaged, INumber<T>
|
||||
@@ -48,6 +50,11 @@ namespace StgSharp.HighPerformance
|
||||
return ref Unsafe.As<byte, T>(ref Buffer[0]);
|
||||
}
|
||||
|
||||
public void BroadCastFrom<T>(T value) where T: unmanaged, INumber<T>
|
||||
{
|
||||
Vec = Vector256.CreateScalarUnsafe(value).As<T, float>();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref T Member<T>(int index) where T: unmanaged, INumber<T>
|
||||
{
|
||||
|
||||
@@ -31,6 +31,7 @@ using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -41,12 +42,18 @@ namespace StgSharp.HighPerformance
|
||||
{
|
||||
|
||||
[FieldOffset(0)]private fixed byte _buffer[64];
|
||||
[FieldOffset(0)]private Vector512<float> Vec;
|
||||
|
||||
public ref T AsRef<T>() where T: unmanaged, INumber<T>
|
||||
{
|
||||
return ref Unsafe.As<byte, T>(ref _buffer[0]);
|
||||
}
|
||||
|
||||
public void BroadCastFrom<T>(T value) where T: unmanaged, INumber<T>
|
||||
{
|
||||
Vec = Vector512.CreateScalarUnsafe(value).As<T, float>();
|
||||
}
|
||||
|
||||
public ref T Member<T>(int index) where T: unmanaged, INumber<T>
|
||||
{
|
||||
return ref Unsafe.As<byte, T>(ref _buffer[0]);
|
||||
|
||||
+23
-4
@@ -1,6 +1,6 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="IRegisterPresentation"
|
||||
// file="ScalarPacket"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
@@ -29,17 +29,36 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.HighPerformance
|
||||
{
|
||||
public interface IRegisterPresentation
|
||||
public unsafe struct ScalarPacket
|
||||
{
|
||||
|
||||
public ref T AsRef<T>() where T: unmanaged, INumber<T>;
|
||||
private fixed ulong data[8];
|
||||
|
||||
public ref T Member<T>(int index) where T: unmanaged, INumber<T>;
|
||||
public void BroadCast<TScalar, TRegister>(int slotIndex, TScalar value)
|
||||
where TScalar: unmanaged, INumber<TScalar>
|
||||
where TRegister: unmanaged, IRegisterPresentation
|
||||
{
|
||||
if (slotIndex is < 0 or >= 8) {
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
ref TRegister register = ref Unsafe.As<ulong, TRegister>(ref data[slotIndex]);
|
||||
register.BroadCastFrom(value);
|
||||
}
|
||||
|
||||
public ref T Data<T>(int index) where T: unmanaged, INumber<T>
|
||||
{
|
||||
if (index is < 0 or >= 8) {
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
return ref Unsafe.As<ulong, T>(ref data[index]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using StgSharp.HighPerformance;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -38,8 +39,9 @@ namespace StgSharp.Internal.Intrinsic
|
||||
|
||||
public delegate* unmanaged[Cdecl]<char*, int, int> city_hash_simplify;
|
||||
public delegate* unmanaged[Cdecl]<void*, void*, void*, void> f32_add;
|
||||
public delegate* unmanaged[Cdecl]<void*, ScalarPacket*, void> f32_fill;
|
||||
public delegate* unmanaged[Cdecl]<void*, void*, void*, void> f32_fma;
|
||||
public delegate* unmanaged[Cdecl]<void*, float, void*, void> f32_scalar_mul;
|
||||
public delegate* unmanaged[Cdecl]<void*, void*, ScalarPacket*, void> f32_scalar_mul;
|
||||
public delegate* unmanaged[Cdecl]<void*, void*, void*, void> f32_sub;
|
||||
public delegate* unmanaged[Cdecl]<void*, void*, void> f32_transpose;
|
||||
public delegate* unmanaged[Cdecl]<int, ulong> factorial_simd;
|
||||
@@ -52,4 +54,4 @@ namespace StgSharp.Internal.Intrinsic
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user