keep working on PLN facotrize

This commit is contained in:
Youmu Liu
2025-12-25 11:59:40 +08:00
parent 3b3a90a2af
commit e5539bcc6d
12 changed files with 123 additions and 76 deletions
@@ -1,4 +1,4 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="StringHashMultiplexer"
// Project: StgSharp
@@ -71,7 +71,7 @@ namespace StgSharp.Collections
{
int hash;
fixed (char* cPtr = obj.AsSpan()) {
hash = NativeIntrinsic.Intrinsic.city_hash_simplify(cPtr, obj.Length);
hash = NativeIntrinsic.Context.city_hash_simplify(cPtr, obj.Length);
}
return hash;
}
@@ -136,7 +136,7 @@ namespace StgSharp.Collections
{
int hash;
fixed (char* cPtr = obj.AsSpan()) {
hash = NativeIntrinsic.Intrinsic.city_hash_simplify(cPtr, obj.Length);
hash = NativeIntrinsic.Context.city_hash_simplify(cPtr, obj.Length);
}
return hash;
}
+1 -1
View File
@@ -49,7 +49,7 @@ namespace StgSharp.HighPerformance
{
ReadOnlySpan<char> nameSpan = Name.AsSpan();
fixed (char* cptr = nameSpan) {
return NativeIntrinsic.Intrinsic.city_hash_simplify(cptr, Name.Length);
return NativeIntrinsic.Context.city_hash_simplify(cptr, Name.Length);
}
}
@@ -1,4 +1,4 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="UnsafeCompute"
// Project: StgSharp
@@ -35,19 +35,19 @@ namespace StgSharp.HighPerformance
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe int CityHashSimplify(char* span, int length)
{
return NativeIntrinsic.Intrinsic.city_hash_simplify(span, length);
return NativeIntrinsic.Context.city_hash_simplify(span, length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe int CityHashSimplify(char* span, int begin, int length)
{
return NativeIntrinsic.Intrinsic.city_hash_simplify(span + begin, length);
return NativeIntrinsic.Context.city_hash_simplify(span + begin, length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe int IndexOfCharPair(char* source, int pairValue, int length)
{
return NativeIntrinsic.Intrinsic.index_pair(source, pairValue, length);
return NativeIntrinsic.Context.index_pair(source, pairValue, length);
}
}
@@ -48,6 +48,7 @@ namespace StgSharp.Internal.Intrinsic
public delegate* unmanaged[Cdecl]<MatrixPanel*, void> f32_clear_panel;
public delegate* unmanaged[Cdecl]<Vector4*, Vector4*, void> f32_normalize_3; //f32_normalize_3
public delegate* unmanaged[Cdecl]<void*, void*, void*, void> f32_panel_fma; //f32_panel_fma
public delegate* unmanaged[Cdecl]<void*, ulong, ulong, ulong, void> f32_pivot; //f32_panel_mul
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
@@ -41,7 +41,7 @@ namespace StgSharp.Internal
public static IntrinsicLevel IntrinsicLevel { get; set; }
internal static IntrinsicContext Intrinsic
internal static IntrinsicContext Context
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _intrinsicContext;
@@ -1,4 +1,4 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="Matrix44"
// Project: StgSharp
@@ -169,7 +169,7 @@ namespace StgSharp.Mathematics.Graphic
internal unsafe void InternalTranspose(ref Matrix44 transpose)
{
fixed (MatrixKernel<float>* source = &this.kernel, target = &transpose.kernel) {
NativeIntrinsic.Intrinsic.f32_buffer_transpose(source, target);
NativeIntrinsic.Context.f32_buffer_transpose(source, target);
}
}
@@ -177,7 +177,7 @@ namespace StgSharp.Mathematics.Graphic
public static unsafe Matrix44 operator -(Matrix44 left, Matrix44 right)
{
Matrix44 ret = new();
NativeIntrinsic.Intrinsic.f32_buffer_sub(&left, &right, &ret, 1);
NativeIntrinsic.Context.f32_buffer_sub(&left, &right, &ret, 1);
return ret;
}
@@ -219,7 +219,7 @@ namespace StgSharp.Mathematics.Graphic
public static unsafe Matrix44 operator +(Matrix44 left, Matrix44 right)
{
Matrix44 ret = new();
NativeIntrinsic.Intrinsic.f32_buffer_add(&left, &right, &ret, 1);
NativeIntrinsic.Context.f32_buffer_add(&left, &right, &ret, 1);
return ret;
}
@@ -1,4 +1,4 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="Factorial"
// Project: StgSharp
@@ -55,7 +55,7 @@ namespace StgSharp.Mathematics
return factorialResult[n];
}
if (n < 30) {
return NativeIntrinsic.Intrinsic.factorial_simd(n);
return NativeIntrinsic.Context.factorial_simd(n);
}
double
dn = n,
@@ -59,19 +59,19 @@ namespace StgSharp.Mathematics.Numeric
{
int i = (int)(c / blocksPerRow) * size;
int j = (int)(c % blocksPerRow) * size;
NativeIntrinsic.Intrinsic.f32_clear_panel((MatrixPanel*)ansPanel);
NativeIntrinsic.Context.f32_clear_panel((MatrixPanel*)ansPanel);
for (int k = 0; k < commonK; k += size)
{
NativeIntrinsic.Intrinsic
NativeIntrinsic.Context
.f32_build_panel((MatrixPanel*)leftPanel, leftBuffer, commonK,
ansHeight, k, i);
NativeIntrinsic.Intrinsic
NativeIntrinsic.Context
.f32_build_panel((MatrixPanel*)rightPanel, rightBuffer, ansWidth,
commonK, j, k);
NativeIntrinsic.Intrinsic
NativeIntrinsic.Context
.f32_panel_fma((MatrixPanel*)leftPanel, (MatrixPanel*)rightPanel, (MatrixPanel*)ansPanel);
}
NativeIntrinsic.Intrinsic
NativeIntrinsic.Context
.f32_store_panel((MatrixPanel*)ansPanel, ansBuffer, ansWidth,
ansHeight, j, i);
}
@@ -25,6 +25,7 @@
//
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
using StgSharp.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -36,11 +37,11 @@ namespace StgSharp.Mathematics.Numeric
public static partial class MatrixCompute
{
public static void FactorizePLU(
Matrix<float> matrix,
Span<float> pivot,
Matrix<float> lower,
Matrix<float> upper)
public static unsafe void FactorizePLU(
Matrix<float> matrix,
Span<int> pivot,
Matrix<float> lower,
Matrix<float> upper)
{
if (matrix.ColumnLength != matrix.RowLength) {
throw new InvalidOperationException("Matrix must be square.");
@@ -54,7 +55,7 @@ namespace StgSharp.Mathematics.Numeric
}
if (lower.RowLength != n ||
lower.ColumnLength != n ||
lower.Layout != MatrixLayout.LowerTriangle) {
lower.Layout != MatrixLayout.UpperTriangle) {
throw new ArgumentException("Lower matrix must be lower-triangular with same dimensions as input.", nameof(lower));
}
if (upper.RowLength != n ||
@@ -66,37 +67,86 @@ namespace StgSharp.Mathematics.Numeric
int size = matrix.KernelColumnLength * matrix.KernelRowLength;
if (size < 256)
{
// Naive Doolittle-style PLU without row swaps (for illustration).
for (int i = 0; i < n; i++)
{
pivot[i] = i; // identity pivot
lower[i, i] = 1.0f; // unit diagonal for L
pivot[i] = i; // identity permutation
}
for (int k = 0; k < n; k++)
// Aggressive: always call native pivot to fetch four-column candidates
ulong* pivots = stackalloc ulong[4];
for (int kBlock = 0; kBlock < n; kBlock += 4)
{
// Compute U[k, j] for j >= k
for (int j = k; j < n; j++)
NativeIntrinsic.Context
.f32_pivot(matrix.Buffer, (ulong)(kBlock >> 2),
(ulong)(matrix.KernelRowLength - (kBlock >> 2)),
(ulong)pivots);
int colsInBlock = Math.Min(4, n - kBlock);
for (int offset = 0; offset < colsInBlock; offset++)
{
float sum = 0f;
for (int s = 0; s < k; s++) {
sum += lower[k, s] * upper[s, j];
}
upper[k, j] = matrix[k, j] - sum;
}
int k = kBlock + offset;
int pivotRow = k;
float maxAbs;
// Compute L[i, k] for i > k
for (int i = k + 1; i < n; i++)
{
float sum = 0f;
for (int s = 0; s < k; s++) {
sum += lower[i, s] * upper[s, k];
int candidateRow = (int)pivots[offset];
int idx = -1;
for (int r = k; r < n; r++)
{
if (pivot[r] == candidateRow)
{
idx = r;
break;
}
}
float u = upper[k, k];
if (u == 0f) {
throw new InvalidOperationException("Zero pivot encountered in demonstration PLU.");
if (idx != -1)
{
pivotRow = idx;
maxAbs = MathF.Abs(matrix.GetElementUnsafe(pivot[idx], k));
} else
{
maxAbs = MathF.Abs(matrix.GetElementUnsafe(pivot[k], k));
for (int r = k + 1; r < n; r++)
{
float val = MathF.Abs(matrix.GetElementUnsafe(pivot[r], k));
if (val > maxAbs)
{
maxAbs = val;
pivotRow = r;
}
}
}
if (maxAbs == 0f) {
throw new InvalidOperationException("Zero pivot encountered in PLU.");
}
if (pivotRow != k) {
(pivot[k], pivot[pivotRow]) = (pivot[pivotRow], pivot[k]);
}
lower[k, k] = 1.0f; // unit diagonal for L
// Compute U[k, j] for j >= k
for (int j = k; j < n; j++)
{
float sum = 0f;
for (int s = 0; s < k; s++) {
sum += lower[k, s] * upper[s, j];
}
upper[k, j] = matrix.GetElementUnsafe(pivot[k], j) - sum;
}
// Compute L[i, k] for i > k
for (int i = k + 1; i < n; i++)
{
float sum = 0f;
for (int s = 0; s < k; s++) {
sum += lower[i, s] * upper[s, k];
}
float u = upper[k, k];
if (u == 0f) {
throw new InvalidOperationException("Zero pivot encountered in PLU.");
}
lower[i, k] = (matrix.GetElementUnsafe(pivot[i], k) - sum) / u;
}
lower[i, k] = (matrix.GetElementUnsafe(i, k) - sum) / u;
}
}
+17 -17
View File
@@ -56,7 +56,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel<float>* leftPtr = left.Buffer;
MatrixKernel<float>* rightPtr = right.Buffer;
MatrixKernel<float>* ansPtr = ans.Buffer;
NativeIntrinsic.Intrinsic.f32_buffer_add(leftPtr, rightPtr, ansPtr, count);
NativeIntrinsic.Context.f32_buffer_add(leftPtr, rightPtr, ansPtr, count);
return;
} else if (count <= 1024)
@@ -66,7 +66,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel<float>* leftPtr = left.Buffer;
MatrixKernel<float>* rightPtr = right.Buffer;
MatrixKernel<float>* ansPtr = ans.Buffer;
NativeIntrinsic.Intrinsic.f32_buffer_add(leftPtr, rightPtr, ansPtr, count);
NativeIntrinsic.Context.f32_buffer_add(leftPtr, rightPtr, ansPtr, count);
MatrixParallel.ReturnParallelResources(ref pool);
return;
@@ -79,7 +79,7 @@ namespace StgSharp.Mathematics.Numeric
package->PrimCount = ans.KernelColumnLength;
package->SecCount = ans.KernelRowLength;
package->ComputeMode = new MatrixOpMode(MatrixIndexStyle.BUFFER_INDEX, MatrixOperationParam.LEFT_RIGHT_ANS_PARAM);
package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_buffer_add;
package->ComputeHandle = (IntPtr)NativeIntrinsic.Context.f32_buffer_add;
MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package);
MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep);
@@ -94,12 +94,12 @@ namespace StgSharp.Mathematics.Numeric
scalar->Data<float>(0) = value;
if (count <= 256)
{
NativeIntrinsic.Intrinsic.f32_buffer_fill(ans.Buffer, scalar, count);
NativeIntrinsic.Context.f32_buffer_fill(ans.Buffer, scalar, count);
return;
} else if (count <= 1024)
{
MatrixParallelThread[] pool = MatrixParallel.LeadParallel(1);
NativeIntrinsic.Intrinsic.f32_buffer_fill(ans.Buffer, scalar, count);
NativeIntrinsic.Context.f32_buffer_fill(ans.Buffer, scalar, count);
MatrixParallel.ReturnParallelResources(ref pool);
return;
}
@@ -109,7 +109,7 @@ namespace StgSharp.Mathematics.Numeric
package->PrimCount = ans.KernelColumnLength;
package->SecCount = ans.KernelRowLength;
package->ComputeMode = new MatrixOpMode(MatrixIndexStyle.BUFFER_INDEX, MatrixOperationParam.ANS_SCALAR_PARAM);
package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_buffer_fill;
package->ComputeHandle = (IntPtr)NativeIntrinsic.Context.f32_buffer_fill;
package->Scalar = scalar;
MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package);
MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep);
@@ -142,27 +142,27 @@ namespace StgSharp.Mathematics.Numeric
{
for (int j = 0; j < ans.KernelColumnLength; j += size)
{
NativeIntrinsic.Intrinsic.f32_clear_panel((MatrixPanel*)ansPanel);
NativeIntrinsic.Context.f32_clear_panel((MatrixPanel*)ansPanel);
// Console.WriteLine($"{i}{j}");
for (int k = 0; k < left.KernelColumnLength; k += size)
{
NativeIntrinsic.Intrinsic
NativeIntrinsic.Context
.f32_build_panel((MatrixPanel*)leftPanel,
(MatrixKernel*)left.Buffer,
left.KernelColumnLength,
left.KernelRowLength, i, k);
NativeIntrinsic.Intrinsic
NativeIntrinsic.Context
.f32_build_panel((MatrixPanel*)rightPanel,
(MatrixKernel*)right.Buffer,
right.KernelColumnLength,
right.KernelRowLength, k, j);
NativeIntrinsic.Intrinsic
NativeIntrinsic.Context
.f32_panel_fma((MatrixPanel*)leftPanel,
(MatrixPanel*)rightPanel,
(MatrixPanel*)ansPanel);
}
NativeIntrinsic.Intrinsic
NativeIntrinsic.Context
.f32_store_panel((MatrixPanel*)ansPanel,
(MatrixKernel*)ans.Buffer,
ans.KernelColumnLength, ans.KernelRowLength,
@@ -211,7 +211,7 @@ namespace StgSharp.Mathematics.Numeric
{
MatrixKernel<float>* leftPtr = left.Buffer;
MatrixKernel<float>* ansPtr = ans.Buffer;
NativeIntrinsic.Intrinsic.f32_buffer_scalar_mul(leftPtr, ansPtr, scalar, count);
NativeIntrinsic.Context.f32_buffer_scalar_mul(leftPtr, ansPtr, scalar, count);
return;
} else if (count <= 1024)
@@ -220,7 +220,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel<float>* leftPtr = left.Buffer;
MatrixKernel<float>* ansPtr = ans.Buffer;
NativeIntrinsic.Intrinsic.f32_buffer_scalar_mul(leftPtr, ansPtr, scalar, count);
NativeIntrinsic.Context.f32_buffer_scalar_mul(leftPtr, ansPtr, scalar, count);
MatrixParallel.ReturnParallelResources(ref pool);
return;
@@ -233,7 +233,7 @@ namespace StgSharp.Mathematics.Numeric
package->SecCount = left.KernelRowLength;
package->Scalar = scalar;
package->ComputeMode = new MatrixOpMode(MatrixIndexStyle.BUFFER_INDEX, MatrixOperationParam.RIGHT_ANS_SCALAR_PARAM);
package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_buffer_scalar_mul;
package->ComputeHandle = (IntPtr)NativeIntrinsic.Context.f32_buffer_scalar_mul;
MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package);
MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep);
@@ -261,7 +261,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel<float>* leftPtr = left.Buffer;
MatrixKernel<float>* rightPtr = right.Buffer;
MatrixKernel<float>* ansPtr = ans.Buffer;
NativeIntrinsic.Intrinsic.f32_buffer_sub(leftPtr, rightPtr, ansPtr, count);
NativeIntrinsic.Context.f32_buffer_sub(leftPtr, rightPtr, ansPtr, count);
return;
} else if (count <= 1024)
@@ -271,7 +271,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel<float>* leftPtr = left.Buffer;
MatrixKernel<float>* rightPtr = right.Buffer;
MatrixKernel<float>* ansPtr = ans.Buffer;
NativeIntrinsic.Intrinsic.f32_buffer_sub(leftPtr, rightPtr, ansPtr, count);
NativeIntrinsic.Context.f32_buffer_sub(leftPtr, rightPtr, ansPtr, count);
MatrixParallel.ReturnParallelResources(ref pool);
return;
@@ -284,7 +284,7 @@ namespace StgSharp.Mathematics.Numeric
package->PrimCount = left.KernelColumnLength;
package->SecCount = left.KernelRowLength;
package->ComputeMode = new MatrixOpMode(MatrixIndexStyle.BUFFER_INDEX, MatrixOperationParam.LEFT_RIGHT_ANS_PARAM);
package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_buffer_sub;
package->ComputeHandle = (IntPtr)NativeIntrinsic.Context.f32_buffer_sub;
MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package);
MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep);
+5 -9
View File
@@ -196,15 +196,10 @@ typedef void(SN_DECL *KER_PROC_LAS)(mat_kernel *matrix, mat_kernel *ans, scalar_
#pragma region special matrix kernel operation
typedef void(SN_DECL *POVITPROC)(mat_kernel const *source, mat_kernel *ans);
#define MAT_POVIT_PROC(T_type, T_arch) povit_##T_type##_##T_arch
#define DECLARE_MAT_POVIT_PROC(T_type, T_arch) \
INTERNAL void SN_DECL MAT_POVIT_PROC(T_type, T_arch)(MAT_KERNEL(T_type) const *source, \
size_t col_begin, size_t col_length, \
size_t *restrict ans)
DECLARE_MAT_POVIT_PROC(float, sse);
DECLARE_MAT_POVIT_PROC(float, avx);
DECLARE_MAT_POVIT_PROC(float, 512);
typedef void(SN_DECL *PIVOTPROC)(mat_kernel const *source, size_t col_begin, size_t col_length,
size_t *restrict ans);
INTERNAL void SN_DECL pivot_float(MAT_KERNEL(float) const *source, size_t col_begin,
size_t col_length, size_t *restrict ans);
#pragma endregion
@@ -292,6 +287,7 @@ typedef struct sn_intrinsic {
PANEL_PROC f32_clear_panel;
VECTORNORMALIZEPROC f32_normalize_3;
PNL_PROC_LRA f32_panel_fma;
PIVOTPROC f32_pivot;
PANEL_PROC f32_store_panel;
FACTORIALROC factorial_simd;
INDEX_PAIR index_pair;
+2 -2
View File
@@ -2,8 +2,8 @@
// Hybrid implementation: SIMD for Abs, Scalar for Max
// Assumes Column-Major layout for both MAT_KERNEL content and Kernel sequence
static void povit_float(MAT_KERNEL(float) const *source, size_t col_begin,
size_t col_length, size_t *restrict ans)
static void pivot_float(MAT_KERNEL(float) const *source, size_t col_begin, size_t col_length,
size_t *restrict ans)
{
float max_v[4] = { -1.0f, -1.0f, -1.0f, -1.0f };