From 0cafe9fd4d9afc156a5bdff4623f7e3a530393e3 Mon Sep 17 00:00:00 2001 From: Youmu Liu <105042599+Nitload-NSI@users.noreply.github.com> Date: Wed, 24 Sep 2025 20:38:15 +0800 Subject: [PATCH] mpl going on good process --- ReadMe.md | 31 ++------ .../Collections/NotEnumerableList.cs | 70 +++++++++++++++++++ .../HighPerformance/MatrixKernel.cs | 16 +---- .../Mathematics/Linear/Matrix.GC.cs | 4 +- .../Mathematics/Linear/Matrix.HLSF.cs | 4 +- .../Linear/MatrixParallel.Publish.cs | 52 +++++++------- .../Linear/MatrixParallel.TaskFactory.cs | 16 ++--- .../Mathematics/Linear/MatrixParallel.cs | 38 ++++++++-- StgSharp.Native/StgSharp.Native.vcxproj | 2 + StgSharp.Native/sn-head/sn_internal.h | 4 +- StgSharp.Native/sn-head/sn_intrinsic.h | 2 +- StgSharp.Native/sn-head/sn_matkernel.h | 17 ++++- StgSharp.Native/sn-src/k_fma.c | 5 +- StgSharp.Native/sn-src/str_string.c | 7 +- StgSharp.Native/sn-src/vector.c | 15 ++-- 15 files changed, 179 insertions(+), 104 deletions(-) create mode 100644 StgSharp.Common/Collections/NotEnumerableList.cs diff --git a/ReadMe.md b/ReadMe.md index 2b269877..ce827fa4 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -79,19 +79,6 @@ Terminal-based user interface: - **EXPRESS Language**: Domain-specific language compilation - **Pipeline Processing**: Efficient data transformation workflows -## Documentation - -### Technical Documentation -- [HLSF Allocator](StgSharp.Common/HighPerformance/Memory/InroductionToHLSF.md) - High-performance memory allocator documentation -- [Native Library Naming](StgSharp.Native/naming.md) - Native library file naming conventions - -### Module-Specific Documentation -- **Mathematics**: Linear algebra, matrix operations, and mathematical utilities -- **Graphics**: OpenGL bindings, rendering, and graphics pipeline -- **High Performance**: SIMD operations, parallel computing, and memory management -- **Scripting**: General syntax analysis framework with EXPRESS language support -- **Modeling**: Geometric model loading and interpretation with STEP format support - ## Requirements - .NET 8.0 or later @@ -180,22 +167,12 @@ var handle = allocator.Alloc(1024); allocator.Free(handle); ``` -## Architecture -StgSharp follows a modular architecture where each component can be used independently or in combination: +## Documentation -- **Core Layer**: Fundamental data structures and utilities -- **Graphics Layer**: Rendering and graphics APIs -- **Performance Layer**: High-performance computing and optimization -- **Application Layer**: Game engine and application frameworks -- **Data Layer**: File processing and data modeling - -## Performance Characteristics - -- **Matrix Operations**: Optimized for large-scale computations -- **Memory Allocation**: O(1) allocation and deallocation with HLSF -- **Parallel Processing**: Multi-threaded execution with intelligent scheduling -- **SIMD Utilization**: Hardware-accelerated vector operations +### Technical Documentation +- [HLSF Allocator](StgSharp.Common/HighPerformance/Memory/InroductionToHLSF.md) - High-performance memory allocator documentation +- [Native Library Naming](StgSharp.Native/naming.md) - Native library file naming conventions ## Contributing diff --git a/StgSharp.Common/Collections/NotEnumerableList.cs b/StgSharp.Common/Collections/NotEnumerableList.cs new file mode 100644 index 00000000..7efc6e7a --- /dev/null +++ b/StgSharp.Common/Collections/NotEnumerableList.cs @@ -0,0 +1,70 @@ +using System; +using System.Runtime.CompilerServices; + +namespace StgSharp.Collections +{ + public sealed class NotEnumerableList(int capacity = 4) + { + + private T[] _items = new T[capacity]; + private int _size = 0; + + public T this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => (uint)index >= (uint)_size ? throw new ArgumentOutOfRangeException(nameof(index)) : _items[index]; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set + { + if ((uint)index >= (uint)_size) { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + _items[index] = value; + } + } + + public int Count => _size; + + public int Capacity => _items.Length; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Add(T item) + { + if (_size == _items.Length) { + EnsureCapacity(_size + 1); + } + + _items[_size++] = item; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Span AsSpan() + { + return new Span(_items, 0, _size); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void FastClear() + { + // 只重置size,不清理数组内容 + _size = 0; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void EnsureCapacity(int min) + { + if (_items.Length < min) + { + int newCapacity = _items.Length == 0 ? 4 : _items.Length * 2; + if (newCapacity < min) { + newCapacity = min; + } + + Array.Resize(ref _items, newCapacity); + } + } + + } +} + diff --git a/StgSharp.Common/HighPerformance/MatrixKernel.cs b/StgSharp.Common/HighPerformance/MatrixKernel.cs index 252c0970..0d16bb60 100644 --- a/StgSharp.Common/HighPerformance/MatrixKernel.cs +++ b/StgSharp.Common/HighPerformance/MatrixKernel.cs @@ -42,25 +42,11 @@ using System.Threading.Tasks; namespace StgSharp.HighPerformance { [StructLayout(LayoutKind.Sequential)] + [InlineArray(16)] public unsafe struct MatrixKernel where T: unmanaged, INumber { private T c0r0; - private T c0r1; - private T c0r2; - private T c0r3; - private T c1r0; - private T c1r1; - private T c1r2; - private T c1r3; - private T c2r0; - private T c2r1; - private T c2r2; - private T c2r3; - private T c3r0; - private T c3r1; - private T c3r2; - private T c3r3; public MatrixKernel() { diff --git a/StgSharp.Common/Mathematics/Linear/Matrix.GC.cs b/StgSharp.Common/Mathematics/Linear/Matrix.GC.cs index 7e5efd7c..c23ffb8e 100644 --- a/StgSharp.Common/Mathematics/Linear/Matrix.GC.cs +++ b/StgSharp.Common/Mathematics/Linear/Matrix.GC.cs @@ -61,7 +61,7 @@ namespace StgSharp.Mathematics int kernelColumn = column / 4, c = column % 4; int kernelRow = row / t_count, r = row % t_count; ref MatrixKernel kernel = ref _buffer[kernelColumn + KernelColumnLength * kernelRow]; - return ref kernel.UnsafeIndex(c, r); + return ref kernel[c, r]; } } @@ -90,7 +90,7 @@ namespace StgSharp.Mathematics int kernelColumn = column / 4, c = column % 4; int kernelRow = row / t_count, r = row % t_count; ref MatrixKernel kernel = ref _buffer[kernelColumn + (KernelColumnLength * kernelRow)]; - return ref kernel.UnsafeIndex(c, r); + return ref kernel[c, r]; } #region enumeration diff --git a/StgSharp.Common/Mathematics/Linear/Matrix.HLSF.cs b/StgSharp.Common/Mathematics/Linear/Matrix.HLSF.cs index 5901bbf0..07b1683f 100644 --- a/StgSharp.Common/Mathematics/Linear/Matrix.HLSF.cs +++ b/StgSharp.Common/Mathematics/Linear/Matrix.HLSF.cs @@ -65,7 +65,7 @@ namespace StgSharp.Mathematics int kernelColumn = column / 4, c = column % 4; int kernelRow = row / t_count, r = row % t_count; ref MatrixKernel kernel = ref k_buffer[(kernelColumn * kernelColumn) + kernelRow]; - return ref kernel.UnsafeIndex(c, r); + return ref kernel[c, r]; } } @@ -94,7 +94,7 @@ namespace StgSharp.Mathematics int kernelColumn = column / 4, c = column % 4; int kernelRow = row / t_count, r = row % t_count; ref MatrixKernel kernel = ref k_buffer[(kernelColumn * kernelColumn) + kernelRow]; - return ref kernel.UnsafeIndex(c, r); + return ref kernel[c, r]; } ~HlsfMatrix() diff --git a/StgSharp.Common/Mathematics/Linear/MatrixParallel.Publish.cs b/StgSharp.Common/Mathematics/Linear/MatrixParallel.Publish.cs index 49d50125..952bec45 100644 --- a/StgSharp.Common/Mathematics/Linear/MatrixParallel.Publish.cs +++ b/StgSharp.Common/Mathematics/Linear/MatrixParallel.Publish.cs @@ -51,31 +51,35 @@ namespace StgSharp.Mathematics { int length = _threads.Length, columnCount = left.PrimSize, - rowCount = right.PrimSize, - cAverage = left.PrimSize / length, cRemain = left.PrimSize % length, - rAverage = right.PrimSize / length, rRemain = right.PrimSize % length; + rowCount = right.PrimSize; + (int c3, int c4) = FastDecompose(columnCount); + + MatrixParallelTaskPackage* package = MatrixParallelFactory.CreateBaseTask(); + package->Left = left.Source; + package->Right = right.Source; + package->Result = ans.Source; + package->LeftPrimOffset = left.PrimOffset; + package->RightPrimOffset = right.PrimOffset; + package->ResultPrimOffset = ans.PrimOffset; + package->LeftPrimStride = left.PrimStride; + package->RightPrimStride = right.PrimStride; + package->ResultPrimStride = ans.PrimStride; + package->LeftSecOffset = left.SecondaryOffset; + package->RightSecOffset = right.SecondaryOffset; + package->ResultSecOffset = ans.SecondaryOffset; + package->LeftSecStride = left.SecondaryStride; + package->RightSecStride = right.SecondaryStride; + package->ResultSecStride = ans.SecondaryStride; + package->PrimCount = left.PrimSize; + package->SecCount = left.SecondarySize; + package->ComputeHandle = (nint)Operation; + package->ElementSize = sizeof(T); + package->ComputeMode = 3; + + int + small_4 = c4 / length, + larget_4 - MatrixParallelTaskPackage package = new() - { - Left = left.Source, - Right = right.Source, - Result = ans.Source, - LeftPrimOffset = left.PrimOffset, - RightPrimOffset = right.PrimOffset, - ResultPrimOffset = ans.PrimOffset, - LeftPrimStride = left.PrimStride, - RightPrimStride = right.PrimStride, - ResultPrimStride = ans.PrimStride, - LeftSecOffset = left.SecondaryOffset, - RightSecOffset = right.SecondaryOffset, - ResultSecOffset = ans.SecondaryOffset, - LeftSecStride = left.SecondaryStride, - RightSecStride = right.SecondaryStride, - ResultSecStride = ans.SecondaryStride, - PrimCount = left.PrimSize, - SecCount = left.SecondarySize, - ComputeHandle = (nint)Operation - }; } } diff --git a/StgSharp.Common/Mathematics/Linear/MatrixParallel.TaskFactory.cs b/StgSharp.Common/Mathematics/Linear/MatrixParallel.TaskFactory.cs index 7bd20e68..9f361357 100644 --- a/StgSharp.Common/Mathematics/Linear/MatrixParallel.TaskFactory.cs +++ b/StgSharp.Common/Mathematics/Linear/MatrixParallel.TaskFactory.cs @@ -58,7 +58,7 @@ namespace StgSharp.Mathematics private static SlabAllocator _scalarAllocator ; - private static SlabAllocator _wrapAllocator ; + private static SlabAllocator _wrapAllocator; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static MatrixParallelTaskPackage* CreateBaseTask() where T: unmanaged, INumber @@ -76,17 +76,13 @@ namespace StgSharp.Mathematics return p; } - public static MatrixParallelTaskPackage* FromTaskWrap(MatrixParallelTaskPackage* source, int offset) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe MatrixParallelTaskPackage* FromExistPackage(MatrixParallelTaskPackage* exist) where T: unmanaged, INumber { - MatrixParallelTaskPackage* p = (MatrixParallelTaskPackage*)_wrapAllocator.Allocate(); - /* - *p = *source; - p->Left += offset * p->LeftStride; - p->Right += offset * p->RightStride; - p->Result += offset * p->ResultStride; - /**/ - return p; + MatrixParallelTaskPackage* ptr = (MatrixParallelTaskPackage*)_wrapAllocator.Allocate(); + MatrixParallelTaskPackage.Copy(exist, ptr); + return ptr; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/StgSharp.Common/Mathematics/Linear/MatrixParallel.cs b/StgSharp.Common/Mathematics/Linear/MatrixParallel.cs index ea22584d..a1721bf0 100644 --- a/StgSharp.Common/Mathematics/Linear/MatrixParallel.cs +++ b/StgSharp.Common/Mathematics/Linear/MatrixParallel.cs @@ -69,15 +69,33 @@ namespace StgSharp.Mathematics private static Thread[] _threads; private static MatrixParallelWrap[] _wraps; - private static readonly (int a, int b)[] LookupTable = [ (1, 1), (0, 2), (3, 0), (2, 1), (1, 2), (0, 3), (3, 1), (2, 2), (1, 3), (0, 4), (3, 2), (2, 3), (1, 4), (0, 5), ]; - private static volatile int RemainThreadCount = 0; + private static readonly (int a, int b)[] LookupTable = [ + (1, 1), + (0, 2), + (3, 0), + (2, 1), + (1, 2), + (0, 3), + (3, 1), + (2, 2), + (1, 3), + (0, 4), + (3, 2), + (2, 3), + (1, 4), + (0, 5), + ]; + private static bool _meaningful; + private static int LargeWrapCount; + private static volatile int RemainThreadCount = 0; + private static int SmallWrapCount; private static readonly object _lock = new(); private static ThreadPriority _AfterWork = ThreadPriority.Lowest; public static bool SupportParallel { get; } = Environment.ProcessorCount > 6; - public static bool IsParallelMeaningful { get; } = Environment.ProcessorCount > 6 && IsInitialized; + public static bool IsParallelMeaningful => Environment.ProcessorCount > 6 && IsInitialized; public static MatrixParallelWrap.Handle LeaderHandle { get; private/**/ set; } @@ -91,7 +109,7 @@ namespace StgSharp.Mathematics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static (int a, int b) FastDecompose(int c) + public static (int count_3, int count_4) FastDecompose(int c) { if (c < 7) { return (0, 0); @@ -111,15 +129,25 @@ namespace StgSharp.Mathematics return; } MatrixParallelFactory.Init(); + if (!SupportParallel) + { + IsInitialized = true; + return; + } int count = Environment.ProcessorCount - 4; count = count == 5 ? 4 : count; _threads = new Thread[count]; if (count < 6) { + count = count == 3 ? 3 : 4; _wraps = [ new MatrixParallelWrap(0, count, true) ]; + (LargeWrapCount, SmallWrapCount) = count == 3 ? (1,0) : (0,1); } else if (count == 6) { - _wraps = [ new MatrixParallelWrap(0, 3, true), new MatrixParallelWrap(3, 3, false) ]; + _wraps = [ + new MatrixParallelWrap(0, 3, true), + new MatrixParallelWrap(3, 3, false) + ]; } else { (int _3wrap, int _4wrap) = FastDecompose(count); diff --git a/StgSharp.Native/StgSharp.Native.vcxproj b/StgSharp.Native/StgSharp.Native.vcxproj index 45bad145..7cd17ce7 100644 --- a/StgSharp.Native/StgSharp.Native.vcxproj +++ b/StgSharp.Native/StgSharp.Native.vcxproj @@ -88,6 +88,7 @@ Console true + opengl32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) @@ -105,6 +106,7 @@ true true true + opengl32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) diff --git a/StgSharp.Native/sn-head/sn_internal.h b/StgSharp.Native/sn-head/sn_internal.h index 60f86caa..1d0077fb 100644 --- a/StgSharp.Native/sn-head/sn_internal.h +++ b/StgSharp.Native/sn-head/sn_internal.h @@ -2,11 +2,11 @@ #pragma once #endif -#include - #ifndef SN_INTERNAL #define SN_INTERNAL +#include + #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS 1 #define WIN32_LEAN_AND_MEAN diff --git a/StgSharp.Native/sn-head/sn_intrinsic.h b/StgSharp.Native/sn-head/sn_intrinsic.h index 5071eac5..57dd3ca5 100644 --- a/StgSharp.Native/sn-head/sn_intrinsic.h +++ b/StgSharp.Native/sn-head/sn_intrinsic.h @@ -59,7 +59,7 @@ typedef uint64_t(SN_DECL *FACTORIALROC)(int n); #pragma region matix function -INTERNAL void normalize(__m128 *source, __m128 *target); +INTERNAL void f32_normalize(VEC(float) * source, VEC(float) * target); INTERNAL void SN_DECL f32_add_sse(MAT_KERNEL(float) const *left, MAT_KERNEL(float) const *right, MAT_KERNEL(float) *restrict ans); diff --git a/StgSharp.Native/sn-head/sn_matkernel.h b/StgSharp.Native/sn-head/sn_matkernel.h index 0bdafa7d..15498d0f 100644 --- a/StgSharp.Native/sn-head/sn_matkernel.h +++ b/StgSharp.Native/sn-head/sn_matkernel.h @@ -9,11 +9,26 @@ #define ZMMCOUNT(T) sizeof(T) / 4 #define MAT_KERNEL(T) \ - union { \ + union mat_kernel_##T##{ \ __m128 xmm[XMMCOUNT(T)]; \ __m256 ymm[YMMCOUNT(T)]; \ __m512 zmm[ZMMCOUNT(T)]; \ T m[4][4]; \ } +#define VEC(T) \ + union vec_##T##{ \ + __m128 xmm[XMMCOUNT(T) / 4]; \ + __m256 ymm[YMMCOUNT(T) / 4]; \ + __m512 zmm[ZMMCOUNT(T) / 4]; \ + T v[4]; \ + } + +/* +#undef ELEMENTSIZE +#undef XMMCOUNT +#undef YMMCOUNT +#undef ZMMCOUNT +/**/ + #endif diff --git a/StgSharp.Native/sn-src/k_fma.c b/StgSharp.Native/sn-src/k_fma.c index 96a67e0f..efed0682 100644 --- a/StgSharp.Native/sn-src/k_fma.c +++ b/StgSharp.Native/sn-src/k_fma.c @@ -1,8 +1,9 @@ #include "sn_intrinsic.h" -// ans = left * right(T) + ans +// ans = left * right + ans INTERNAL void SN_DECL f32_fma_sse(MAT_KERNEL(float) const *restrict left, - MAT_KERNEL(float) const *restrict right, MAT_KERNEL(float) *restrict ans) + MAT_KERNEL(float) const *restrict right, + MAT_KERNEL(float) *restrict ans) { register __m128 source0 = _mm_load_ps(&left->xmm[0]); register __m128 source1 = _mm_load_ps(&left->xmm[1]); diff --git a/StgSharp.Native/sn-src/str_string.c b/StgSharp.Native/sn-src/str_string.c index d3995444..37f208e7 100644 --- a/StgSharp.Native/sn-src/str_string.c +++ b/StgSharp.Native/sn-src/str_string.c @@ -3,12 +3,7 @@ INTERNAL int SN_DECL index_pair_sse(short const *str, uint32_t target, int length) { int index = 0, result = 0, size = length, end = size - 8; - __m128i s = { - target, - target, - target, - target, - }; + __m128i s = _mm_set1_epi32(target); __m128i vec, com; while (index < end) { diff --git a/StgSharp.Native/sn-src/vector.c b/StgSharp.Native/sn-src/vector.c index 65744302..3a25a09b 100644 --- a/StgSharp.Native/sn-src/vector.c +++ b/StgSharp.Native/sn-src/vector.c @@ -1,24 +1,25 @@ -#include "StgSharpNative.h" +#include "sn_intrinsic.h" #include "sn_internal.h" -SN_API void SN_DECL normalize(__m128 *restrict source, __m128 *restrict target) +SN_API void SN_DECL normalize(VEC(float) *restrict source, VEC(float) *restrict target) { - __m128 a_length_sq = _mm_mul_ps(*source, *source); + register __m128 s = _mm_load_ps(&source->xmm); + register __m128 a_length_sq = _mm_mul_ps(s, s); a_length_sq = _mm_add_ps(a_length_sq, _mm_shuffle_ps(a_length_sq, a_length_sq, _MM_SHUFFLE(2, 3, 0, 1))); a_length_sq = _mm_add_ss(a_length_sq, _mm_shuffle_ps(a_length_sq, a_length_sq, _MM_SHUFFLE(0, 0, 3, 2))); __m128 a_inv_length = _mm_rsqrt_ps(a_length_sq); - *source = _mm_mul_ps(*source, a_inv_length); + s = _mm_mul_ps(s, a_inv_length); - __m128 dot_product = _mm_mul_ps(*target, *source); + __m128 dot_product = _mm_mul_ps(target->xmm[0], s); dot_product = _mm_add_ps(dot_product, _mm_shuffle_ps(dot_product, dot_product, _MM_SHUFFLE(2, 3, 0, 1))); dot_product = _mm_add_ss(dot_product, _mm_shuffle_ps(dot_product, dot_product, _MM_SHUFFLE(0, 0, 3, 2))); - __m128 b_orthogonal = _mm_sub_ps(*target, _mm_mul_ps(*source, dot_product)); + __m128 b_orthogonal = _mm_sub_ps(target->xmm[0], _mm_mul_ps(s, dot_product)); __m128 b_length_sq = _mm_mul_ps(b_orthogonal, b_orthogonal); b_length_sq = _mm_add_ps(b_length_sq, @@ -27,5 +28,5 @@ SN_API void SN_DECL normalize(__m128 *restrict source, __m128 *restrict target) _mm_shuffle_ps(b_length_sq, b_length_sq, _MM_SHUFFLE(0, 0, 3, 2))); __m128 b_inv_length = _mm_rsqrt_ps(b_length_sq); - *target = _mm_mul_ps(b_orthogonal, b_inv_length); + target->xmm[0] = _mm_mul_ps(b_orthogonal, b_inv_length); }