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
@@ -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);