better kernel fma

This commit is contained in:
Youmu Liu
2026-01-07 18:06:36 +08:00
parent 3d488abd2e
commit 88af8d8957
11 changed files with 347 additions and 149 deletions
+56 -21
View File
@@ -1,4 +1,4 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="Platform"
// Project: StgSharp
@@ -55,15 +55,28 @@ namespace StgSharp
private static uint markCount = 0;
internal static GraphicAPI API = default;
public static int DefaultSIMDAlignment => NativeIntrinsic.IntrinsicLevel switch
public static unsafe int DefaultSIMDAlignment
{
IntrinsicLevel.SSE => 16,
IntrinsicLevel.AVX2 => 32,
IntrinsicLevel.AVX512 => 64,
IntrinsicLevel.NEON => 16,
IntrinsicLevel.Non => 8,
_ => 8,
};
get
{
SIMDID id = NativeIntrinsic.IntrinsicMask;
switch (id.MaskByte[0] & 0b_00001111)
{
case 1:
return id.MaskByte[1] switch
{
1 => 16,
2 => 32,
3 => 64,
4 => 64,
5 => 64,
_ => 8,
};
default:
return 8;
}
}
}
public static ModuleToInitializeCollection Initialize()
{
@@ -71,31 +84,41 @@ namespace StgSharp
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void LogError(Exception ex)
public static void LogError(
Exception ex
)
{
DefaultLog.InternalWriteLog(ex.Message, LogType.Error);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void LogInfo(string log)
public static void LogInfo(
string log
)
{
DefaultLog.InternalWriteLog(log, LogType.Info);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void LogWarning(string log)
public static void LogWarning(
string log
)
{
DefaultLog.InternalWriteLog(log, LogType.Warning);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void LogWarning(Exception notVerySeriesException)
public static void LogWarning(
Exception notVerySeriesException
)
{
DefaultLog.InternalWriteLog(notVerySeriesException.Message, LogType.Warning);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Mark(bool needConsole)
public static void Mark(
bool needConsole
)
{
markCount++;
if (needConsole) {
@@ -103,7 +126,9 @@ namespace StgSharp
}
}
public static void Terminate(int exitCode)
public static void Terminate(
int exitCode
)
{
MainTimeProvider.StopProvidingTime();
GraphicFramework.glfwTerminate();
@@ -116,7 +141,8 @@ namespace StgSharp
bool isConsole,
[CallerFilePath] string filePath = "",
[CallerMemberName] string callerName = "",
[CallerLineNumber] int lineNumber = 0)
[CallerLineNumber] int lineNumber = 0
)
{
Type t = target.GetType();
string log = $"Tracked object: {nameof(target)}\t\tType:{t.Name}\n";
@@ -147,12 +173,17 @@ namespace StgSharp
/// The severity of current message.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteLog(string message, LogType logType)
public static void WriteLog(
string message,
LogType logType
)
{
DefaultLog.InternalWriteLog(message, logType);
}
internal static TDele ConvertAPI<TDele>(IntPtr funcPtr)
internal static TDele ConvertAPI<TDele>(
IntPtr funcPtr
)
{
if (funcPtr == IntPtr.Zero) {
throw new InvalidCastException(
@@ -168,7 +199,10 @@ namespace StgSharp
}
}
internal static Delegate ConvertAPI(IntPtr funcPtr, Type T)
internal static Delegate ConvertAPI(
IntPtr funcPtr,
Type T
)
{
if (funcPtr == IntPtr.Zero) {
throw new InvalidCastException(
@@ -197,12 +231,13 @@ namespace StgSharp
$"Program {Assembly.GetEntryAssembly()!.FullName} on {Environment.MachineName} Started.", LogType.Info);
MainThreadID = System.Environment.CurrentManagedThreadId;
/**/
Dialogue.NeedShowWhenStartup = false;
Dialogue.LoadDialogue();
if (Dialogue.NeedShowWhenStartup) {
Dialogue.CreateDialogueProcessIfNotExist();
}
/**/
NativeIntrinsic.InitIntrinsicContext();
}
+42 -17
View File
@@ -46,13 +46,17 @@ namespace StgSharp.HighPerformance
return (MatrixPanel<T>*)NativeMemory.AlignedAlloc(Size<T>(), AlignmentBytes);
}
public static unsafe void Destroy<T>(MatrixPanel<T>* panel) where T : unmanaged, INumber<T>
public static unsafe void Destroy<T>(
MatrixPanel<T>* panel
) where T : unmanaged, INumber<T>
{
NativeMemory.AlignedFree(panel);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe Span<T> Elements<T>(ref T head) where T : unmanaged, INumber<T>
public static unsafe Span<T> Elements<T>(
ref T head
) where T : unmanaged, INumber<T>
{
void* p = Unsafe.AsPointer(ref head);
return new Span<T>(p, MaxElementCount<T>());
@@ -92,17 +96,26 @@ namespace StgSharp.HighPerformance
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int KernelSideCount<T>() where T : unmanaged, INumber<T>
{
return NativeIntrinsic.IntrinsicLevel switch
SIMDID id = NativeIntrinsic.IntrinsicMask;
switch (id.MaskByte[0] & 0b_00001111)
{
IntrinsicLevel.SSE => KernelSideCountSse<T>(),
IntrinsicLevel.AVX2 => KernelSideCountAvx2<T>(),
IntrinsicLevel.AVX512 => KernelSideCountAvx512<T>(),
_ => 0
};
case 1:
return id.MaskByte[1] switch
{
1 => KernelSideCountSse<T>(),
2 => KernelSideCountAvx2<T>(),
3 => KernelSideCountAvx512<T>(),
_ => throw new NotSupportedException("Unsupported SIMD level."),
};
default:
throw new NotSupportedException("Current hardware platform is not supported");
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe nuint Align64(void* p) => ((nuint)p + (AlignmentBytes - 1)) & ~(nuint)(AlignmentBytes - 1);
private static unsafe nuint Align64(
void* p
) => ((nuint)p + (AlignmentBytes - 1)) & ~(nuint)(AlignmentBytes - 1);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int KernelSideCountAvx2<T>() where T : unmanaged, INumber<T>
@@ -123,7 +136,9 @@ namespace StgSharp.HighPerformance
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int PanelSideFromBits<T>(int vectorBits) where T : unmanaged, INumber<T>
private static int PanelSideFromBits<T>(
int vectorBits
) where T : unmanaged, INumber<T>
{
int elemBits = sizeof(T) * 8;
@@ -137,13 +152,20 @@ namespace StgSharp.HighPerformance
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int PanelSideLength<T>() where T : unmanaged, INumber<T>
{
return NativeIntrinsic.IntrinsicLevel switch
SIMDID id = NativeIntrinsic.IntrinsicMask;
switch (id.MaskByte[0] & 0b_00001111)
{
IntrinsicLevel.SSE => PanelSideFromBits<T>(128),
IntrinsicLevel.AVX2 => PanelSideFromBits<T>(256),
IntrinsicLevel.AVX512 => PanelSideFromBits<T>(512),
_ => 0
};
case 1:
return id.MaskByte[1] switch
{
1 => PanelSideFromBits<T>(128),
2 => PanelSideFromBits<T>(256),
3 => PanelSideFromBits<T>(512),
_ => throw new NotSupportedException("Unsupported SIMD level."),
};
default:
throw new NotSupportedException("Current hardware platform is not supported");
}
}
}
@@ -154,7 +176,10 @@ namespace StgSharp.HighPerformance
internal T Head; // first element of the panel buffer
public ref T this[int column, int row]
public ref T this[
int column,
int row
]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref Unsafe.Add(ref Head, row * MatrixPanel.ElementSideLength<T>() + column);
@@ -0,0 +1,51 @@
//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="SIMDID"
// Project: StgSharp
// AuthorGroup: Nitload
// Copyright (c) Nitload. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace StgSharp.Internal.Intrinsic
{
[StructLayout(LayoutKind.Explicit)]
internal unsafe struct SIMDID
{
[FieldOffset(0)]public fixed byte MaskByte[16];
[FieldOffset(0)]public ulong Mask;
public SIMDID()
{
Unsafe.SkipInit(out this);
}
}
}
@@ -39,7 +39,7 @@ namespace StgSharp.Internal
private static readonly IntrinsicContext _intrinsicContext = new();
public static IntrinsicLevel IntrinsicLevel { get; set; }
public static SIMDID IntrinsicMask { get; set; }
internal static IntrinsicContext Context
{
@@ -49,39 +49,32 @@ namespace StgSharp.Internal
internal static void InitIntrinsicContext()
{
int statCode;
ulong statCode = 0;
fixed (IntrinsicContext* cPtr = &_intrinsicContext) {
statCode = LoadIntrinsicFunction(cPtr);
}
switch (statCode)
SIMDID id = new()
{
Mask = statCode
};
switch (id.MaskByte[1])
{
case 0:
Dialogue.PostError(new PlatformNotSupportedException("No SIMD instructions supported on current hardware platform"));
Environment.Exit(-1);
break;
default:
IntrinsicLevel = (IntrinsicLevel)statCode;
break;
}
IntrinsicMask = id;
}
[LibraryImport(Native.LibName, EntryPoint = "load_intrinsic_function")]
[UnmanagedCallConv(CallConvs =[ typeof(CallConvCdecl) ])]
private static partial int LoadIntrinsicFunction(IntrinsicContext* context);
}
internal enum IntrinsicLevel : sbyte
{
Non = 0,
SSE = 1,
AVX2 = 2,
AVX512 = 3,
NEON = -1
private static partial ulong LoadIntrinsicFunction(
IntrinsicContext* context
);
}
}
+2 -5
View File
@@ -178,12 +178,9 @@ namespace StgSharp.Mathematics.Numeric
)
{
// Caller guarantees: indices in range, layout is dense square.
int k_c = y >> 2;
int k_r = x >> 2;
MatrixKernelEnumerator enumerator = new(_size.KernelColumnLength, _size.KernelRowLength,
k_c, k_r);
return Buffer + _boarder.GetIndexOffset(k_c, k_r, in enumerator);
x, y);
return Buffer + _boarder.GetIndexOffset(x, y, in enumerator);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+4 -8
View File
@@ -1,4 +1,4 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="Random"
// Project: StgSharp
@@ -88,7 +88,7 @@ namespace StgSharp.Mathematics
///
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Random<T>() where T: unmanaged, IConvertible, INumber<T>
public static T Random<T>() where T : unmanaged, IConvertible, INumber<T>
{
if (randomSeed == null)
@@ -97,13 +97,9 @@ namespace StgSharp.Mathematics
string originSeed =
($"{((Assembly.GetEntryAssembly() == null) ? (Assembly.GetAssembly(typeof(World))!) :
Assembly.GetEntryAssembly())}") + ($"{DateTime.UtcNow.ToString("o")}");
using (SHA256 sha = SHA256.Create()) {
randomSeed = sha.ComputeHash(Encoding.UTF8.GetBytes(originSeed));
}
}
using (SHA256 sha = SHA256.Create()) {
randomSeed = sha.ComputeHash(randomSeed);
randomSeed = SHA256.HashData(Encoding.UTF8.GetBytes(originSeed));
}
randomSeed = SHA256.HashData(randomSeed);
fixed (byte* bptr = randomSeed) {
return *(T*)bptr;
}