better kernel fma
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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)]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -142,9 +142,13 @@ namespace StgSharp.Mathematics.Numeric
|
||||
{
|
||||
throw new IndexOutOfRangeException("Matrix dimensions must agree.");
|
||||
}
|
||||
if (left.Layout != MatrixLayout.DenseRectangle ||
|
||||
right.Layout != MatrixLayout.DenseRectangle ||
|
||||
ans.Layout != MatrixLayout.DenseRectangle) {
|
||||
throw new NotSupportedException("Only dense rectangle matrices are supported.");
|
||||
}
|
||||
long count = (long)left.KernelColumnLength * left.KernelRowLength;
|
||||
|
||||
// int size = MatrixPanel.KernelSideCount<float>();
|
||||
if (count <= 1024)
|
||||
{
|
||||
MatrixParallelThread[] pool = null;
|
||||
@@ -155,15 +159,22 @@ namespace StgSharp.Mathematics.Numeric
|
||||
{
|
||||
for (int j = 0; j < ans.KernelColumnLength; j++)
|
||||
{
|
||||
MatrixKernel<float>* ansPanel = ans.GetKernelAddressUnsafe(i, j);
|
||||
NativeIntrinsic.Context.mat[f32].clear_panel((MatrixPanel*)ansPanel);
|
||||
MatrixKernel<float>* ansPanel = GetKernelAddressUnsafe(ans.Buffer,
|
||||
ans.KernelColumnLength,
|
||||
i, j);
|
||||
|
||||
// Console.WriteLine($"{i}{j}");
|
||||
// NativeIntrinsic.Context.mat[f32].clear_panel((MatrixPanel*)ansPanel);
|
||||
for (int k = 0; k < left.KernelColumnLength; k++)
|
||||
{
|
||||
NativeIntrinsic.Context
|
||||
.mat[f32].kernel_fma((MatrixPanel*)left.GetKernelAddressUnsafe(i, k),
|
||||
(MatrixPanel*)right.GetKernelAddressUnsafe(k, j),
|
||||
.mat[f32].kernel_fma((MatrixPanel*)GetKernelAddressUnsafe(left.Buffer,
|
||||
left.KernelColumnLength,
|
||||
i,
|
||||
k),
|
||||
(MatrixPanel*)GetKernelAddressUnsafe(right.Buffer,
|
||||
right.KernelColumnLength,
|
||||
k,
|
||||
j),
|
||||
(MatrixPanel*)ansPanel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ namespace StgSharp.Mathematics.Numeric
|
||||
)
|
||||
{
|
||||
int f32 = (int)MatrixElementType.F32;
|
||||
int size = MatrixPanel.KernelSideCount<float>();
|
||||
MatrixKernel* leftBuffer = (MatrixKernel*)p->Left;
|
||||
MatrixKernel* rightBuffer = (MatrixKernel*)p->Right;
|
||||
MatrixKernel* ansBuffer = (MatrixKernel*)p->Answer;
|
||||
@@ -62,17 +61,15 @@ namespace StgSharp.Mathematics.Numeric
|
||||
{
|
||||
int i = (int)(c / ansWidth);
|
||||
int j = (int)(c % ansWidth);
|
||||
MatrixKernel<float>* ansPanel = GetKernelAddressUnsafe((MatrixKernel<float>*)ansBuffer,
|
||||
ansHeight, i, j);
|
||||
NativeIntrinsic.Context.mat[f32].clear_panel((MatrixPanel*)ansPanel);
|
||||
for (int k = 0; k < commonK; k += size) {
|
||||
for (int k = 0; k < commonK; k++) {
|
||||
NativeIntrinsic.Context
|
||||
.mat[f32].kernel_fma(
|
||||
(MatrixPanel*)GetKernelAddressUnsafe((MatrixKernel<float>*)leftBuffer,
|
||||
ansHeight, k, j),
|
||||
(MatrixPanel*)GetKernelAddressUnsafe((MatrixKernel<float>*)rightBuffer,
|
||||
commonK, j, k),
|
||||
(MatrixPanel*)ansPanel);
|
||||
(MatrixPanel*)GetKernelAddressUnsafe((MatrixKernel<float>*)ansBuffer,
|
||||
ansHeight, i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ static int is_intel_native_avx512(int family, int model)
|
||||
|
||||
SN_API SIMDID SN_DECL sn_get_simd_level()
|
||||
{
|
||||
if (!global_simdid.mask) {
|
||||
if (global_simdid.mask) {
|
||||
return global_simdid;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
#define _FMA_SELECT(i) _MM_SHUFFLE(i, i, i, i)
|
||||
|
||||
// ans = left * right + ans
|
||||
// right is not transposed
|
||||
// float
|
||||
|
||||
DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, sse, , fma)
|
||||
{
|
||||
const __m128 a0 = _mm_load_ps((float *)&left->f32_x[0]);
|
||||
@@ -57,56 +57,18 @@ DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, sse, , fma)
|
||||
ans->f32_x[3] = c3;
|
||||
}
|
||||
|
||||
DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, _fma, fma)
|
||||
{
|
||||
register __m256 a01 = _mm256_load_ps((float *)&left->f32_y[0]);
|
||||
register __m256 a23 = _mm256_load_ps((float *)&left->f32_y[1]);
|
||||
|
||||
register __m256 b01 = _mm256_load_ps((float *)&right->f32_y[0]);
|
||||
register __m256 b23 = _mm256_load_ps((float *)&right->f32_y[1]);
|
||||
|
||||
register __m256 c01 = _mm256_load_ps((float *)&ans->f32_y[0]);
|
||||
register __m256 c23 = _mm256_load_ps((float *)&ans->f32_y[1]);
|
||||
|
||||
//group 0
|
||||
register __m256 b01_perm = _mm256_shuffle_ps(b01, b01, _FMA_SELECT(0));
|
||||
register __m256 b23_perm = _mm256_shuffle_ps(b23, b23, _FMA_SELECT(0));
|
||||
c01 = _mm256_fmadd_ps(a01, b01_perm, c01);
|
||||
c23 = _mm256_fmadd_ps(a23, b23_perm, c23);
|
||||
|
||||
//group 2
|
||||
b01_perm = _mm256_shuffle_ps(b01, b01, _FMA_SELECT(2));
|
||||
b23_perm = _mm256_shuffle_ps(b23, b23, _FMA_SELECT(2));
|
||||
c01 = _mm256_fmadd_ps(a23, b01_perm, c01);
|
||||
c23 = _mm256_fmadd_ps(a01, b23_perm, c23);
|
||||
|
||||
//group 1
|
||||
register __m256 a12 = _mm256_permute2f128_ps(a01, a23, 0x21);
|
||||
register __m256 a03 = _mm256_permute2f128_ps(a01, a23, 0x30);
|
||||
b01_perm = _mm256_shuffle_ps(b01, b01, _FMA_SELECT(1));
|
||||
b23_perm = _mm256_shuffle_ps(b23, b23, _FMA_SELECT(1));
|
||||
c01 = _mm256_fmadd_ps(a12, b01_perm, c01);
|
||||
c23 = _mm256_fmadd_ps(a03, b23_perm, c23);
|
||||
|
||||
//group 3
|
||||
a12 = _mm256_permute2f128_ps(a01, a23, 0x21);
|
||||
a03 = _mm256_permute2f128_ps(a01, a23, 0x30);
|
||||
b01_perm = _mm256_shuffle_ps(b01, b01, _FMA_SELECT(3));
|
||||
b23_perm = _mm256_shuffle_ps(b23, b23, _FMA_SELECT(3));
|
||||
c01 = _mm256_fmadd_ps(a03, b01_perm, c01);
|
||||
c23 = _mm256_fmadd_ps(a12, b23_perm, c23);
|
||||
|
||||
ans->f32_y[0] = c01;
|
||||
ans->f32_y[1] = c23;
|
||||
}
|
||||
|
||||
DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, , fma)
|
||||
{
|
||||
static const __m256i b01_shift = { 0, 1, 2, 3, 5, 6, 7, 4 };
|
||||
static const __m256i b23_shift = { 2, 3, 0, 1, 7, 4, 5, 6 };
|
||||
|
||||
register __m256 a01 = _mm256_load_ps((float *)&left->f32_y[0]);
|
||||
register __m256 a23 = _mm256_load_ps((float *)&left->f32_y[1]);
|
||||
|
||||
register __m256 b01 = _mm256_load_ps((float *)&right->f32_y[0]);
|
||||
register __m256 b23 = _mm256_load_ps((float *)&right->f32_y[1]);
|
||||
b01 = _mm256_permutevar_ps(b01, b01_shift);
|
||||
b23 = _mm256_permutevar_ps(b23, b23_shift);
|
||||
|
||||
register __m256 c01 = _mm256_load_ps((float *)&ans->f32_y[0]);
|
||||
register __m256 c23 = _mm256_load_ps((float *)&ans->f32_y[1]);
|
||||
@@ -125,49 +87,186 @@ DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, , fma)
|
||||
|
||||
//group 1
|
||||
register __m256 a12 = _mm256_permute2f128_ps(a01, a23, 0x21);
|
||||
register __m256 a03 = _mm256_permute2f128_ps(a01, a23, 0x30);
|
||||
register __m256 a30 = _mm256_permute2f128_ps(a01, a23, 0x30);
|
||||
b01_perm = _mm256_shuffle_ps(b01, b01, _FMA_SELECT(1));
|
||||
b23_perm = _mm256_shuffle_ps(b23, b23, _FMA_SELECT(1));
|
||||
c01 = _mm256_add_ps(_mm256_mul_ps(a12, b01_perm), c01);
|
||||
c23 = _mm256_add_ps(_mm256_mul_ps(a03, b23_perm), c23);
|
||||
c23 = _mm256_add_ps(_mm256_mul_ps(a30, b23_perm), c23);
|
||||
|
||||
//group 3
|
||||
a12 = _mm256_permute2f128_ps(a01, a23, 0x21);
|
||||
a03 = _mm256_permute2f128_ps(a01, a23, 0x30);
|
||||
b01_perm = _mm256_shuffle_ps(b01, b01, _FMA_SELECT(3));
|
||||
b23_perm = _mm256_shuffle_ps(b23, b23, _FMA_SELECT(3));
|
||||
c01 = _mm256_add_ps(_mm256_mul_ps(a03, b01_perm), c01);
|
||||
c01 = _mm256_add_ps(_mm256_mul_ps(a30, b01_perm), c01);
|
||||
c23 = _mm256_add_ps(_mm256_mul_ps(a12, b23_perm), c23);
|
||||
|
||||
ans->f32_y[0] = c01;
|
||||
ans->f32_y[1] = c23;
|
||||
}
|
||||
|
||||
DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, _fma, fma)
|
||||
{
|
||||
static const __m256i b01_shift = { 0, 1, 2, 3, 5, 6, 7, 4 };
|
||||
static const __m256i b23_shift = { 2, 3, 0, 1, 7, 4, 5, 6 };
|
||||
|
||||
register __m256 a01 = _mm256_load_ps((float *)&left->f32_y[0]);
|
||||
register __m256 a23 = _mm256_load_ps((float *)&left->f32_y[1]);
|
||||
|
||||
register __m256 b01 = _mm256_load_ps((float *)&right->f32_y[0]);
|
||||
register __m256 b23 = _mm256_load_ps((float *)&right->f32_y[1]);
|
||||
b01 = _mm256_permutevar_ps(b01, b01_shift);
|
||||
b23 = _mm256_permutevar_ps(b23, b23_shift);
|
||||
|
||||
register __m256 c01 = _mm256_load_ps((float *)&ans->f32_y[0]);
|
||||
register __m256 c23 = _mm256_load_ps((float *)&ans->f32_y[1]);
|
||||
|
||||
//group 0
|
||||
register __m256 b01_perm = _mm256_shuffle_ps(b01, b01, _FMA_SELECT(0));
|
||||
register __m256 b23_perm = _mm256_shuffle_ps(b23, b23, _FMA_SELECT(0));
|
||||
c01 = _mm256_fmadd_ps(a01, b01_perm, c01);
|
||||
c23 = _mm256_fmadd_ps(a23, b23_perm, c23);
|
||||
|
||||
//group 2
|
||||
b01_perm = _mm256_shuffle_ps(b01, b01, _FMA_SELECT(2));
|
||||
b23_perm = _mm256_shuffle_ps(b23, b23, _FMA_SELECT(2));
|
||||
c01 = _mm256_fmadd_ps(a23, b01_perm, c01);
|
||||
c23 = _mm256_fmadd_ps(a01, b23_perm, c23);
|
||||
|
||||
//group 1
|
||||
register __m256 a12 = _mm256_permute2f128_ps(a01, a23, 0x21);
|
||||
register __m256 a30 = _mm256_permute2f128_ps(a01, a23, 0x30);
|
||||
b01_perm = _mm256_shuffle_ps(b01, b01, _FMA_SELECT(1));
|
||||
b23_perm = _mm256_shuffle_ps(b23, b23, _FMA_SELECT(1));
|
||||
c01 = _mm256_fmadd_ps(a12, b01_perm, c01);
|
||||
c23 = _mm256_fmadd_ps(a30, b23_perm, c23);
|
||||
|
||||
//group 3
|
||||
b01_perm = _mm256_shuffle_ps(b01, b01, _FMA_SELECT(3));
|
||||
b23_perm = _mm256_shuffle_ps(b23, b23, _FMA_SELECT(3));
|
||||
c01 = _mm256_fmadd_ps(a30, b01_perm, c01);
|
||||
c23 = _mm256_fmadd_ps(a12, b23_perm, c23);
|
||||
|
||||
ans->f32_y[0] = c01;
|
||||
ans->f32_y[1] = c23;
|
||||
}
|
||||
|
||||
DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, 512, , fma)
|
||||
{
|
||||
static const __m512i b_shift = { 0, 1, 2, 3, 5, 6, 7, 4, 10, 11, 8, 9, 15, 12, 13, 14 };
|
||||
|
||||
register __m512 a = _mm512_load_ps((float *)left);
|
||||
register __m512 b = _mm512_load_ps((float *)right);
|
||||
register __m512 c = _mm512_load_ps((float *)ans);
|
||||
|
||||
b = _mm512_permutexvar_ps(b_shift, b);
|
||||
register __m512 a_perm = _mm512_shuffle_f32x4(a, a, _MM_SHUFFLE(3, 2, 1, 0));
|
||||
register __m512 b_perm = _mm512_permute_ps(b, _FMA_SELECT(0));
|
||||
c = _mm512_fmadd_ps(a, b_perm, c);
|
||||
c = _mm512_fmadd_ps(a_perm, b_perm, c);
|
||||
|
||||
a_perm = _mm512_shuffle_f32x4(a, a, _MM_SHUFFLE(2, 1, 0, 3));
|
||||
b_perm = _mm512_permute_ps(b, _FMA_SELECT(1));
|
||||
c = _mm512_fmadd_ps(a, b_perm, c);
|
||||
c = _mm512_fmadd_ps(a_perm, b_perm, c);
|
||||
|
||||
a_perm = _mm512_shuffle_f32x4(a, a, _MM_SHUFFLE(1, 0, 3, 2));
|
||||
b_perm = _mm512_permute_ps(b, _FMA_SELECT(2));
|
||||
c = _mm512_fmadd_ps(a, b_perm, c);
|
||||
c = _mm512_fmadd_ps(a_perm, b_perm, c);
|
||||
|
||||
a_perm = _mm512_shuffle_f32x4(a, a, _MM_SHUFFLE(0, 3, 2, 1));
|
||||
b_perm = _mm512_permute_ps(b, _FMA_SELECT(3));
|
||||
c = _mm512_fmadd_ps(a, b_perm, c);
|
||||
c = _mm512_fmadd_ps(a_perm, b_perm, c);
|
||||
|
||||
_mm512_store_ps((float *)ans, c);
|
||||
}
|
||||
|
||||
// double
|
||||
|
||||
DECLARE_KER_PROC_LEFT_RIGHT_ANS(double, avx, , fma)
|
||||
{
|
||||
const __m256d a0 = _mm256_load_pd((double *)&left->f64_y[0]);
|
||||
const __m256d a1 = _mm256_load_pd((double *)&left->f64_y[1]);
|
||||
const __m256d a2 = _mm256_load_pd((double *)&left->f64_y[2]);
|
||||
const __m256d a3 = _mm256_load_pd((double *)&left->f64_y[3]);
|
||||
|
||||
__m256d b0 = _mm256_load_pd((double *)&right->f64_y[0]);
|
||||
__m256d b1 = _mm256_load_pd((double *)&right->f64_y[1]);
|
||||
__m256d b2 = _mm256_load_pd((double *)&right->f64_y[2]);
|
||||
__m256d b3 = _mm256_load_pd((double *)&right->f64_y[3]);
|
||||
|
||||
register __m256d ccol;
|
||||
|
||||
/* Column 0 */
|
||||
ccol = _mm256_load_pd((double *)&ans->f32_y[0]);
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a0, _mm256_permute4x64_pd(b0, _FMA_SELECT(0))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a1, _mm256_permute4x64_pd(b0, _FMA_SELECT(1))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a2, _mm256_permute4x64_pd(b0, _FMA_SELECT(2))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a3, _mm256_permute4x64_pd(b0, _FMA_SELECT(3))));
|
||||
ans->f64_y[0] = ccol;
|
||||
/* Column 0 */
|
||||
ccol = _mm256_load_pd((double *)&ans->f32_y[1]);
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a0, _mm256_permute4x64_pd(b1, _FMA_SELECT(0))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a1, _mm256_permute4x64_pd(b1, _FMA_SELECT(1))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a2, _mm256_permute4x64_pd(b1, _FMA_SELECT(2))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a3, _mm256_permute4x64_pd(b1, _FMA_SELECT(3))));
|
||||
ans->f64_y[0] = ccol;
|
||||
/* Column 0 */
|
||||
ccol = _mm256_load_pd((double *)&ans->f32_y[2]);
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a0, _mm256_permute4x64_pd(b2, _FMA_SELECT(0))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a1, _mm256_permute4x64_pd(b2, _FMA_SELECT(1))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a2, _mm256_permute4x64_pd(b2, _FMA_SELECT(2))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a3, _mm256_permute4x64_pd(b2, _FMA_SELECT(3))));
|
||||
ans->f64_y[0] = ccol;
|
||||
/* Column 0 */
|
||||
ccol = _mm256_load_pd((double *)&ans->f32_y[3]);
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a0, _mm256_permute4x64_pd(b3, _FMA_SELECT(0))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a1, _mm256_permute4x64_pd(b3, _FMA_SELECT(1))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a2, _mm256_permute4x64_pd(b3, _FMA_SELECT(2))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a3, _mm256_permute4x64_pd(b3, _FMA_SELECT(3))));
|
||||
ans->f64_y[0] = ccol;
|
||||
}
|
||||
|
||||
DECLARE_KER_PROC_LEFT_RIGHT_ANS(double, avx, _fma, fma)
|
||||
{
|
||||
const __m256d a0 = _mm256_load_pd((double *)&left->f64_y[0]);
|
||||
const __m256d a1 = _mm256_load_pd((double *)&left->f64_y[1]);
|
||||
const __m256d a2 = _mm256_load_pd((double *)&left->f64_y[2]);
|
||||
const __m256d a3 = _mm256_load_pd((double *)&left->f64_y[3]);
|
||||
|
||||
__m256d b0 = _mm256_load_pd((double *)&right->f64_y[0]);
|
||||
__m256d b1 = _mm256_load_pd((double *)&right->f64_y[1]);
|
||||
__m256d b2 = _mm256_load_pd((double *)&right->f64_y[2]);
|
||||
__m256d b3 = _mm256_load_pd((double *)&right->f64_y[3]);
|
||||
|
||||
register __m256d ccol;
|
||||
|
||||
/* Column 0 */
|
||||
ccol = _mm256_load_pd((double *)&ans->f32_y[0]);
|
||||
ccol = _mm256_fmadd_pd(a0, _mm256_permute4x64_pd(b0, _FMA_SELECT(0)), ccol);
|
||||
ccol = _mm256_fmadd_pd(a1, _mm256_permute4x64_pd(b0, _FMA_SELECT(1)), ccol);
|
||||
ccol = _mm256_fmadd_pd(a2, _mm256_permute4x64_pd(b0, _FMA_SELECT(2)), ccol);
|
||||
ccol = _mm256_fmadd_pd(a3, _mm256_permute4x64_pd(b0, _FMA_SELECT(3)), ccol);
|
||||
ans->f64_y[0] = ccol;
|
||||
/* Column 0 */
|
||||
ccol = _mm256_load_pd((double *)&ans->f32_y[1]);
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a0, _mm256_permute4x64_pd(b1, _FMA_SELECT(0))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a1, _mm256_permute4x64_pd(b1, _FMA_SELECT(1))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a2, _mm256_permute4x64_pd(b1, _FMA_SELECT(2))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a3, _mm256_permute4x64_pd(b1, _FMA_SELECT(3))));
|
||||
ans->f64_y[0] = ccol;
|
||||
/* Column 0 */
|
||||
ccol = _mm256_load_pd((double *)&ans->f32_y[2]);
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a0, _mm256_permute4x64_pd(b2, _FMA_SELECT(0))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a1, _mm256_permute4x64_pd(b2, _FMA_SELECT(1))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a2, _mm256_permute4x64_pd(b2, _FMA_SELECT(2))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a3, _mm256_permute4x64_pd(b2, _FMA_SELECT(3))));
|
||||
ans->f64_y[0] = ccol;
|
||||
/* Column 0 */
|
||||
ccol = _mm256_load_pd((double *)&ans->f32_y[3]);
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a0, _mm256_permute4x64_pd(b3, _FMA_SELECT(0))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a1, _mm256_permute4x64_pd(b3, _FMA_SELECT(1))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a2, _mm256_permute4x64_pd(b3, _FMA_SELECT(2))));
|
||||
ccol = _mm256_add_pd(ccol, _mm256_mul_pd(a3, _mm256_permute4x64_pd(b3, _FMA_SELECT(3))));
|
||||
ans->f64_y[0] = ccol;
|
||||
}
|
||||
|
||||
DECLARE_PNL_PROC_LEFT_RIGHT_ANS(double, sse, , fma)
|
||||
{
|
||||
for (int col = 0; col < 4; ++col) {
|
||||
|
||||
@@ -66,19 +66,13 @@ namespace StgSharp
|
||||
hlsf);
|
||||
MatrixCompute.Fill(p, 0.0f);
|
||||
|
||||
/*
|
||||
for (int i = 0; i < 10; i++)
|
||||
/**/
|
||||
for (int j = 0; j < 20; j++)
|
||||
{
|
||||
MatrixCompute.Add(n, m, n);
|
||||
for (int j = 0; j < 5; j++)
|
||||
{
|
||||
for (int k = 0; k < 5; k++) {
|
||||
Console.Write($"{n[j, k]:0.0E+00} \t");
|
||||
}
|
||||
Console.WriteLine();
|
||||
for (int k = 0; k < 10; k++) {
|
||||
Console.Write($"{m[j, k]:0.0E+00}\t");
|
||||
}
|
||||
Console.WriteLine($"{i}");
|
||||
GC.Collect();
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
/**/
|
||||
@@ -86,8 +80,8 @@ namespace StgSharp
|
||||
MatrixCompute.Mul(n, m, p);
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
for (int j = 0; j < 20; j++) {
|
||||
Console.Write($"{p[i, j]:0.0E+00} \t");
|
||||
for (int j = 0; j < 10; j++) {
|
||||
Console.Write($"{p[i, j]:0.0E+00}\t");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user