mpl going on good process
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[InlineArray(16)]
|
||||
public unsafe struct MatrixKernel<T> where T: unmanaged, INumber<T>
|
||||
{
|
||||
|
||||
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()
|
||||
{
|
||||
|
||||
@@ -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<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 kernelRow = row / t_count, r = row % t_count;
|
||||
ref MatrixKernel<T> kernel = ref _buffer[kernelColumn + (KernelColumnLength * kernelRow)];
|
||||
return ref kernel.UnsafeIndex(c, r);
|
||||
return ref kernel[c, r];
|
||||
}
|
||||
|
||||
#region enumeration
|
||||
|
||||
@@ -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<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 kernelRow = row / t_count, r = row % t_count;
|
||||
ref MatrixKernel<T> kernel = ref k_buffer[(kernelColumn * kernelColumn) + kernelRow];
|
||||
return ref kernel.UnsafeIndex(c, r);
|
||||
return ref kernel[c, r];
|
||||
}
|
||||
|
||||
~HlsfMatrix()
|
||||
|
||||
@@ -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<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<MatrixParallelTaskPackageNonGeneric> _wrapAllocator ;
|
||||
private static SlabAllocator<MatrixParallelTaskPackageNonGeneric> _wrapAllocator;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static MatrixParallelTaskPackage<T>* CreateBaseTask<T>() where T: unmanaged, INumber<T>
|
||||
@@ -76,17 +76,13 @@ namespace StgSharp.Mathematics
|
||||
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>
|
||||
{
|
||||
MatrixParallelTaskPackage<T>* p = (MatrixParallelTaskPackage<T>*)_wrapAllocator.Allocate();
|
||||
/*
|
||||
*p = *source;
|
||||
p->Left += offset * p->LeftStride;
|
||||
p->Right += offset * p->RightStride;
|
||||
p->Result += offset * p->ResultStride;
|
||||
/**/
|
||||
return p;
|
||||
MatrixParallelTaskPackage<T>* ptr = (MatrixParallelTaskPackage<T>*)_wrapAllocator.Allocate();
|
||||
MatrixParallelTaskPackage<T>.Copy(exist, ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>opengl32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
@@ -105,6 +106,7 @@
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>opengl32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#ifndef SN_INTERNAL
|
||||
#define SN_INTERNAL
|
||||
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_WARNINGS 1
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user