mpl going on good process

This commit is contained in:
Youmu Liu
2025-09-24 20:38:15 +08:00
parent 8abc82ae08
commit 0cafe9fd4d
15 changed files with 179 additions and 104 deletions
+4 -27
View File
@@ -79,19 +79,6 @@ Terminal-based user interface:
- **EXPRESS Language**: Domain-specific language compilation - **EXPRESS Language**: Domain-specific language compilation
- **Pipeline Processing**: Efficient data transformation workflows - **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 ## Requirements
- .NET 8.0 or later - .NET 8.0 or later
@@ -180,22 +167,12 @@ var handle = allocator.Alloc(1024);
allocator.Free(handle); 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 ### Technical Documentation
- **Graphics Layer**: Rendering and graphics APIs - [HLSF Allocator](StgSharp.Common/HighPerformance/Memory/InroductionToHLSF.md) - High-performance memory allocator documentation
- **Performance Layer**: High-performance computing and optimization - [Native Library Naming](StgSharp.Native/naming.md) - Native library file naming conventions
- **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
## Contributing ## Contributing
@@ -0,0 +1,70 @@
using System;
using System.Runtime.CompilerServices;
namespace StgSharp.Collections
{
public sealed class NotEnumerableList<T>(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<T> AsSpan()
{
return new Span<T>(_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);
}
}
}
}
@@ -42,25 +42,11 @@ using System.Threading.Tasks;
namespace StgSharp.HighPerformance namespace StgSharp.HighPerformance
{ {
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
[InlineArray(16)]
public unsafe struct MatrixKernel<T> where T: unmanaged, INumber<T> public unsafe struct MatrixKernel<T> where T: unmanaged, INumber<T>
{ {
private T c0r0; 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() public MatrixKernel()
{ {
@@ -61,7 +61,7 @@ namespace StgSharp.Mathematics
int kernelColumn = column / 4, c = column % 4; int kernelColumn = column / 4, c = column % 4;
int kernelRow = row / t_count, r = row % t_count; int kernelRow = row / t_count, r = row % t_count;
ref MatrixKernel<T> kernel = ref _buffer[kernelColumn + KernelColumnLength * kernelRow]; ref MatrixKernel<T> 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 kernelColumn = column / 4, c = column % 4;
int kernelRow = row / t_count, r = row % t_count; int kernelRow = row / t_count, r = row % t_count;
ref MatrixKernel<T> kernel = ref _buffer[kernelColumn + (KernelColumnLength * kernelRow)]; ref MatrixKernel<T> kernel = ref _buffer[kernelColumn + (KernelColumnLength * kernelRow)];
return ref kernel.UnsafeIndex(c, r); return ref kernel[c, r];
} }
#region enumeration #region enumeration
@@ -65,7 +65,7 @@ namespace StgSharp.Mathematics
int kernelColumn = column / 4, c = column % 4; int kernelColumn = column / 4, c = column % 4;
int kernelRow = row / t_count, r = row % t_count; int kernelRow = row / t_count, r = row % t_count;
ref MatrixKernel<T> kernel = ref k_buffer[(kernelColumn * kernelColumn) + kernelRow]; ref MatrixKernel<T> 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 kernelColumn = column / 4, c = column % 4;
int kernelRow = row / t_count, r = row % t_count; int kernelRow = row / t_count, r = row % t_count;
ref MatrixKernel<T> kernel = ref k_buffer[(kernelColumn * kernelColumn) + kernelRow]; ref MatrixKernel<T> kernel = ref k_buffer[(kernelColumn * kernelColumn) + kernelRow];
return ref kernel.UnsafeIndex(c, r); return ref kernel[c, r];
} }
~HlsfMatrix() ~HlsfMatrix()
@@ -51,31 +51,35 @@ namespace StgSharp.Mathematics
{ {
int length = _threads.Length, int length = _threads.Length,
columnCount = left.PrimSize, columnCount = left.PrimSize,
rowCount = right.PrimSize, rowCount = right.PrimSize;
cAverage = left.PrimSize / length, cRemain = left.PrimSize % length, (int c3, int c4) = FastDecompose(columnCount);
rAverage = right.PrimSize / length, rRemain = right.PrimSize % length;
MatrixParallelTaskPackage<T>* package = MatrixParallelFactory.CreateBaseTask<T>();
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<T> 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
};
} }
} }
@@ -58,7 +58,7 @@ namespace StgSharp.Mathematics
private static SlabAllocator<ScalarPacket> _scalarAllocator ; private static SlabAllocator<ScalarPacket> _scalarAllocator ;
private static SlabAllocator<MatrixParallelTaskPackageNonGeneric> _wrapAllocator ; private static SlabAllocator<MatrixParallelTaskPackageNonGeneric> _wrapAllocator;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static MatrixParallelTaskPackage<T>* CreateBaseTask<T>() where T: unmanaged, INumber<T> public static MatrixParallelTaskPackage<T>* CreateBaseTask<T>() where T: unmanaged, INumber<T>
@@ -76,17 +76,13 @@ namespace StgSharp.Mathematics
return p; return p;
} }
public static MatrixParallelTaskPackage<T>* FromTaskWrap<T>(MatrixParallelTaskPackage<T>* source, int offset) [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe MatrixParallelTaskPackage<T>* FromExistPackage<T>(MatrixParallelTaskPackage<T>* exist)
where T: unmanaged, INumber<T> where T: unmanaged, INumber<T>
{ {
MatrixParallelTaskPackage<T>* p = (MatrixParallelTaskPackage<T>*)_wrapAllocator.Allocate(); MatrixParallelTaskPackage<T>* ptr = (MatrixParallelTaskPackage<T>*)_wrapAllocator.Allocate();
/* MatrixParallelTaskPackage<T>.Copy(exist, ptr);
*p = *source; return ptr;
p->Left += offset * p->LeftStride;
p->Right += offset * p->RightStride;
p->Result += offset * p->ResultStride;
/**/
return p;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -69,15 +69,33 @@ namespace StgSharp.Mathematics
private static Thread[] _threads; private static Thread[] _threads;
private static MatrixParallelWrap[] _wraps; 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 readonly (int a, int b)[] LookupTable = [
private static volatile int RemainThreadCount = 0; (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 readonly object _lock = new();
private static ThreadPriority _AfterWork = ThreadPriority.Lowest; private static ThreadPriority _AfterWork = ThreadPriority.Lowest;
public static bool SupportParallel { get; } = Environment.ProcessorCount > 6; 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; } public static MatrixParallelWrap.Handle LeaderHandle { get; private/**/ set; }
@@ -91,7 +109,7 @@ namespace StgSharp.Mathematics
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [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) { if (c < 7) {
return (0, 0); return (0, 0);
@@ -111,15 +129,25 @@ namespace StgSharp.Mathematics
return; return;
} }
MatrixParallelFactory.Init(); MatrixParallelFactory.Init();
if (!SupportParallel)
{
IsInitialized = true;
return;
}
int count = Environment.ProcessorCount - 4; int count = Environment.ProcessorCount - 4;
count = count == 5 ? 4 : count; count = count == 5 ? 4 : count;
_threads = new Thread[count]; _threads = new Thread[count];
if (count < 6) if (count < 6)
{ {
count = count == 3 ? 3 : 4;
_wraps = [ new MatrixParallelWrap(0, count, true) ]; _wraps = [ new MatrixParallelWrap(0, count, true) ];
(LargeWrapCount, SmallWrapCount) = count == 3 ? (1,0) : (0,1);
} else if (count == 6) } 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 } else
{ {
(int _3wrap, int _4wrap) = FastDecompose(count); (int _3wrap, int _4wrap) = FastDecompose(count);
+2
View File
@@ -88,6 +88,7 @@
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>opengl32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -105,6 +106,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>opengl32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+2 -2
View File
@@ -2,11 +2,11 @@
#pragma once #pragma once
#endif #endif
#include <xmmintrin.h>
#ifndef SN_INTERNAL #ifndef SN_INTERNAL
#define SN_INTERNAL #define SN_INTERNAL
#include <xmmintrin.h>
#ifdef _MSC_VER #ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS 1 #define _CRT_SECURE_NO_WARNINGS 1
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
+1 -1
View File
@@ -59,7 +59,7 @@ typedef uint64_t(SN_DECL *FACTORIALROC)(int n);
#pragma region matix function #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, INTERNAL void SN_DECL f32_add_sse(MAT_KERNEL(float) const *left, MAT_KERNEL(float) const *right,
MAT_KERNEL(float) *restrict ans); MAT_KERNEL(float) *restrict ans);
+16 -1
View File
@@ -9,11 +9,26 @@
#define ZMMCOUNT(T) sizeof(T) / 4 #define ZMMCOUNT(T) sizeof(T) / 4
#define MAT_KERNEL(T) \ #define MAT_KERNEL(T) \
union { \ union mat_kernel_##T##{ \
__m128 xmm[XMMCOUNT(T)]; \ __m128 xmm[XMMCOUNT(T)]; \
__m256 ymm[YMMCOUNT(T)]; \ __m256 ymm[YMMCOUNT(T)]; \
__m512 zmm[ZMMCOUNT(T)]; \ __m512 zmm[ZMMCOUNT(T)]; \
T m[4][4]; \ 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 #endif
+3 -2
View File
@@ -1,8 +1,9 @@
#include "sn_intrinsic.h" #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, 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 source0 = _mm_load_ps(&left->xmm[0]);
register __m128 source1 = _mm_load_ps(&left->xmm[1]); register __m128 source1 = _mm_load_ps(&left->xmm[1]);
+1 -6
View File
@@ -3,12 +3,7 @@
INTERNAL int SN_DECL index_pair_sse(short const *str, uint32_t target, int length) 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; int index = 0, result = 0, size = length, end = size - 8;
__m128i s = { __m128i s = _mm_set1_epi32(target);
target,
target,
target,
target,
};
__m128i vec, com; __m128i vec, com;
while (index < end) { while (index < end) {
+8 -7
View File
@@ -1,24 +1,25 @@
#include "StgSharpNative.h" #include "sn_intrinsic.h"
#include "sn_internal.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, a_length_sq = _mm_add_ps(a_length_sq,
_mm_shuffle_ps(a_length_sq, a_length_sq, _MM_SHUFFLE(2, 3, 0, 1))); _mm_shuffle_ps(a_length_sq, a_length_sq, _MM_SHUFFLE(2, 3, 0, 1)));
a_length_sq = _mm_add_ss(a_length_sq, a_length_sq = _mm_add_ss(a_length_sq,
_mm_shuffle_ps(a_length_sq, a_length_sq, _MM_SHUFFLE(0, 0, 3, 2))); _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); __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, dot_product = _mm_add_ps(dot_product,
_mm_shuffle_ps(dot_product, dot_product, _MM_SHUFFLE(2, 3, 0, 1))); _mm_shuffle_ps(dot_product, dot_product, _MM_SHUFFLE(2, 3, 0, 1)));
dot_product = _mm_add_ss(dot_product, dot_product = _mm_add_ss(dot_product,
_mm_shuffle_ps(dot_product, dot_product, _MM_SHUFFLE(0, 0, 3, 2))); _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); __m128 b_length_sq = _mm_mul_ps(b_orthogonal, b_orthogonal);
b_length_sq = _mm_add_ps(b_length_sq, 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))); _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); __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);
} }