From b32c1cb4eb8dce91a6b66478b09f5dcc3020e471 Mon Sep 17 00:00:00 2001 From: Youmu Liu <105042599+Nitload-NSI@users.noreply.github.com> Date: Thu, 18 Dec 2025 18:04:55 +0800 Subject: [PATCH 1/3] redesign matrix design --- .../{MatrixEnum.cs => Matrix.Create.cs} | 24 +- StgSharp.Common/Mathematics/Linear/Matrix.cs | 97 ++++---- .../Mathematics/Linear/MatrixMetadata.cs | 114 +++++++++ .../Mathematics/Linear/MatrixStorage.cs | 65 ++++++ .../Mathematics/Linear/Matrix_T.GC.cs | 124 ---------- .../Mathematics/Linear/Matrix_T.HLSF.cs | 137 ----------- .../Mathematics/Linear/Matrix_T.cs | 218 ------------------ .../Numeric/MatrixCompute.Factorize.cs | 2 +- StgSharp.Native/sn-src/k_pivot.c | 17 +- 9 files changed, 256 insertions(+), 542 deletions(-) rename StgSharp.Common/Mathematics/Linear/{MatrixEnum.cs => Matrix.Create.cs} (63%) create mode 100644 StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs create mode 100644 StgSharp.Common/Mathematics/Linear/MatrixStorage.cs delete mode 100644 StgSharp.Common/Mathematics/Linear/Matrix_T.GC.cs delete mode 100644 StgSharp.Common/Mathematics/Linear/Matrix_T.HLSF.cs delete mode 100644 StgSharp.Common/Mathematics/Linear/Matrix_T.cs diff --git a/StgSharp.Common/Mathematics/Linear/MatrixEnum.cs b/StgSharp.Common/Mathematics/Linear/Matrix.Create.cs similarity index 63% rename from StgSharp.Common/Mathematics/Linear/MatrixEnum.cs rename to StgSharp.Common/Mathematics/Linear/Matrix.Create.cs index 4c0aee51..cde390e0 100644 --- a/StgSharp.Common/Mathematics/Linear/MatrixEnum.cs +++ b/StgSharp.Common/Mathematics/Linear/Matrix.Create.cs @@ -1,6 +1,6 @@ -//----------------------------------------------------------------------- +//----------------------------------------------------------------------- // ----------------------------------------------------------------------- -// file="MatrixEnum" +// file="Matrix.Create" // Project: StgSharp // AuthorGroup: Nitload // Copyright (c) Nitload. All rights reserved. @@ -25,6 +25,7 @@ // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- +using StgSharp.HighPerformance.Memory; using System; using System.Collections.Generic; using System.Linq; @@ -33,11 +34,24 @@ using System.Threading.Tasks; namespace StgSharp.Mathematics.Numeric { - public enum MatrixAllocation + public unsafe partial class Matrix { - HLSF, - GC, + public static Matrix Create( + int columnLength, + int rowLength, + HybridLayerSegregatedFitAllocator allocator) + { + Matrix matrix = new Matrix(); + int tSize = sizeof(T); + int totalSize = columnLength * rowLength * tSize; + HybridLayerSegregatedFitAllocationHandle handle = allocator.Alloc((uint)totalSize); + MatrixStorageHLSF storage = new MatrixStorageHLSF(handle); + storage._handle = handle; + matrix._buffer = storage; + matrix._enumeration = new MatrixMetadata(columnLength, rowLength); + return matrix; + } } } diff --git a/StgSharp.Common/Mathematics/Linear/Matrix.cs b/StgSharp.Common/Mathematics/Linear/Matrix.cs index 5738ecca..8ecf1326 100644 --- a/StgSharp.Common/Mathematics/Linear/Matrix.cs +++ b/StgSharp.Common/Mathematics/Linear/Matrix.cs @@ -25,59 +25,74 @@ // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- +using StgSharp.HighPerformance; +using StgSharp.Mathematics.Numeric; using System; -using System.Collections.Generic; -using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; +using System.Runtime.InteropServices; -using hlsfAllocator = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocator; +// using hlsfHandle = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocationHandle; namespace StgSharp.Mathematics.Numeric { - public static class Matrix + public unsafe partial class Matrix where T : unmanaged, INumber { - public static hlsfAllocator? DefaultAllocator + private protected static readonly int t_count = 16 / sizeof(T); + + private protected static readonly int t_size = sizeof(T); + private MatrixMetadata _enumeration; + + private MatrixStorage _buffer; + + private protected Matrix() { } + + public ref T this[int column, int row] { - get - { - ArgumentNullException.ThrowIfNull(field, nameof(DefaultAllocator)); - return null; + get => throw new NotImplementedException(); + } + + public unsafe Matrix this[ + ReadOnlySpan column, + ReadOnlySpan row] + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + /// + /// Length of the matrix in columns. + /// + public int ColumnLength { get; init; } + + /// + /// Length of the matrix in rows. + /// + public int RowLength { get; init; } + + public MatrixLayout Layout { get; init; } + + internal MatrixKernel* Buffer { get; } + + protected internal int KernelColumnLength { get; init; } + + protected internal int KernelRowLength { get; init; } + + public ref MatrixKernel GetMatrixKernel(int column, int row) + { + if (_enumeration.GetCurrentKernelIndex) { } else { } + } + + private protected void AssertIndex(int column, int row) + { + if (column < 0 || column >= ColumnLength) { + throw new ArgumentOutOfRangeException(nameof(column)); } - set; - } = null; - public static MatrixAllocation DefaultAllocation { get; set; } = MatrixAllocation.GC; - - public static Matrix FromDefault(int columnLength, int rowLength) - where T : unmanaged, INumber - { - return DefaultAllocation switch - { - MatrixAllocation.GC => FromGC(columnLength, rowLength), - MatrixAllocation.HLSF => FromHlsf(columnLength, rowLength, DefaultAllocator!), - _ => throw new NotSupportedException("This allocation is not supported."), - }; - } - - public static Matrix FromGC(int columnLength, int rowLength) - where T : unmanaged, INumber - { - return new GCMatrix(columnLength, rowLength); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Matrix FromHlsf( - int columnLength, - int rowLength, - hlsfAllocator allocator) - where T : unmanaged, INumber - { - ArgumentNullException.ThrowIfNull(allocator, nameof(allocator)); - return new HlsfMatrix(columnLength, rowLength, allocator); + if (row < 0 || row >= RowLength) { + throw new ArgumentOutOfRangeException(nameof(row)); + } } } diff --git a/StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs b/StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs new file mode 100644 index 00000000..754ea926 --- /dev/null +++ b/StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs @@ -0,0 +1,114 @@ +//----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +// file="MatrixMetadata" +// Project: StgSharp +// AuthorGroup: Nitload +// Copyright (c) Nitload. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// ----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +using StgSharp.HighPerformance; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace StgSharp.Mathematics.Numeric +{ + public enum MatrixLayout + { + + DenseSquare, + UpperTriangle, + LowerTriangle, + + } + + [StructLayout(LayoutKind.Sequential)] + public unsafe struct MatrixKernelEnumeration + { + + public readonly delegate* unmanaged[Cdecl] + GetIndexOffset; + + public readonly delegate* unmanaged[Cdecl] IsInBuffer; + + [Obsolete("Do not use constructor, use static method instead", true)] + public MatrixKernelEnumeration() { } + + public MatrixKernelEnumeration( + delegate* unmanaged[Cdecl] + getOffset, + delegate* unmanaged[Cdecl] inBuffer) + { + GetIndexOffset = getOffset; + IsInBuffer = inBuffer; + } + + private static delegate* unmanaged[Cdecl] IsInBufferDenseSquarePtr { get; } = (delegate* unmanaged[Cdecl])&IsInBufferDenseSquare; + + public static MatrixKernelEnumeration Create(MatrixLayout layout) + { + return layout switch + { + MatrixLayout.DenseSquare => new MatrixKernelEnumeration(null, IsInBufferDenseSquarePtr), + + MatrixLayout.UpperTriangle => throw new NotImplementedException(), + }; + } + + private static bool IsInBufferDenseSquare( + int col, + int row, + MatrixKernelEnumerator* enumerator) + { + return true; + } + + } + + [StructLayout(LayoutKind.Explicit)] + public struct MatrixSize + { + + [FieldOffset(0)] public readonly int ElementColumnLength; + [FieldOffset(4)] public readonly int ElementRowLength; + + [FieldOffset(8)] public readonly int KernelColumnLength; + [FieldOffset(12)] public readonly int KernelRowLength; + + } + + [StructLayout(LayoutKind.Explicit)] + public struct MatrixKernelEnumerator + { + + [FieldOffset(0)] public int CurrentColumn; + [FieldOffset(4)] public int CurrentRow; + + [FieldOffset(8)] public readonly int KernelColumnLength; + [FieldOffset(12)] public readonly int KernelRowLength; + + } +} diff --git a/StgSharp.Common/Mathematics/Linear/MatrixStorage.cs b/StgSharp.Common/Mathematics/Linear/MatrixStorage.cs new file mode 100644 index 00000000..696ba01a --- /dev/null +++ b/StgSharp.Common/Mathematics/Linear/MatrixStorage.cs @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +// file="MatrixStorage" +// Project: StgSharp +// AuthorGroup: Nitload +// Copyright (c) Nitload. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// ----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +using StgSharp.HighPerformance.Memory; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; + +using HLSFAllocator = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocator; +using HLSFHandle = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocationHandle; + +namespace StgSharp.Mathematics.Numeric +{ + public abstract class MatrixStorage : IDisposable where T : unmanaged, INumber + { + + protected internal abstract unsafe T* BufferPointer { get; } + + public abstract void Dispose(); + + } + + internal class MatrixStorageHLSF(HLSFAllocator allocator, HLSFHandle handle) : MatrixStorage + where T : unmanaged, INumber + { + + internal HLSFAllocator _allocator = allocator; + internal HLSFHandle _handle = handle; + + protected internal override unsafe T* BufferPointer => (T*)_handle.Pointer; + + public override void Dispose() + { + allocator.Free(_handle); + } + + } +} diff --git a/StgSharp.Common/Mathematics/Linear/Matrix_T.GC.cs b/StgSharp.Common/Mathematics/Linear/Matrix_T.GC.cs deleted file mode 100644 index 5d971427..00000000 --- a/StgSharp.Common/Mathematics/Linear/Matrix_T.GC.cs +++ /dev/null @@ -1,124 +0,0 @@ -//----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -// file="Matrix_T.GC" -// Project: StgSharp -// AuthorGroup: Nitload -// Copyright (c) Nitload. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -// ----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -using StgSharp.HighPerformance; -using StgSharp.Mathematics; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace StgSharp.Mathematics.Numeric -{ - internal unsafe partial class GCMatrix : Matrix where T : unmanaged, INumber - { - - private readonly MatrixKernel* _buffer; - - public GCMatrix(int column, int row) - { - KernelColumnLength = (column + 3) / 4; - KernelRowLength = (row + 3) / t_count; - ColumnLength = column; - RowLength = row; - _buffer = (MatrixKernel*)NativeMemory.AlignedAlloc((nuint)(column * row * sizeof(T)), (nuint)World.DefaultSIMDAlignment); - } - - public override ref T this[int column, int row] - { - get - { - AssertIndex(column, row); - 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[c, r]; - } - } - - public override Matrix this[ReadOnlySpan column, ReadOnlySpan row] - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - - internal override unsafe MatrixKernel* Buffer - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _buffer; - } - - public override unsafe ref MatrixKernel GetMatrixKernel(int column, int row) - { - AssertIndex(column, row); - int kernelColumn = column / 4; - int kernelRow = row / t_count; - return ref _buffer[kernelColumn + (KernelColumnLength * kernelRow)]; - } - - public override ref T UnsafeIndex(int column, int row) - { - 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[c, r]; - } - - ~GCMatrix() - { - NativeMemory.AlignedFree(_buffer); - } - - #region enumeration - - public override unsafe MatrixSegmentEnumeration ColumnEnumeration - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new MatrixSegmentEnumeration(_buffer, KernelColumnLength, KernelColumnLength * KernelRowLength, 1, - KernelColumnLength); - } - - public override unsafe MatrixSegmentEnumeration GetRowEnumeration() - { - return new MatrixSegmentEnumeration(_buffer, 1, KernelColumnLength, KernelColumnLength, KernelRowLength); - } - - public override unsafe MatrixSegmentEnumeration SequentialEnumeration - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new MatrixSegmentEnumeration(_buffer, KernelRowLength * KernelColumnLength, - KernelColumnLength * KernelRowLength, 1, - KernelRowLength * KernelColumnLength); - } - - #endregion - } -} diff --git a/StgSharp.Common/Mathematics/Linear/Matrix_T.HLSF.cs b/StgSharp.Common/Mathematics/Linear/Matrix_T.HLSF.cs deleted file mode 100644 index c0b28d22..00000000 --- a/StgSharp.Common/Mathematics/Linear/Matrix_T.HLSF.cs +++ /dev/null @@ -1,137 +0,0 @@ -//----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -// file="Matrix_T.HLSF" -// Project: StgSharp -// AuthorGroup: Nitload -// Copyright (c) Nitload. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -// ----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -using StgSharp.HighPerformance; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; - -using hlsfAllocator = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocator; -using hlsfHandle = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocationHandle; - -namespace StgSharp.Mathematics.Numeric -{ - internal unsafe partial class HlsfMatrix : Matrix where T : unmanaged, INumber - { - - private readonly MatrixKernel* k_buffer; - private readonly hlsfAllocator allocator; - private readonly hlsfHandle handle; - - internal HlsfMatrix(int column, int row, hlsfAllocator allocator) - { - KernelColumnLength = (column + 3) / 4; - KernelRowLength = (row + 3) / t_count; - ColumnLength = column; - RowLength = row; - long size = (long)KernelColumnLength * (long)KernelRowLength * (long)sizeof(MatrixKernel); - this.handle = allocator.Alloc((uint)(size)); - if (handle.AllocSize < size) { - throw new InsufficientMemoryException(); - } - k_buffer = (MatrixKernel*)handle.Pointer; - } - - public override ref T this[int column, int row] - { - get - { - AssertIndex(column, row); - 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[c, r]; - } - } - - public override Matrix this[ - ReadOnlySpan column, - ReadOnlySpan row] - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - - internal override unsafe MatrixKernel* Buffer - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => k_buffer; - } - - public override unsafe ref MatrixKernel GetMatrixKernel(int column, int row) - { - AssertIndex(column, row); - int kernelColumn = column / 4, c = column % 4; - int kernelRow = row / t_count, r = row % t_count; - return ref k_buffer[(kernelColumn * kernelColumn) + kernelRow]; - } - - public override ref T UnsafeIndex(int column, int row) - { - 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[c, r]; - } - - ~HlsfMatrix() - { - allocator.Free(handle); - } - - #region enumeration - - public override unsafe MatrixSegmentEnumeration ColumnEnumeration - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new MatrixSegmentEnumeration(k_buffer, KernelColumnLength, - KernelColumnLength * KernelRowLength, 1, - KernelColumnLength); - } - - public override unsafe MatrixSegmentEnumeration GetRowEnumeration() - { - return new MatrixSegmentEnumeration(k_buffer, 1, KernelColumnLength, - KernelColumnLength, KernelRowLength); - } - - public override unsafe MatrixSegmentEnumeration SequentialEnumeration - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - - get => new MatrixSegmentEnumeration(k_buffer, KernelRowLength * KernelColumnLength, - KernelColumnLength * KernelRowLength, 1, - KernelRowLength * KernelColumnLength); - } - - #endregion - } -} diff --git a/StgSharp.Common/Mathematics/Linear/Matrix_T.cs b/StgSharp.Common/Mathematics/Linear/Matrix_T.cs deleted file mode 100644 index 3d1e3cff..00000000 --- a/StgSharp.Common/Mathematics/Linear/Matrix_T.cs +++ /dev/null @@ -1,218 +0,0 @@ -//----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -// file="Matrix_T" -// Project: StgSharp -// AuthorGroup: Nitload -// Copyright (c) Nitload. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -// ----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -using StgSharp.HighPerformance; -using System; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// using hlsfHandle = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocationHandle; - -namespace StgSharp.Mathematics.Numeric -{ - public abstract unsafe partial class Matrix where T : unmanaged, INumber - { - - private protected readonly int t_count = 16 / sizeof(T); - - private protected readonly int t_size = sizeof(T); - - private protected Matrix() { } - - public abstract ref T this[int column, int row] - { - get; - } - - public abstract unsafe Matrix this[ReadOnlySpan column, ReadOnlySpan row] - { - get; - set; - } - - /// - /// Length of the matrix in columns. - /// - public int ColumnLength { get; init; } - - /// - /// Length of the matrix in rows. - /// - public int RowLength { get; init; } - - public abstract MatrixSegmentEnumeration ColumnEnumeration { get; } - - public abstract MatrixSegmentEnumeration SequentialEnumeration { get; } - - internal abstract MatrixKernel* Buffer { get; } - - protected internal int KernelColumnLength { get; init; } - - protected internal int KernelRowLength { get; init; } - - public abstract ref MatrixKernel GetMatrixKernel(int column, int row); - - public abstract MatrixSegmentEnumeration GetRowEnumeration(); - - [Obsolete("This method does not contain boarder check, so be careful on size or use indexer instead.", false)] - public abstract ref T UnsafeIndex(int column, int row); - - private protected void AssertIndex(int column, int row) - { - if (column < 0 || column >= ColumnLength) { - throw new ArgumentOutOfRangeException(nameof(column)); - } - - if (row < 0 || row >= RowLength) { - throw new ArgumentOutOfRangeException(nameof(row)); - } - } - - } - - public readonly unsafe ref struct MatrixSegmentEnumeration( - MatrixKernel* source, - int primStride, - int primSize, - int secondaryStride, - int secondarySize, - int primOffset = 0, - int secondaryOffset = 0) - where T : unmanaged, INumber - { - - private readonly MatrixKernel* _source = source; - internal readonly int PrimOffset = primOffset; - - internal readonly int PrimSize = primSize; - internal readonly int PrimStride = primStride; - internal readonly int SecondaryOffset = secondaryOffset; - internal readonly int SecondarySize = secondarySize; - internal readonly int SecondaryStride = secondaryStride; - - internal readonly MatrixKernel* Source - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _source; - } - - public Enumerator GetEnumerator() - { - return new Enumerator(in this); - } - - public ref struct Enumerator(in MatrixSegmentEnumeration enumeration) - { - - private readonly MatrixKernel* _source = enumeration._source; - private int _indexCount = -1; - private readonly int _stride = enumeration.PrimStride; - private readonly long _bound = (long)enumeration.PrimSize * enumeration.PrimStride; - private long _index = (long)enumeration.PrimOffset * enumeration.PrimStride; - - private readonly MatrixSegmentEnumeration _enumeration; - - public readonly MatrixSegment Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new(_source + _index, _enumeration.SecondarySize, _enumeration.SecondaryStride, - _enumeration.PrimOffset); - } - - public bool MoveNext() - { - _indexCount++; - _index += _stride; - if (_index >= _bound) { - _index = 0; - } - return _indexCount >= _enumeration.PrimSize; - } - - } - - } - - public readonly unsafe ref struct MatrixSegment(MatrixKernel* source, int size, int stride, int offset) - where T : unmanaged, INumber - { - - private readonly MatrixKernel* _source = source; - private readonly int _offset = offset; - private readonly int _secondarySize = size; - private readonly int _size = size; - private readonly int _stride = stride; - - public ref MatrixKernel this[int index] - { - get - { - if (index < 0 || index >= _size) { - throw new ArgumentOutOfRangeException(nameof(index)); - } - return ref _source[index * _stride]; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator GetEnumerator() - { - return new Enumerator(in this); - } - - public ref struct Enumerator(in MatrixSegment segment) - { - - private readonly int _end = segment._size; - - private int _indexCount = -1; - private readonly long _bound = (long)segment._size * segment._stride; - private long _index = (long)segment._offset * segment._stride; - private readonly MatrixSegment _segment = segment; - - public readonly MatrixKernel* Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _segment._source + _index; - } - - public bool MoveNext() - { - _index += _segment._stride; - _indexCount++; - if (_index >= _bound) { - _index = 0; - } - - return _indexCount < _end; - } - - } - - } -} diff --git a/StgSharp.Mathematics/Numeric/MatrixCompute.Factorize.cs b/StgSharp.Mathematics/Numeric/MatrixCompute.Factorize.cs index ebc58bdd..c2b8d787 100644 --- a/StgSharp.Mathematics/Numeric/MatrixCompute.Factorize.cs +++ b/StgSharp.Mathematics/Numeric/MatrixCompute.Factorize.cs @@ -38,7 +38,7 @@ namespace StgSharp.Mathematics.Numeric public static void FactorizePLU( Matrix matrix, - Matrix p, + Span p, Matrix lower, Matrix upper) { diff --git a/StgSharp.Native/sn-src/k_pivot.c b/StgSharp.Native/sn-src/k_pivot.c index 6617c14b..c2b51c7b 100644 --- a/StgSharp.Native/sn-src/k_pivot.c +++ b/StgSharp.Native/sn-src/k_pivot.c @@ -2,7 +2,7 @@ // Hybrid implementation: SIMD for Abs, Scalar for Max // Assumes Column-Major layout for both MAT_KERNEL content and Kernel sequence -static void povit_float_simd_abs(MAT_KERNEL(float) const *source, size_t col_begin, +static void povit_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 }; @@ -62,18 +62,3 @@ static void povit_float_simd_abs(MAT_KERNEL(float) const *source, size_t col_beg } } } - -DECLARE_MAT_POVIT_PROC(float, sse) -{ - povit_float_simd_abs(source, col_begin, col_length, ans); -} - -DECLARE_MAT_POVIT_PROC(float, avx) -{ - povit_float_simd_abs(source, col_begin, col_length, ans); -} - -DECLARE_MAT_POVIT_PROC(float, 512) -{ - povit_float_simd_abs(source, col_begin, col_length, ans); -} From b60ce56f1c731b48568a06618e2d692ffd46c8b5 Mon Sep 17 00:00:00 2001 From: Youmu Liu <105042599+Nitload-NSI@users.noreply.github.com> Date: Tue, 23 Dec 2025 18:13:05 +0800 Subject: [PATCH 2/3] redesign matrix design --- .../HighPerformance/MatrixKernel.cs | 6 +- .../Mathematics/Linear/CoordinationNaming.md | 88 +++++++++++ .../Mathematics/Linear/Matrix.Create.cs | 67 ++++++++- StgSharp.Common/Mathematics/Linear/Matrix.cs | 82 ++++++++--- .../Mathematics/Linear/MatrixMetadata.cs | 138 ++++++++++++++++-- .../Mathematics/Linear/MatrixStorage.cs | 7 + StgSharp.Native/StgSharp.Native.vcxproj | 2 +- .../StgSharp.Native.vcxproj.filters | 2 +- StgSharp.Native/sn-head/sn_intrinsic.h | 73 ++++----- StgSharp.Native/sn-src/k_bufop.c | 134 ----------------- StgSharp.Native/sn-src/k_kerop.c | 113 ++++++++++++++ StgSharpDebug/Program.cs | 6 +- 12 files changed, 493 insertions(+), 225 deletions(-) create mode 100644 StgSharp.Common/Mathematics/Linear/CoordinationNaming.md delete mode 100644 StgSharp.Native/sn-src/k_bufop.c create mode 100644 StgSharp.Native/sn-src/k_kerop.c diff --git a/StgSharp.Common/HighPerformance/MatrixKernel.cs b/StgSharp.Common/HighPerformance/MatrixKernel.cs index 4535487f..1b5adb73 100644 --- a/StgSharp.Common/HighPerformance/MatrixKernel.cs +++ b/StgSharp.Common/HighPerformance/MatrixKernel.cs @@ -44,6 +44,8 @@ namespace StgSharp.HighPerformance public unsafe struct MatrixKernel where T : unmanaged, INumber { + public static readonly int Size = 16 * sizeof(T); + private T c0r0; public MatrixKernel() @@ -58,10 +60,10 @@ namespace StgSharp.HighPerformance } } - public ref T this[int column, int row] + public ref T this[int row, int column] { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref Unsafe.Add(ref c0r0, (column * 4) + row); + get => ref Unsafe.Add(ref c0r0, (row * 4) + column); } } diff --git a/StgSharp.Common/Mathematics/Linear/CoordinationNaming.md b/StgSharp.Common/Mathematics/Linear/CoordinationNaming.md new file mode 100644 index 00000000..1f1cc175 --- /dev/null +++ b/StgSharp.Common/Mathematics/Linear/CoordinationNaming.md @@ -0,0 +1,88 @@ +# Matrix Coordinate & Naming Conventions (StgSharp) + +This document defines the coordinate terminology and naming rules used across `Matrix`, `MatrixKernel`, and packed/triangular storage layouts. +Goal: eliminate ambiguity around `column`/`row` names (e.g., “index **of** a column” vs “index **along** a column”). + +--- + +## 1) The key rule: encode prepositions into identifiers (`Of` vs `In`) + +### `...OfX` — “which X” (object identity / ordinal) +Use **`Of`** when the value identifies **which object** (which column, which row, which kernel, etc.). + +Examples: +- `columnOfElement`: the element is located in **which column** +- `rowOfKernel`: the kernel block is located in **which row** + +### `...InX` / `...WithinX` — “inside X” (local coordinate) +Use **`In`** (or `Within`) when the value is a **local coordinate inside** another object. + +Examples: +- `columnInKernel`: local column coordinate **inside** a kernel block +- `rowInKernel`: local row coordinate **inside** a kernel block + +> Quick mental model: **`Of` = identity**, **`In` = inside**. + +--- + +## 2) Coordinate levels: `Element`, `KernelGrid`, `InKernel` + +StgSharp commonly uses three coordinate levels: + +1. **Element-level**: final matrix element coordinates (`Matrix[col,row]`) +2. **Kernel-grid level**: coordinates of a kernel block in the kernel grid +3. **In-kernel level**: local element coordinates within a kernel (e.g., 4×4) + +Recommended names: + +| Level | Column name | Row name | Meaning | +|---|---|---|---| +| Element | `columnOfElement` | `rowOfElement` | element located in which column/row (0-based) | +| Kernel grid | `columnOfKernel` | `rowOfKernel` | kernel block located in which kernel-column/kernel-row (0-based) | +| In-kernel | `columnInKernel` | `rowInKernel` | local coordinate inside the kernel (0..KernelSize-1) | + +--- + +## 3) Index base: 0-based (mandatory) + +Unless explicitly documented otherwise, all coordinates are **0-based**: + +- `columnOfElement ∈ [0, ColumnLength-1]` +- `rowOfElement ∈ [0, RowLength-1]` +- `columnOfKernel ∈ [0, KernelColumnLength-1]` +- `rowOfKernel ∈ [0, KernelRowLength-1]` +- `columnInKernel ∈ [0, KernelSize-1]` +- `rowInKernel ∈ [0, KernelSize-1]` + +--- + +## 4) Mapping element coordinates to kernel coordinates (KernelSize = 4 example) + +For a fixed kernel size `KernelSize = 4`: + +```csharp +int columnOfKernel = columnOfElement / 4; +int rowOfKernel = rowOfElement / 4; + +int columnInKernel = columnOfElement % 4; +int rowInKernel = rowOfElement % 4; +``` + +If `columnOfElement` and `rowOfElement` are guaranteed non-negative, bit operations can be used: + +```csharp +int columnOfKernel = columnOfElement >> 2; +int rowOfKernel = rowOfElement >> 2; + +int columnInKernel = columnOfElement & 3; +int rowInKernel = rowOfElement & 3; +``` + +--- + +## 5) Packed storage: distinguish `Index` from `Offset` + +Packed layouts do **not** store “empty blocks”; stored blocks are placed contiguously in a packed buffer. + +### Use the correct terms +- **`packedKernelIndex`**: “the N-th kernel diff --git a/StgSharp.Common/Mathematics/Linear/Matrix.Create.cs b/StgSharp.Common/Mathematics/Linear/Matrix.Create.cs index cde390e0..4aad5110 100644 --- a/StgSharp.Common/Mathematics/Linear/Matrix.Create.cs +++ b/StgSharp.Common/Mathematics/Linear/Matrix.Create.cs @@ -25,10 +25,12 @@ // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- +using StgSharp.HighPerformance; using StgSharp.HighPerformance.Memory; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; @@ -37,21 +39,72 @@ namespace StgSharp.Mathematics.Numeric public unsafe partial class Matrix { + private const int KernelSideLength = 4; + public static Matrix Create( int columnLength, int rowLength, + MatrixLayout layout, HybridLayerSegregatedFitAllocator allocator) { - Matrix matrix = new Matrix(); - int tSize = sizeof(T); - int totalSize = columnLength * rowLength * tSize; - HybridLayerSegregatedFitAllocationHandle handle = allocator.Alloc((uint)totalSize); - MatrixStorageHLSF storage = new MatrixStorageHLSF(handle); - storage._handle = handle; + ArgumentNullException.ThrowIfNull(allocator); + + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(columnLength); + + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(rowLength); + + int kernelColumns = DivideRoundUp(columnLength, KernelSideLength); + int kernelRows = DivideRoundUp(rowLength, KernelSideLength); + + if (layout is MatrixLayout.UpperTriangle or MatrixLayout.LowerTriangle) + { + if (kernelColumns != kernelRows) { + throw new ArgumentException("Triangular layouts require square matrices."); + } + } + + long kernelCount = layout switch + { + MatrixLayout.DenseSquare => (long)kernelColumns * kernelRows, + MatrixLayout.UpperTriangle => TriangularKernelCount(kernelColumns), + MatrixLayout.LowerTriangle => TriangularKernelCount(kernelRows), + _ => throw new ArgumentOutOfRangeException(nameof(layout)) + }; + + long requiredBytes = kernelCount * MatrixKernel.Size; + if (requiredBytes <= 0 || requiredBytes > uint.MaxValue) { + throw new ArgumentOutOfRangeException(nameof(requiredBytes), "Requested matrix exceeds allocator capacity."); + } + + HybridLayerSegregatedFitAllocationHandle handle = allocator.Alloc((uint)requiredBytes); + MatrixStorageHLSF storage = new MatrixStorageHLSF(allocator, handle); + + Matrix matrix = new Matrix + { + Layout = layout, + KernelColumnLength = kernelColumns, + KernelRowLength = kernelRows, + }; + matrix._buffer = storage; - matrix._enumeration = new MatrixMetadata(columnLength, rowLength); + matrix._boarder = MatrixKernelBoarder.Create(layout); + matrix._size = new MatrixSize(columnLength, rowLength, kernelColumns, kernelRows); + return matrix; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int DivideRoundUp(int value, int divisor) + { + return (value + (divisor - 1)) / divisor; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static long TriangularKernelCount(int order) + { + long n = order; + return (n * (n + 1L)) / 2L; + } + } } diff --git a/StgSharp.Common/Mathematics/Linear/Matrix.cs b/StgSharp.Common/Mathematics/Linear/Matrix.cs index 8ecf1326..f356cca5 100644 --- a/StgSharp.Common/Mathematics/Linear/Matrix.cs +++ b/StgSharp.Common/Mathematics/Linear/Matrix.cs @@ -30,7 +30,6 @@ using StgSharp.Mathematics.Numeric; using System; using System.Numerics; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; // using hlsfHandle = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocationHandle; @@ -42,17 +41,61 @@ namespace StgSharp.Mathematics.Numeric private protected static readonly int t_count = 16 / sizeof(T); private protected static readonly int t_size = sizeof(T); - private MatrixMetadata _enumeration; - + private MatrixKernelBoarder _boarder; + private MatrixSize _size; private MatrixStorage _buffer; private protected Matrix() { } - public ref T this[int column, int row] + public T this[int x, int y] { - get => throw new NotImplementedException(); + get + { + if (y < 0 || y > _size.ElementColumnLength || x < 0 || x > _size.ElementRowLength) { + throw new ArgumentOutOfRangeException($"Index [{x},{y}] is out of matrix index range."); + } + + int + k_c = y / 4, + k_r = x / 4, + c = y % 4, + r = x % 4; + ref MatrixKernel kernel = ref GetMatrixKernel(k_c, k_r); + return Unsafe.IsNullRef(ref kernel) ? T.Zero : kernel[c, r]; + } + set + { + if (y < 0 || y > _size.ElementColumnLength || x < 0 || x > _size.ElementRowLength) { + throw new ArgumentOutOfRangeException($"Index [{x},{y}] is out of matrix index range."); + } + + int + k_c = y / 4, + k_r = x / 4, + c = y % 4, + r = x % 4; + ref MatrixKernel kernel = ref GetMatrixKernel(k_c, k_r); + if (!Unsafe.IsNullRef(ref kernel)) { + kernel[c, r] = value; + } + } } + /// + /// Matlab style indexer to generate a new matrix + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public unsafe Matrix this[ ReadOnlySpan column, ReadOnlySpan row] @@ -64,34 +107,33 @@ namespace StgSharp.Mathematics.Numeric /// /// Length of the matrix in columns. /// - public int ColumnLength { get; init; } + public int ColumnLength => _size.ElementColumnLength; /// /// Length of the matrix in rows. /// - public int RowLength { get; init; } + public int RowLength => _size.ElementRowLength; public MatrixLayout Layout { get; init; } - internal MatrixKernel* Buffer { get; } + internal MatrixKernel* Buffer + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => (MatrixKernel*)_buffer.BufferPointer; + } protected internal int KernelColumnLength { get; init; } protected internal int KernelRowLength { get; init; } - public ref MatrixKernel GetMatrixKernel(int column, int row) + public unsafe ref MatrixKernel GetMatrixKernel(int x, int y) { - if (_enumeration.GetCurrentKernelIndex) { } else { } - } - - private protected void AssertIndex(int column, int row) - { - if (column < 0 || column >= ColumnLength) { - throw new ArgumentOutOfRangeException(nameof(column)); - } - - if (row < 0 || row >= RowLength) { - throw new ArgumentOutOfRangeException(nameof(row)); + fixed (MatrixSize *msPtr = &_size) + { + MatrixKernelEnumerator* e = (MatrixKernelEnumerator*)msPtr; + return ref _boarder.IsInBuffer(x, y, e) ? + ref _buffer[_boarder.GetIndexOffset(x, y, e)] : + ref Unsafe.NullRef>(); } } diff --git a/StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs b/StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs index 754ea926..abd6c632 100644 --- a/StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs +++ b/StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs @@ -46,7 +46,7 @@ namespace StgSharp.Mathematics.Numeric } [StructLayout(LayoutKind.Sequential)] - public unsafe struct MatrixKernelEnumeration + public unsafe struct MatrixKernelBoarder { public readonly delegate* unmanaged[Cdecl] @@ -55,9 +55,9 @@ namespace StgSharp.Mathematics.Numeric public readonly delegate* unmanaged[Cdecl] IsInBuffer; [Obsolete("Do not use constructor, use static method instead", true)] - public MatrixKernelEnumeration() { } + public MatrixKernelBoarder() { } - public MatrixKernelEnumeration( + public MatrixKernelBoarder( delegate* unmanaged[Cdecl] getOffset, delegate* unmanaged[Cdecl] inBuffer) @@ -66,24 +66,128 @@ namespace StgSharp.Mathematics.Numeric IsInBuffer = inBuffer; } - private static delegate* unmanaged[Cdecl] IsInBufferDenseSquarePtr { get; } = (delegate* unmanaged[Cdecl])&IsInBufferDenseSquare; + private static delegate* unmanaged[Cdecl] GetIndexOffsetDenseSquarePtr { get; } = + (delegate* unmanaged[Cdecl])&GetIndexOffsetDenseSquare; - public static MatrixKernelEnumeration Create(MatrixLayout layout) + private static delegate* unmanaged[Cdecl] GetIndexOffsetUpperTrianglePtr { get; } = + (delegate* unmanaged[Cdecl])&GetIndexOffsetUpperTriangle; + + private static delegate* unmanaged[Cdecl] GetIndexOffsetLowerTrianglePtr { get; } = + (delegate* unmanaged[Cdecl])&GetIndexOffsetLowerTriangle; + + private static delegate* unmanaged[Cdecl] IsInBufferDenseSquarePtr { get; } = + (delegate* unmanaged[Cdecl])&IsInBufferDenseSquare; + + private static delegate* unmanaged[Cdecl] IsInBufferUpperTrianglePtr { get; } = + (delegate* unmanaged[Cdecl])&IsInBufferUpperTriangle; + + private static delegate* unmanaged[Cdecl] IsInBufferLowerTrianglePtr { get; } = + (delegate* unmanaged[Cdecl])&IsInBufferLowerTriangle; + + public static MatrixKernelBoarder Create(MatrixLayout layout) { return layout switch { - MatrixLayout.DenseSquare => new MatrixKernelEnumeration(null, IsInBufferDenseSquarePtr), + MatrixLayout.DenseSquare => new MatrixKernelBoarder(GetIndexOffsetDenseSquarePtr, IsInBufferDenseSquarePtr), - MatrixLayout.UpperTriangle => throw new NotImplementedException(), + MatrixLayout.UpperTriangle => new MatrixKernelBoarder(GetIndexOffsetUpperTrianglePtr, IsInBufferUpperTrianglePtr), + MatrixLayout.LowerTriangle => new MatrixKernelBoarder(GetIndexOffsetLowerTrianglePtr, IsInBufferLowerTrianglePtr), + _ => throw new ArgumentOutOfRangeException(nameof(layout)), }; } - private static bool IsInBufferDenseSquare( - int col, - int row, + [UnmanagedCallersOnly(CallConvs =[ typeof(CallConvCdecl) ])] + private static long GetIndexOffsetDenseSquare( + int x_kernel, + int y_kernel, MatrixKernelEnumerator* enumerator) { - return true; + long x = x_kernel; + long y = y_kernel; + long rows = enumerator->KernelRowLength; + return x * rows + y; + } + + [UnmanagedCallersOnly(CallConvs =[ typeof(CallConvCdecl) ])] + private static long GetIndexOffsetLowerTriangle( + int x_kernel, + int y_kernel, + MatrixKernelEnumerator* enumerator) + { + long order = GetTriangularOrder(enumerator); + long x = x_kernel; + long y = y_kernel; + + long prefixColumns = x * order - (x * (x - 1L)) / 2L; + return prefixColumns + (y - x); + } + + [UnmanagedCallersOnly(CallConvs =[ typeof(CallConvCdecl) ])] + private static long GetIndexOffsetUpperTriangle( + int x_kernel, + int y_kernel, + MatrixKernelEnumerator* enumerator) + { + long x = x_kernel; + long y = y_kernel; + + long prefixColumns = (x * (x + 1L)) / 2L; + return prefixColumns + y; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static long GetTriangularOrder(MatrixKernelEnumerator* enumerator) + { + return Math.Min(enumerator->KernelColumnLength, enumerator->KernelRowLength); + } + + [UnmanagedCallersOnly(CallConvs =[ typeof(CallConvCdecl) ])] + private static bool IsInBufferDenseSquare( + int x_kernel, + int y_kernel, + MatrixKernelEnumerator* enumerator) + { + return IsWithinKernelDomain(enumerator, x_kernel, y_kernel); + } + + [UnmanagedCallersOnly(CallConvs =[ typeof(CallConvCdecl) ])] + private static bool IsInBufferLowerTriangle( + int x_kernel, + int y_kernel, + MatrixKernelEnumerator* enumerator) + { + return IsWithinTriangularDomain(enumerator, x_kernel, y_kernel) && y_kernel >= x_kernel; + } + + [UnmanagedCallersOnly(CallConvs =[ typeof(CallConvCdecl) ])] + private static bool IsInBufferUpperTriangle( + int x_kernel, + int y_kernel, + MatrixKernelEnumerator* enumerator) + { + return IsWithinTriangularDomain(enumerator, x_kernel, y_kernel) && y_kernel <= x_kernel; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsWithinKernelDomain( + MatrixKernelEnumerator* enumerator, + int x_kernel, + int y_kernel) + { + return x_kernel >= 0 && + y_kernel >= 0 && + x_kernel < enumerator->KernelColumnLength && + y_kernel < enumerator->KernelRowLength; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsWithinTriangularDomain( + MatrixKernelEnumerator* enumerator, + int x_kernel, + int y_kernel) + { + long order = GetTriangularOrder(enumerator); + return x_kernel >= 0 && y_kernel >= 0 && x_kernel < order && y_kernel < order; } } @@ -98,6 +202,18 @@ namespace StgSharp.Mathematics.Numeric [FieldOffset(8)] public readonly int KernelColumnLength; [FieldOffset(12)] public readonly int KernelRowLength; + public MatrixSize( + int elementColumnLength, + int elementRowLength, + int kernelColumnLength, + int kernelRowLength) + { + ElementColumnLength = elementColumnLength; + ElementRowLength = elementRowLength; + KernelColumnLength = kernelColumnLength; + KernelRowLength = kernelRowLength; + } + } [StructLayout(LayoutKind.Explicit)] diff --git a/StgSharp.Common/Mathematics/Linear/MatrixStorage.cs b/StgSharp.Common/Mathematics/Linear/MatrixStorage.cs index 696ba01a..6df883fd 100644 --- a/StgSharp.Common/Mathematics/Linear/MatrixStorage.cs +++ b/StgSharp.Common/Mathematics/Linear/MatrixStorage.cs @@ -25,11 +25,13 @@ // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- +using StgSharp.HighPerformance; using StgSharp.HighPerformance.Memory; using System; using System.Collections.Generic; using System.Linq; using System.Numerics; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; @@ -41,6 +43,11 @@ namespace StgSharp.Mathematics.Numeric public abstract class MatrixStorage : IDisposable where T : unmanaged, INumber { + internal unsafe ref MatrixKernel this[long index] + { + get { return ref Unsafe.AsRef>(BufferPointer + MatrixKernel.Size * index); } + } + protected internal abstract unsafe T* BufferPointer { get; } public abstract void Dispose(); diff --git a/StgSharp.Native/StgSharp.Native.vcxproj b/StgSharp.Native/StgSharp.Native.vcxproj index 2858b025..a9c77499 100644 --- a/StgSharp.Native/StgSharp.Native.vcxproj +++ b/StgSharp.Native/StgSharp.Native.vcxproj @@ -151,7 +151,7 @@ - + diff --git a/StgSharp.Native/StgSharp.Native.vcxproj.filters b/StgSharp.Native/StgSharp.Native.vcxproj.filters index 8161ef1c..d9beed83 100644 --- a/StgSharp.Native/StgSharp.Native.vcxproj.filters +++ b/StgSharp.Native/StgSharp.Native.vcxproj.filters @@ -48,7 +48,7 @@ 源文件 - + 源文件 diff --git a/StgSharp.Native/sn-head/sn_intrinsic.h b/StgSharp.Native/sn-head/sn_intrinsic.h index 8ba80fc4..142d5c92 100644 --- a/StgSharp.Native/sn-head/sn_intrinsic.h +++ b/StgSharp.Native/sn-head/sn_intrinsic.h @@ -96,40 +96,6 @@ static_assert(sizeof(matrix_task) == 128, "matrix_parallel_task_package size mis _Static_assert(sizeof(MAT_TASK(float)) == 128, "matrix_parallel_task_package size mismatch"); #endif -#pragma region matrix buffer operation function type - -typedef void(SN_DECL *BUF_PROC_AS)(mat_kernel *ans, scalar_pack *scalar, int count); -typedef void(SN_DECL *BUF_PROC_RAS)(mat_kernel *right, mat_kernel *ans, scalar_pack *scalar, - int count); -typedef void(SN_DECL *BUF_PROC_LRAS)(mat_kernel *left, mat_kernel *right, mat_kernel *ans, - scalar_pack *scalar, int count); -typedef void(SN_DECL *BUF_PROC_RA)(mat_kernel *right, mat_kernel *ans, int count); -typedef void(SN_DECL *BUF_PROC_LRA)(mat_kernel *left, mat_kernel *right, mat_kernel *ans, - int count); - -#define BUF_PROC(T_type, T_arch, T_op_name) T_type##_buf_##T_op_name##_##T_arch - -#define DECLARE_BUF_PROC_ANS_SCALAR(T_type, T_arch, T_op_name) \ - INTERNAL void SN_DECL BUF_PROC(T_type, T_arch, T_op_name)( \ - MAT_KERNEL(T_type) *restrict ans, scalar_pack const *scalar, size_t count) -#define DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(T_type, T_arch, T_op_name) \ - INTERNAL void SN_DECL BUF_PROC(T_type, T_arch, T_op_name)( \ - MAT_KERNEL(T_type) const *right, MAT_KERNEL(T_type) *restrict ans, \ - scalar_pack const *scalar, int count) -#define DECLARE_BUF_PROC_LEFT_RIGHT_ANS_SCALAR(T_type, T_arch, T_op_name) \ - INTERNAL void SN_DECL BUF_PROC(T_type, T_arch, T_op_name)( \ - MAT_KERNEL(T_type) const *left, MAT_KERNEL(T_type) const *right, \ - MAT_KERNEL(T_type) *restrict ans, scalar_pack const *scalar, size_t count) -#define DECLARE_BUF_PROC_RIGHT_ANS(T_type, T_arch, T_op_name) \ - INTERNAL void SN_DECL BUF_PROC(T_type, T_arch, T_op_name)( \ - MAT_KERNEL(T_type) const *right, MAT_KERNEL(T_type) *restrict ans, size_t count) -#define DECLARE_BUF_PROC_LEFT_RIGHT_ANS(T_type, T_arch, T_op_name) \ - INTERNAL void SN_DECL BUF_PROC(T_type, T_arch, T_op_name)( \ - MAT_KERNEL(T_type) const *left, MAT_KERNEL(T_type) const *right, \ - MAT_KERNEL(T_type) *restrict ans, size_t count) - -#pragma endregion - #pragma region matrix panel function type typedef void(SN_DECL *PANEL_PROC)(mat_panel *panel, mat_kernel *kernel, int col_length, @@ -176,6 +142,9 @@ typedef void(SN_DECL *KER_PROC_LAS)(mat_kernel *matrix, mat_kernel *ans, scalar_ #define KER_PROC(T_type, T_arch, T_op_name) T_type##_kernel_##T_op_name##_##T_arch +#define DECLARE_KER_PROC_ANS_SCALAR(T_type, T_arch, T_op_name) \ + INTERNAL void SN_DECL KER_PROC(T_type, T_arch, T_op_name)( \ + MAT_KERNEL(T_type) *restrict ans, scalar_pack const *scalar) #define DECLARE_KER_PROC_LEFT_RIGHT_ANS_SCALAR(T_type, T_arch, T_op_name) \ INTERNAL void SN_DECL KER_PROC(T_type, T_arch, T_op_name)( \ MAT_KERNEL(T_type) const *left, MAT_KERNEL(T_type) const *right, \ @@ -216,25 +185,25 @@ typedef uint64_t(SN_DECL *FACTORIALROC)(int n); INTERNAL void f32_normalize(VEC(float) * source, VEC(float) * target); -DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, sse, add); -DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, avx, add); -DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, 512, add); +DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, sse, add); +DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, add); +DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, 512, add); -DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, sse, sub); -DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, avx, sub); -DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, 512, sub); +DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, sse, sub); +DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, sub); +DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, 512, sub); DECLARE_KER_PROC_RIGHT_ANS(float, sse, transpose); DECLARE_KER_PROC_RIGHT_ANS(float, avx, transpose); DECLARE_KER_PROC_RIGHT_ANS(float, 512, transpose); -DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, sse, scalar_mul); -DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, avx, scalar_mul); -DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, 512, scalar_mul); +DECLARE_KER_PROC_RIGHT_ANS_SCALAR(float, sse, scalar_mul); +DECLARE_KER_PROC_RIGHT_ANS_SCALAR(float, avx, scalar_mul); +DECLARE_KER_PROC_RIGHT_ANS_SCALAR(float, 512, scalar_mul); -DECLARE_BUF_PROC_ANS_SCALAR(float, sse, fill); -DECLARE_BUF_PROC_ANS_SCALAR(float, avx, fill); -DECLARE_BUF_PROC_ANS_SCALAR(float, 512, fill); +DECLARE_KER_PROC_ANS_SCALAR(float, sse, fill); +DECLARE_KER_PROC_ANS_SCALAR(float, avx, fill); +DECLARE_KER_PROC_ANS_SCALAR(float, 512, fill); #pragma endregion @@ -280,6 +249,18 @@ INTERNAL int SN_DECL index_pair_sse(short const *str, uint32_t target, int lengt #pragma endregion +typedef struct sn_mat_enumerator { + int CurrentColumn; + int CurrentRow; + int KernelColumnLength; + int KernelRowLength; +} sn_mat_enumerator; + +typedef struct sn_mat_boarder { + int (*SN_DECL is_in_buffer)(int col, int row, sn_mat_enumerator *enumerator); + long (*SN_DECL get_index_offset)(int col, int row, sn_mat_enumerator *wnumerator); +} sn_mat_boarder; + // Mirrors C# IntrinsicContext field order so managed/unmanaged layouts stay in sync. typedef struct sn_intrinsic { HASH city_hash_simplify; diff --git a/StgSharp.Native/sn-src/k_bufop.c b/StgSharp.Native/sn-src/k_bufop.c deleted file mode 100644 index ce3d29ad..00000000 --- a/StgSharp.Native/sn-src/k_bufop.c +++ /dev/null @@ -1,134 +0,0 @@ -#include "sn_intrinsic.h" - -DECLARE_BUF_PROC_ANS_SCALAR(float, sse, fill) -{ - register __m128 vec = _mm_set_ps1(((float *)(scalar->data))[0]); - for (size_t i = 0; i < count; i++) { - ans[i].xmm[0] = vec; - ans[i].xmm[1] = vec; - ans[i].xmm[2] = vec; - ans[i].xmm[3] = vec; - } -} - -DECLARE_BUF_PROC_ANS_SCALAR(float, avx, fill) -{ - register __m256 vec = _mm256_broadcast_ss(((float *)(scalar->data))); - for (size_t i = 0; i < count; i++) { - ans[i].ymm[0] = vec; - ans[i].ymm[1] = vec; - } -} - -DECLARE_BUF_PROC_ANS_SCALAR(float, 512, fill) -{ - register __m512 vec = _mm512_broadcastss_ps(((__m128 *)(scalar->data))[0]); - for (size_t i = 0; i < count; i++) { - ans[i].zmm[0] = vec; - } -} - -DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, sse, add) -{ - for (size_t i = 0; i < count; i++) { - register __m128 c0 = _mm_add_ps(left[i].xmm[0], right[i].xmm[0]); - register __m128 c1 = _mm_add_ps(left[i].xmm[1], right[i].xmm[1]); - register __m128 c2 = _mm_add_ps(left[i].xmm[2], right[i].xmm[2]); - register __m128 c3 = _mm_add_ps(left[i].xmm[3], right[i].xmm[3]); - - ans[i].xmm[0] = c0; - ans[i].xmm[1] = c1; - ans[i].xmm[2] = c2; - ans[i].xmm[3] = c3; - } -} - -DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, avx, add) -{ - for (size_t i = 0; i < count; i++) { - size_t s = sizeof(MAT_KERNEL(float)); - register __m256 c0 = _mm256_add_ps(left[i].ymm[0], right[i].ymm[0]); - register __m256 c1 = _mm256_add_ps(left[i].ymm[1], right[i].ymm[1]); - ans[i].ymm[0] = c0; - ans[i].ymm[1] = c1; - } -} - -DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, 512, add) -{ - for (size_t i = 0; i < count; i++) { - register __m512 c0 = _mm512_add_ps(left[i].zmm[0], right[i].zmm[0]); - ans[i].zmm[0] = c0; - } -} - -DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, sse, sub) -{ - for (size_t i = 0; i < count; i++) { - register __m128 c0 = _mm_sub_ps(left[i].xmm[0], right[i].xmm[0]); - register __m128 c1 = _mm_sub_ps(left[i].xmm[1], right[i].xmm[1]); - register __m128 c2 = _mm_sub_ps(left[i].xmm[2], right[i].xmm[2]); - register __m128 c3 = _mm_sub_ps(left[i].xmm[3], right[i].xmm[3]); - - ans[i].xmm[0] = c0; - ans[i].xmm[1] = c1; - ans[i].xmm[2] = c2; - ans[i].xmm[3] = c3; - } -} - -DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, avx, sub) -{ - for (size_t i = 0; i < count; i++) { - register __m256 c0 = _mm256_sub_ps(left[i].ymm[0], right[i].ymm[0]); - register __m256 c1 = _mm256_sub_ps(left[i].ymm[1], right[i].ymm[1]); - ans[i].ymm[0] = c0; - ans[i].ymm[1] = c1; - } -} - -DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, 512, sub) -{ - for (size_t i = 0; i < count; i++) { - register __m512 c0 = _mm512_sub_ps(left[i].zmm[0], right[i].zmm[0]); - ans[i].zmm[0] = c0; - } -} - -DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, sse, scalar_mul) -{ - register __m128 vec = _mm_set_ps1(((float *)(scalar->data))[0]); - for (size_t i = 0; i < count; i++) { - register __m128 c0 = _mm_mul_ps(right[i].xmm[0], vec); - register __m128 c1 = _mm_mul_ps(right[i].xmm[1], vec); - register __m128 c2 = _mm_mul_ps(right[i].xmm[2], vec); - register __m128 c3 = _mm_mul_ps(right[i].xmm[3], vec); - - ans[i].xmm[0] = c0; - ans[i].xmm[1] = c1; - ans[i].xmm[2] = c2; - ans[i].xmm[3] = c3; - } -} - -DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, avx, scalar_mul) -{ - register __m256 vec = _mm256_broadcast_ss(((float *)(scalar->data))); - for (size_t i = 0; i < count; i++) { - register __m256 c0 = _mm256_mul_ps(right[i].ymm[0], vec); - register __m256 c1 = _mm256_mul_ps(right[i].ymm[1], vec); - - ans[i].ymm[0] = c0; - ans[i].ymm[1] = c1; - } -} - -DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, 512, scalar_mul) -{ - register __m512 vec = _mm512_broadcastss_ps(((__m128 *)(scalar->data))[0]); - for (size_t i = 0; i < count; i++) { - register __m512 c0 = _mm512_mul_ps(right[i].zmm[0], vec); - - ans[i].zmm[0] = c0; - } -} diff --git a/StgSharp.Native/sn-src/k_kerop.c b/StgSharp.Native/sn-src/k_kerop.c new file mode 100644 index 00000000..33a09bbb --- /dev/null +++ b/StgSharp.Native/sn-src/k_kerop.c @@ -0,0 +1,113 @@ +#include "sn_intrinsic.h" + +DECLARE_KER_PROC_ANS_SCALAR(float, sse, fill) +{ + register __m128 vec = _mm_set_ps1(((float *)(scalar->data))[0]); + ans->xmm[0] = vec; + ans->xmm[1] = vec; + ans->xmm[2] = vec; + ans->xmm[3] = vec; +} + +DECLARE_KER_PROC_ANS_SCALAR(float, avx, fill) +{ + register __m256 vec = _mm256_broadcast_ss(((float *)(scalar->data))); + ans->ymm[0] = vec; + ans->ymm[1] = vec; +} + +DECLARE_KER_PROC_ANS_SCALAR(float, 512, fill) +{ + register __m512 vec = _mm512_broadcastss_ps(((__m128 *)(scalar->data))[0]); + ans[i].zmm[0] = vec; +} + +DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, sse, add) +{ + register __m128 c0 = _mm_add_ps(left->xmm[0], right->xmm[0]); + register __m128 c1 = _mm_add_ps(left->xmm[1], right->xmm[1]); + register __m128 c2 = _mm_add_ps(left->xmm[2], right->xmm[2]); + register __m128 c3 = _mm_add_ps(left->xmm[3], right->xmm[3]); + + ans->xmm[0] = c0; + ans->xmm[1] = c1; + ans->xmm[2] = c2; + ans->xmm[3] = c3; +} + +DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, add) +{ + register __m256 c0 = _mm256_add_ps(left->ymm[0], right->ymm[0]); + register __m256 c1 = _mm256_add_ps(left->ymm[1], right->ymm[1]); + ans->ymm[0] = c0; + ans->ymm[1] = c1; +} + +DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, 512, add) +{ + register __m512 c0 = _mm512_add_ps(left->zmm[0], right->zmm[0]); + ans->zmm[0] = c0; +} + +DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, sse, sub) +{ + register __m128 c0 = _mm_sub_ps(left->xmm[0], right->xmm[0]); + register __m128 c1 = _mm_sub_ps(left->xmm[1], right->xmm[1]); + register __m128 c2 = _mm_sub_ps(left->xmm[2], right->xmm[2]); + register __m128 c3 = _mm_sub_ps(left->xmm[3], right->xmm[3]); + + ans->xmm[0] = c0; + ans->xmm[1] = c1; + ans->xmm[2] = c2; + ans->xmm[3] = c3; +} + +DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, sub) +{ + register __m256 c0 = _mm256_sub_ps(left->ymm[0], right->ymm[0]); + register __m256 c1 = _mm256_sub_ps(left->ymm[1], right->ymm[1]); + ans->ymm[0] = c0; + ans->ymm[1] = c1; +} + +DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, 512, sub) +{ + register __m512 c0 = _mm512_sub_ps(left->zmm[0], right->zmm[0]); + ans->zmm[0] = c0; +} + +DECLARE_KER_PROC_RIGHT_ANS_SCALAR(float, sse, scalar_mul) +{ + register __m128 vec = _mm_set_ps1(((float *)(scalar->data))[0]); + register __m128 c0 = _mm_mul_ps(right->xmm[0], vec); + register __m128 c1 = _mm_mul_ps(right->xmm[1], vec); + register __m128 c2 = _mm_mul_ps(right->xmm[2], vec); + register __m128 c3 = _mm_mul_ps(right->xmm[3], vec); + + ans->xmm[0] = c0; + ans->xmm[1] = c1; + ans->xmm[2] = c2; + ans->xmm[3] = c3; +} + +DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, avx, scalar_mul) +{ + register __m256 vec = _mm256_broadcast_ss(((float *)(scalar->data))); + for (size_t i = 0; i < count; i++) { + register __m256 c0 = _mm256_mul_ps(right[i].ymm[0], vec); + register __m256 c1 = _mm256_mul_ps(right[i].ymm[1], vec); + + ans[i].ymm[0] = c0; + ans[i].ymm[1] = c1; + } +} + +DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, 512, scalar_mul) +{ + register __m512 vec = _mm512_broadcastss_ps(((__m128 *)(scalar->data))[0]); + for (size_t i = 0; i < count; i++) { + register __m512 c0 = _mm512_mul_ps(right[i].zmm[0], vec); + + ans[i].zmm[0] = c0; + } +} diff --git a/StgSharpDebug/Program.cs b/StgSharpDebug/Program.cs index bbae7ad6..b1309fbb 100644 --- a/StgSharpDebug/Program.cs +++ b/StgSharpDebug/Program.cs @@ -58,11 +58,11 @@ namespace StgSharp unchecked { hlsf = new((nuint)(64 * (ulong)10000 * 10000)); } - Matrix m = Matrix.FromHlsf(4000, 4000, hlsf); + Matrix m = Matrix.Create(4000, 4000, MatrixLayout.DenseSquare, hlsf); MatrixCompute.Fill(m, 1.0f); - Matrix n = Matrix.FromHlsf(4000, 4000, hlsf); + Matrix n = Matrix.Create(4000, 4000, MatrixLayout.DenseSquare, hlsf); MatrixCompute.Fill(n, 1.0f); - Matrix p = Matrix.FromHlsf(4000, 4000, hlsf); + Matrix p = Matrix.Create(4000, 4000, MatrixLayout.DenseSquare, hlsf); // MatrixCompute.Fill(p, 0.0f); /* From 3b3a90a2aff272b7a592e841f1f07a4a1e5ea5d0 Mon Sep 17 00:00:00 2001 From: Youmu Liu <105042599+Nitload-NSI@users.noreply.github.com> Date: Wed, 24 Dec 2025 18:09:16 +0800 Subject: [PATCH 3/3] keep working on PLN facotrize --- .../Mathematics/Linear/Matrix.Create.cs | 16 +- StgSharp.Common/Mathematics/Linear/Matrix.cs | 50 +++- .../Mathematics/Linear/MatrixMetadata.cs | 244 +++++++++--------- .../Numeric/MatrixCompute.Factorize.cs | 56 +++- StgSharp.Mathematics/Numeric/MatrixCompute.cs | 9 + StgSharp.Native/StgSharp.Native.vcxproj | 2 +- .../StgSharp.Native.vcxproj.filters | 2 +- StgSharp.Native/sn-head/sn_intrinsic.h | 73 ++++-- StgSharp.Native/sn-src/k_bufop.c | 134 ++++++++++ StgSharp.Native/sn-src/k_kerop.c | 113 -------- StgSharpDebug/Program.cs | 6 +- StgSharpDevelop.sln | 28 +- 12 files changed, 428 insertions(+), 305 deletions(-) create mode 100644 StgSharp.Native/sn-src/k_bufop.c delete mode 100644 StgSharp.Native/sn-src/k_kerop.c diff --git a/StgSharp.Common/Mathematics/Linear/Matrix.Create.cs b/StgSharp.Common/Mathematics/Linear/Matrix.Create.cs index 4aad5110..507672d5 100644 --- a/StgSharp.Common/Mathematics/Linear/Matrix.Create.cs +++ b/StgSharp.Common/Mathematics/Linear/Matrix.Create.cs @@ -65,7 +65,7 @@ namespace StgSharp.Mathematics.Numeric long kernelCount = layout switch { - MatrixLayout.DenseSquare => (long)kernelColumns * kernelRows, + MatrixLayout.DenseRectangle => (long)kernelColumns * kernelRows, MatrixLayout.UpperTriangle => TriangularKernelCount(kernelColumns), MatrixLayout.LowerTriangle => TriangularKernelCount(kernelRows), _ => throw new ArgumentOutOfRangeException(nameof(layout)) @@ -79,16 +79,10 @@ namespace StgSharp.Mathematics.Numeric HybridLayerSegregatedFitAllocationHandle handle = allocator.Alloc((uint)requiredBytes); MatrixStorageHLSF storage = new MatrixStorageHLSF(allocator, handle); - Matrix matrix = new Matrix - { - Layout = layout, - KernelColumnLength = kernelColumns, - KernelRowLength = kernelRows, - }; - - matrix._buffer = storage; - matrix._boarder = MatrixKernelBoarder.Create(layout); - matrix._size = new MatrixSize(columnLength, rowLength, kernelColumns, kernelRows); + Matrix matrix = new Matrix(MatrixKernelBoarder.Create(layout), new MatrixSize(columnLength, + rowLength, + kernelColumns, + kernelRows), storage); return matrix; } diff --git a/StgSharp.Common/Mathematics/Linear/Matrix.cs b/StgSharp.Common/Mathematics/Linear/Matrix.cs index f356cca5..26bfd118 100644 --- a/StgSharp.Common/Mathematics/Linear/Matrix.cs +++ b/StgSharp.Common/Mathematics/Linear/Matrix.cs @@ -41,11 +41,21 @@ namespace StgSharp.Mathematics.Numeric private protected static readonly int t_count = 16 / sizeof(T); private protected static readonly int t_size = sizeof(T); - private MatrixKernelBoarder _boarder; - private MatrixSize _size; - private MatrixStorage _buffer; + private readonly MatrixKernelBoarder _boarder; + private readonly MatrixSize _size; + private readonly MatrixStorage _buffer; - private protected Matrix() { } + private protected Matrix( + MatrixKernelBoarder boarder, + MatrixSize size, + MatrixStorage buffer + + ) + { + _boarder = boarder; + _size = size; + _buffer = buffer; + } public T this[int x, int y] { @@ -122,19 +132,33 @@ namespace StgSharp.Mathematics.Numeric get => (MatrixKernel*)_buffer.BufferPointer; } - protected internal int KernelColumnLength { get; init; } + protected internal int KernelColumnLength => _size.KernelColumnLength; - protected internal int KernelRowLength { get; init; } + protected internal int KernelRowLength => _size.KernelRowLength; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe ref MatrixKernel GetMatrixKernel(int x, int y) { - fixed (MatrixSize *msPtr = &_size) - { - MatrixKernelEnumerator* e = (MatrixKernelEnumerator*)msPtr; - return ref _boarder.IsInBuffer(x, y, e) ? - ref _buffer[_boarder.GetIndexOffset(x, y, e)] : - ref Unsafe.NullRef>(); - } + MatrixKernelEnumerator enumerator = new(_size.KernelColumnLength, _size.KernelRowLength, + x, y); + return ref _boarder.IsInBuffer(x, y, in enumerator) ? + ref _buffer[_boarder.GetIndexOffset(x, y, in enumerator)] : + ref Unsafe.NullRef>(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal unsafe ref T GetElementUnsafe(int x, int y) + { + // Caller guarantees: indices in range, layout is dense square. + int k_c = y >> 2; + int k_r = x >> 2; + int c = y & 3; + int r = x & 3; + + MatrixKernelEnumerator enumerator = new(_size.KernelColumnLength, _size.KernelRowLength, + k_c, k_r); + ref MatrixKernel kernel = ref _buffer[_boarder.GetIndexOffset(k_c, k_r, in enumerator)]; + return ref kernel[c, r]; } } diff --git a/StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs b/StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs index abd6c632..253710cd 100644 --- a/StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs +++ b/StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs @@ -25,169 +25,159 @@ // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- -using StgSharp.HighPerformance; using System; -using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; namespace StgSharp.Mathematics.Numeric { public enum MatrixLayout { - DenseSquare, + DenseRectangle, UpperTriangle, LowerTriangle, } - [StructLayout(LayoutKind.Sequential)] - public unsafe struct MatrixKernelBoarder + public abstract class MatrixKernelBoarder { - public readonly delegate* unmanaged[Cdecl] - GetIndexOffset; - - public readonly delegate* unmanaged[Cdecl] IsInBuffer; - - [Obsolete("Do not use constructor, use static method instead", true)] - public MatrixKernelBoarder() { } - - public MatrixKernelBoarder( - delegate* unmanaged[Cdecl] - getOffset, - delegate* unmanaged[Cdecl] inBuffer) - { - GetIndexOffset = getOffset; - IsInBuffer = inBuffer; - } - - private static delegate* unmanaged[Cdecl] GetIndexOffsetDenseSquarePtr { get; } = - (delegate* unmanaged[Cdecl])&GetIndexOffsetDenseSquare; - - private static delegate* unmanaged[Cdecl] GetIndexOffsetUpperTrianglePtr { get; } = - (delegate* unmanaged[Cdecl])&GetIndexOffsetUpperTriangle; - - private static delegate* unmanaged[Cdecl] GetIndexOffsetLowerTrianglePtr { get; } = - (delegate* unmanaged[Cdecl])&GetIndexOffsetLowerTriangle; - - private static delegate* unmanaged[Cdecl] IsInBufferDenseSquarePtr { get; } = - (delegate* unmanaged[Cdecl])&IsInBufferDenseSquare; - - private static delegate* unmanaged[Cdecl] IsInBufferUpperTrianglePtr { get; } = - (delegate* unmanaged[Cdecl])&IsInBufferUpperTriangle; - - private static delegate* unmanaged[Cdecl] IsInBufferLowerTrianglePtr { get; } = - (delegate* unmanaged[Cdecl])&IsInBufferLowerTriangle; + private static readonly MatrixKernelBoarder DenseSquareInstance = new DenseSquareKernelBoarder(); + private static readonly MatrixKernelBoarder LowerTriangleInstance = new LowerTriangleKernelBoarder(); + private static readonly MatrixKernelBoarder UpperTriangleInstance = new UpperTriangleKernelBoarder(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static MatrixKernelBoarder Create(MatrixLayout layout) { return layout switch { - MatrixLayout.DenseSquare => new MatrixKernelBoarder(GetIndexOffsetDenseSquarePtr, IsInBufferDenseSquarePtr), - - MatrixLayout.UpperTriangle => new MatrixKernelBoarder(GetIndexOffsetUpperTrianglePtr, IsInBufferUpperTrianglePtr), - MatrixLayout.LowerTriangle => new MatrixKernelBoarder(GetIndexOffsetLowerTrianglePtr, IsInBufferLowerTrianglePtr), + MatrixLayout.DenseRectangle => DenseSquareInstance, + MatrixLayout.UpperTriangle => UpperTriangleInstance, + MatrixLayout.LowerTriangle => LowerTriangleInstance, _ => throw new ArgumentOutOfRangeException(nameof(layout)), }; } - [UnmanagedCallersOnly(CallConvs =[ typeof(CallConvCdecl) ])] - private static long GetIndexOffsetDenseSquare( - int x_kernel, - int y_kernel, - MatrixKernelEnumerator* enumerator) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public abstract long GetIndexOffset( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public abstract bool IsInBuffer( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected static long GetTriangularOrder(in MatrixKernelEnumerator enumerator) { - long x = x_kernel; - long y = y_kernel; - long rows = enumerator->KernelRowLength; - return x * rows + y; + return Math.Min(enumerator.KernelColumnLength, enumerator.KernelRowLength); } - [UnmanagedCallersOnly(CallConvs =[ typeof(CallConvCdecl) ])] - private static long GetIndexOffsetLowerTriangle( - int x_kernel, - int y_kernel, - MatrixKernelEnumerator* enumerator) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected static bool IsWithinKernelDomain( + in MatrixKernelEnumerator enumerator, + int xKernel, + int yKernel) + { + return xKernel >= 0 && + yKernel >= 0 && + xKernel < enumerator.KernelColumnLength && + yKernel < enumerator.KernelRowLength; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected static bool IsWithinTriangularDomain( + in MatrixKernelEnumerator enumerator, + int xKernel, + int yKernel) { long order = GetTriangularOrder(enumerator); - long x = x_kernel; - long y = y_kernel; - - long prefixColumns = x * order - (x * (x - 1L)) / 2L; - return prefixColumns + (y - x); + return xKernel >= 0 && yKernel >= 0 && xKernel < order && yKernel < order; } - [UnmanagedCallersOnly(CallConvs =[ typeof(CallConvCdecl) ])] - private static long GetIndexOffsetUpperTriangle( - int x_kernel, - int y_kernel, - MatrixKernelEnumerator* enumerator) + private sealed class DenseSquareKernelBoarder : MatrixKernelBoarder { - long x = x_kernel; - long y = y_kernel; - long prefixColumns = (x * (x + 1L)) / 2L; - return prefixColumns + y; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override long GetIndexOffset( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator) + { + long x = xKernel; + long y = yKernel; + long rows = enumerator.KernelRowLength; + return x * rows + y; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override bool IsInBuffer( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator) + { + return IsWithinKernelDomain(enumerator, xKernel, yKernel); + } + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static long GetTriangularOrder(MatrixKernelEnumerator* enumerator) + private sealed class LowerTriangleKernelBoarder : MatrixKernelBoarder { - return Math.Min(enumerator->KernelColumnLength, enumerator->KernelRowLength); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override long GetIndexOffset( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator) + { + long order = GetTriangularOrder(enumerator); + long x = xKernel; + long y = yKernel; + + long prefixColumns = x * order - (x * (x - 1L)) / 2L; + return prefixColumns + (y - x); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override bool IsInBuffer( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator) + { + return IsWithinTriangularDomain(enumerator, xKernel, yKernel) && yKernel >= xKernel; + } + } - [UnmanagedCallersOnly(CallConvs =[ typeof(CallConvCdecl) ])] - private static bool IsInBufferDenseSquare( - int x_kernel, - int y_kernel, - MatrixKernelEnumerator* enumerator) + private sealed unsafe class UpperTriangleKernelBoarder : MatrixKernelBoarder { - return IsWithinKernelDomain(enumerator, x_kernel, y_kernel); - } - [UnmanagedCallersOnly(CallConvs =[ typeof(CallConvCdecl) ])] - private static bool IsInBufferLowerTriangle( - int x_kernel, - int y_kernel, - MatrixKernelEnumerator* enumerator) - { - return IsWithinTriangularDomain(enumerator, x_kernel, y_kernel) && y_kernel >= x_kernel; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override long GetIndexOffset( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator) + { + long x = xKernel; + long y = yKernel; - [UnmanagedCallersOnly(CallConvs =[ typeof(CallConvCdecl) ])] - private static bool IsInBufferUpperTriangle( - int x_kernel, - int y_kernel, - MatrixKernelEnumerator* enumerator) - { - return IsWithinTriangularDomain(enumerator, x_kernel, y_kernel) && y_kernel <= x_kernel; - } + long prefixColumns = (x * (x + 1L)) / 2L; + return prefixColumns + y; + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool IsWithinKernelDomain( - MatrixKernelEnumerator* enumerator, - int x_kernel, - int y_kernel) - { - return x_kernel >= 0 && - y_kernel >= 0 && - x_kernel < enumerator->KernelColumnLength && - y_kernel < enumerator->KernelRowLength; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override bool IsInBuffer( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator) + { + return IsWithinTriangularDomain(enumerator, xKernel, yKernel) && yKernel <= xKernel; + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool IsWithinTriangularDomain( - MatrixKernelEnumerator* enumerator, - int x_kernel, - int y_kernel) - { - long order = GetTriangularOrder(enumerator); - return x_kernel >= 0 && y_kernel >= 0 && x_kernel < order && y_kernel < order; } } @@ -202,6 +192,7 @@ namespace StgSharp.Mathematics.Numeric [FieldOffset(8)] public readonly int KernelColumnLength; [FieldOffset(12)] public readonly int KernelRowLength; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public MatrixSize( int elementColumnLength, int elementRowLength, @@ -223,8 +214,21 @@ namespace StgSharp.Mathematics.Numeric [FieldOffset(0)] public int CurrentColumn; [FieldOffset(4)] public int CurrentRow; - [FieldOffset(8)] public readonly int KernelColumnLength; + [FieldOffset(8)] public readonly int KernelColumnLength; [FieldOffset(12)] public readonly int KernelRowLength; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public MatrixKernelEnumerator( + int kernelColumnLength, + int kernelRowLength, + int currentColumn = 0, + int currentRow = 0) + { + CurrentColumn = currentColumn; + CurrentRow = currentRow; + KernelColumnLength = kernelColumnLength; + KernelRowLength = kernelRowLength; + } + } } diff --git a/StgSharp.Mathematics/Numeric/MatrixCompute.Factorize.cs b/StgSharp.Mathematics/Numeric/MatrixCompute.Factorize.cs index c2b8d787..bc4a4d1c 100644 --- a/StgSharp.Mathematics/Numeric/MatrixCompute.Factorize.cs +++ b/StgSharp.Mathematics/Numeric/MatrixCompute.Factorize.cs @@ -38,17 +38,69 @@ namespace StgSharp.Mathematics.Numeric public static void FactorizePLU( Matrix matrix, - Span p, + Span pivot, Matrix lower, Matrix upper) { if (matrix.ColumnLength != matrix.RowLength) { throw new InvalidOperationException("Matrix must be square."); } + if (matrix.Layout != MatrixLayout.DenseRectangle) { + throw new NotSupportedException("Only dense square matrices are supported."); + } + int n = matrix.RowLength; + if (pivot.Length < n) { + throw new ArgumentException("Pivot span length is insufficient.", nameof(pivot)); + } + if (lower.RowLength != n || + lower.ColumnLength != n || + lower.Layout != MatrixLayout.LowerTriangle) { + throw new ArgumentException("Lower matrix must be lower-triangular with same dimensions as input.", nameof(lower)); + } + if (upper.RowLength != n || + upper.ColumnLength != n || + upper.Layout != MatrixLayout.UpperTriangle) { + throw new ArgumentException("Upper matrix must be upper-triangular with same dimensions as input.", nameof(upper)); + } + int size = matrix.KernelColumnLength * matrix.KernelRowLength; if (size < 256) { - for (int i = 0; i < matrix.KernelColumnLength; i++) { } + // 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 + } + + for (int k = 0; k < n; k++) + { + // 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[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 demonstration PLU."); + } + lower[i, k] = (matrix.GetElementUnsafe(i, k) - sum) / u; + } + } + + // TODO: For larger kernels, consider calling native pivot helper to extract 4 pivots at once. } else if (size < 1024) { } else { } } diff --git a/StgSharp.Mathematics/Numeric/MatrixCompute.cs b/StgSharp.Mathematics/Numeric/MatrixCompute.cs index 587df5c4..0c99c154 100644 --- a/StgSharp.Mathematics/Numeric/MatrixCompute.cs +++ b/StgSharp.Mathematics/Numeric/MatrixCompute.cs @@ -200,6 +200,10 @@ namespace StgSharp.Mathematics.Numeric if (left.ColumnLength != ans.ColumnLength || left.RowLength != ans.RowLength) { throw new IndexOutOfRangeException("Matrix dimensions must agree."); } + if (left.Layout != MatrixLayout.DenseRectangle || + ans.Layout != MatrixLayout.DenseRectangle) { + throw new NotSupportedException("Only dense rectangle matrices are supported."); + } long count = (long)left.KernelColumnLength * left.KernelRowLength; ScalarPacket* scalar = MatrixParallelFactory.CreateScalarPacket(); scalar->Data(0) = right; @@ -246,6 +250,11 @@ namespace StgSharp.Mathematics.Numeric left.RowLength != ans.RowLength) { throw new IndexOutOfRangeException("Matrix dimensions must agree."); } + if (left.Layout != MatrixLayout.DenseRectangle || + right.Layout != MatrixLayout.DenseRectangle || + ans.Layout != MatrixLayout.DenseRectangle) { + throw new NotSupportedException("Only dense rectangle matrices are supported."); + } long count = (long)left.KernelColumnLength * left.KernelRowLength; if (count <= 256) { diff --git a/StgSharp.Native/StgSharp.Native.vcxproj b/StgSharp.Native/StgSharp.Native.vcxproj index a9c77499..2858b025 100644 --- a/StgSharp.Native/StgSharp.Native.vcxproj +++ b/StgSharp.Native/StgSharp.Native.vcxproj @@ -151,7 +151,7 @@ - + diff --git a/StgSharp.Native/StgSharp.Native.vcxproj.filters b/StgSharp.Native/StgSharp.Native.vcxproj.filters index d9beed83..8161ef1c 100644 --- a/StgSharp.Native/StgSharp.Native.vcxproj.filters +++ b/StgSharp.Native/StgSharp.Native.vcxproj.filters @@ -48,7 +48,7 @@ 源文件 - + 源文件 diff --git a/StgSharp.Native/sn-head/sn_intrinsic.h b/StgSharp.Native/sn-head/sn_intrinsic.h index 142d5c92..8ba80fc4 100644 --- a/StgSharp.Native/sn-head/sn_intrinsic.h +++ b/StgSharp.Native/sn-head/sn_intrinsic.h @@ -96,6 +96,40 @@ static_assert(sizeof(matrix_task) == 128, "matrix_parallel_task_package size mis _Static_assert(sizeof(MAT_TASK(float)) == 128, "matrix_parallel_task_package size mismatch"); #endif +#pragma region matrix buffer operation function type + +typedef void(SN_DECL *BUF_PROC_AS)(mat_kernel *ans, scalar_pack *scalar, int count); +typedef void(SN_DECL *BUF_PROC_RAS)(mat_kernel *right, mat_kernel *ans, scalar_pack *scalar, + int count); +typedef void(SN_DECL *BUF_PROC_LRAS)(mat_kernel *left, mat_kernel *right, mat_kernel *ans, + scalar_pack *scalar, int count); +typedef void(SN_DECL *BUF_PROC_RA)(mat_kernel *right, mat_kernel *ans, int count); +typedef void(SN_DECL *BUF_PROC_LRA)(mat_kernel *left, mat_kernel *right, mat_kernel *ans, + int count); + +#define BUF_PROC(T_type, T_arch, T_op_name) T_type##_buf_##T_op_name##_##T_arch + +#define DECLARE_BUF_PROC_ANS_SCALAR(T_type, T_arch, T_op_name) \ + INTERNAL void SN_DECL BUF_PROC(T_type, T_arch, T_op_name)( \ + MAT_KERNEL(T_type) *restrict ans, scalar_pack const *scalar, size_t count) +#define DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(T_type, T_arch, T_op_name) \ + INTERNAL void SN_DECL BUF_PROC(T_type, T_arch, T_op_name)( \ + MAT_KERNEL(T_type) const *right, MAT_KERNEL(T_type) *restrict ans, \ + scalar_pack const *scalar, int count) +#define DECLARE_BUF_PROC_LEFT_RIGHT_ANS_SCALAR(T_type, T_arch, T_op_name) \ + INTERNAL void SN_DECL BUF_PROC(T_type, T_arch, T_op_name)( \ + MAT_KERNEL(T_type) const *left, MAT_KERNEL(T_type) const *right, \ + MAT_KERNEL(T_type) *restrict ans, scalar_pack const *scalar, size_t count) +#define DECLARE_BUF_PROC_RIGHT_ANS(T_type, T_arch, T_op_name) \ + INTERNAL void SN_DECL BUF_PROC(T_type, T_arch, T_op_name)( \ + MAT_KERNEL(T_type) const *right, MAT_KERNEL(T_type) *restrict ans, size_t count) +#define DECLARE_BUF_PROC_LEFT_RIGHT_ANS(T_type, T_arch, T_op_name) \ + INTERNAL void SN_DECL BUF_PROC(T_type, T_arch, T_op_name)( \ + MAT_KERNEL(T_type) const *left, MAT_KERNEL(T_type) const *right, \ + MAT_KERNEL(T_type) *restrict ans, size_t count) + +#pragma endregion + #pragma region matrix panel function type typedef void(SN_DECL *PANEL_PROC)(mat_panel *panel, mat_kernel *kernel, int col_length, @@ -142,9 +176,6 @@ typedef void(SN_DECL *KER_PROC_LAS)(mat_kernel *matrix, mat_kernel *ans, scalar_ #define KER_PROC(T_type, T_arch, T_op_name) T_type##_kernel_##T_op_name##_##T_arch -#define DECLARE_KER_PROC_ANS_SCALAR(T_type, T_arch, T_op_name) \ - INTERNAL void SN_DECL KER_PROC(T_type, T_arch, T_op_name)( \ - MAT_KERNEL(T_type) *restrict ans, scalar_pack const *scalar) #define DECLARE_KER_PROC_LEFT_RIGHT_ANS_SCALAR(T_type, T_arch, T_op_name) \ INTERNAL void SN_DECL KER_PROC(T_type, T_arch, T_op_name)( \ MAT_KERNEL(T_type) const *left, MAT_KERNEL(T_type) const *right, \ @@ -185,25 +216,25 @@ typedef uint64_t(SN_DECL *FACTORIALROC)(int n); INTERNAL void f32_normalize(VEC(float) * source, VEC(float) * target); -DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, sse, add); -DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, add); -DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, 512, add); +DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, sse, add); +DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, avx, add); +DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, 512, add); -DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, sse, sub); -DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, sub); -DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, 512, sub); +DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, sse, sub); +DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, avx, sub); +DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, 512, sub); DECLARE_KER_PROC_RIGHT_ANS(float, sse, transpose); DECLARE_KER_PROC_RIGHT_ANS(float, avx, transpose); DECLARE_KER_PROC_RIGHT_ANS(float, 512, transpose); -DECLARE_KER_PROC_RIGHT_ANS_SCALAR(float, sse, scalar_mul); -DECLARE_KER_PROC_RIGHT_ANS_SCALAR(float, avx, scalar_mul); -DECLARE_KER_PROC_RIGHT_ANS_SCALAR(float, 512, scalar_mul); +DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, sse, scalar_mul); +DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, avx, scalar_mul); +DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, 512, scalar_mul); -DECLARE_KER_PROC_ANS_SCALAR(float, sse, fill); -DECLARE_KER_PROC_ANS_SCALAR(float, avx, fill); -DECLARE_KER_PROC_ANS_SCALAR(float, 512, fill); +DECLARE_BUF_PROC_ANS_SCALAR(float, sse, fill); +DECLARE_BUF_PROC_ANS_SCALAR(float, avx, fill); +DECLARE_BUF_PROC_ANS_SCALAR(float, 512, fill); #pragma endregion @@ -249,18 +280,6 @@ INTERNAL int SN_DECL index_pair_sse(short const *str, uint32_t target, int lengt #pragma endregion -typedef struct sn_mat_enumerator { - int CurrentColumn; - int CurrentRow; - int KernelColumnLength; - int KernelRowLength; -} sn_mat_enumerator; - -typedef struct sn_mat_boarder { - int (*SN_DECL is_in_buffer)(int col, int row, sn_mat_enumerator *enumerator); - long (*SN_DECL get_index_offset)(int col, int row, sn_mat_enumerator *wnumerator); -} sn_mat_boarder; - // Mirrors C# IntrinsicContext field order so managed/unmanaged layouts stay in sync. typedef struct sn_intrinsic { HASH city_hash_simplify; diff --git a/StgSharp.Native/sn-src/k_bufop.c b/StgSharp.Native/sn-src/k_bufop.c new file mode 100644 index 00000000..ce3d29ad --- /dev/null +++ b/StgSharp.Native/sn-src/k_bufop.c @@ -0,0 +1,134 @@ +#include "sn_intrinsic.h" + +DECLARE_BUF_PROC_ANS_SCALAR(float, sse, fill) +{ + register __m128 vec = _mm_set_ps1(((float *)(scalar->data))[0]); + for (size_t i = 0; i < count; i++) { + ans[i].xmm[0] = vec; + ans[i].xmm[1] = vec; + ans[i].xmm[2] = vec; + ans[i].xmm[3] = vec; + } +} + +DECLARE_BUF_PROC_ANS_SCALAR(float, avx, fill) +{ + register __m256 vec = _mm256_broadcast_ss(((float *)(scalar->data))); + for (size_t i = 0; i < count; i++) { + ans[i].ymm[0] = vec; + ans[i].ymm[1] = vec; + } +} + +DECLARE_BUF_PROC_ANS_SCALAR(float, 512, fill) +{ + register __m512 vec = _mm512_broadcastss_ps(((__m128 *)(scalar->data))[0]); + for (size_t i = 0; i < count; i++) { + ans[i].zmm[0] = vec; + } +} + +DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, sse, add) +{ + for (size_t i = 0; i < count; i++) { + register __m128 c0 = _mm_add_ps(left[i].xmm[0], right[i].xmm[0]); + register __m128 c1 = _mm_add_ps(left[i].xmm[1], right[i].xmm[1]); + register __m128 c2 = _mm_add_ps(left[i].xmm[2], right[i].xmm[2]); + register __m128 c3 = _mm_add_ps(left[i].xmm[3], right[i].xmm[3]); + + ans[i].xmm[0] = c0; + ans[i].xmm[1] = c1; + ans[i].xmm[2] = c2; + ans[i].xmm[3] = c3; + } +} + +DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, avx, add) +{ + for (size_t i = 0; i < count; i++) { + size_t s = sizeof(MAT_KERNEL(float)); + register __m256 c0 = _mm256_add_ps(left[i].ymm[0], right[i].ymm[0]); + register __m256 c1 = _mm256_add_ps(left[i].ymm[1], right[i].ymm[1]); + ans[i].ymm[0] = c0; + ans[i].ymm[1] = c1; + } +} + +DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, 512, add) +{ + for (size_t i = 0; i < count; i++) { + register __m512 c0 = _mm512_add_ps(left[i].zmm[0], right[i].zmm[0]); + ans[i].zmm[0] = c0; + } +} + +DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, sse, sub) +{ + for (size_t i = 0; i < count; i++) { + register __m128 c0 = _mm_sub_ps(left[i].xmm[0], right[i].xmm[0]); + register __m128 c1 = _mm_sub_ps(left[i].xmm[1], right[i].xmm[1]); + register __m128 c2 = _mm_sub_ps(left[i].xmm[2], right[i].xmm[2]); + register __m128 c3 = _mm_sub_ps(left[i].xmm[3], right[i].xmm[3]); + + ans[i].xmm[0] = c0; + ans[i].xmm[1] = c1; + ans[i].xmm[2] = c2; + ans[i].xmm[3] = c3; + } +} + +DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, avx, sub) +{ + for (size_t i = 0; i < count; i++) { + register __m256 c0 = _mm256_sub_ps(left[i].ymm[0], right[i].ymm[0]); + register __m256 c1 = _mm256_sub_ps(left[i].ymm[1], right[i].ymm[1]); + ans[i].ymm[0] = c0; + ans[i].ymm[1] = c1; + } +} + +DECLARE_BUF_PROC_LEFT_RIGHT_ANS(float, 512, sub) +{ + for (size_t i = 0; i < count; i++) { + register __m512 c0 = _mm512_sub_ps(left[i].zmm[0], right[i].zmm[0]); + ans[i].zmm[0] = c0; + } +} + +DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, sse, scalar_mul) +{ + register __m128 vec = _mm_set_ps1(((float *)(scalar->data))[0]); + for (size_t i = 0; i < count; i++) { + register __m128 c0 = _mm_mul_ps(right[i].xmm[0], vec); + register __m128 c1 = _mm_mul_ps(right[i].xmm[1], vec); + register __m128 c2 = _mm_mul_ps(right[i].xmm[2], vec); + register __m128 c3 = _mm_mul_ps(right[i].xmm[3], vec); + + ans[i].xmm[0] = c0; + ans[i].xmm[1] = c1; + ans[i].xmm[2] = c2; + ans[i].xmm[3] = c3; + } +} + +DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, avx, scalar_mul) +{ + register __m256 vec = _mm256_broadcast_ss(((float *)(scalar->data))); + for (size_t i = 0; i < count; i++) { + register __m256 c0 = _mm256_mul_ps(right[i].ymm[0], vec); + register __m256 c1 = _mm256_mul_ps(right[i].ymm[1], vec); + + ans[i].ymm[0] = c0; + ans[i].ymm[1] = c1; + } +} + +DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, 512, scalar_mul) +{ + register __m512 vec = _mm512_broadcastss_ps(((__m128 *)(scalar->data))[0]); + for (size_t i = 0; i < count; i++) { + register __m512 c0 = _mm512_mul_ps(right[i].zmm[0], vec); + + ans[i].zmm[0] = c0; + } +} diff --git a/StgSharp.Native/sn-src/k_kerop.c b/StgSharp.Native/sn-src/k_kerop.c deleted file mode 100644 index 33a09bbb..00000000 --- a/StgSharp.Native/sn-src/k_kerop.c +++ /dev/null @@ -1,113 +0,0 @@ -#include "sn_intrinsic.h" - -DECLARE_KER_PROC_ANS_SCALAR(float, sse, fill) -{ - register __m128 vec = _mm_set_ps1(((float *)(scalar->data))[0]); - ans->xmm[0] = vec; - ans->xmm[1] = vec; - ans->xmm[2] = vec; - ans->xmm[3] = vec; -} - -DECLARE_KER_PROC_ANS_SCALAR(float, avx, fill) -{ - register __m256 vec = _mm256_broadcast_ss(((float *)(scalar->data))); - ans->ymm[0] = vec; - ans->ymm[1] = vec; -} - -DECLARE_KER_PROC_ANS_SCALAR(float, 512, fill) -{ - register __m512 vec = _mm512_broadcastss_ps(((__m128 *)(scalar->data))[0]); - ans[i].zmm[0] = vec; -} - -DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, sse, add) -{ - register __m128 c0 = _mm_add_ps(left->xmm[0], right->xmm[0]); - register __m128 c1 = _mm_add_ps(left->xmm[1], right->xmm[1]); - register __m128 c2 = _mm_add_ps(left->xmm[2], right->xmm[2]); - register __m128 c3 = _mm_add_ps(left->xmm[3], right->xmm[3]); - - ans->xmm[0] = c0; - ans->xmm[1] = c1; - ans->xmm[2] = c2; - ans->xmm[3] = c3; -} - -DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, add) -{ - register __m256 c0 = _mm256_add_ps(left->ymm[0], right->ymm[0]); - register __m256 c1 = _mm256_add_ps(left->ymm[1], right->ymm[1]); - ans->ymm[0] = c0; - ans->ymm[1] = c1; -} - -DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, 512, add) -{ - register __m512 c0 = _mm512_add_ps(left->zmm[0], right->zmm[0]); - ans->zmm[0] = c0; -} - -DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, sse, sub) -{ - register __m128 c0 = _mm_sub_ps(left->xmm[0], right->xmm[0]); - register __m128 c1 = _mm_sub_ps(left->xmm[1], right->xmm[1]); - register __m128 c2 = _mm_sub_ps(left->xmm[2], right->xmm[2]); - register __m128 c3 = _mm_sub_ps(left->xmm[3], right->xmm[3]); - - ans->xmm[0] = c0; - ans->xmm[1] = c1; - ans->xmm[2] = c2; - ans->xmm[3] = c3; -} - -DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, sub) -{ - register __m256 c0 = _mm256_sub_ps(left->ymm[0], right->ymm[0]); - register __m256 c1 = _mm256_sub_ps(left->ymm[1], right->ymm[1]); - ans->ymm[0] = c0; - ans->ymm[1] = c1; -} - -DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, 512, sub) -{ - register __m512 c0 = _mm512_sub_ps(left->zmm[0], right->zmm[0]); - ans->zmm[0] = c0; -} - -DECLARE_KER_PROC_RIGHT_ANS_SCALAR(float, sse, scalar_mul) -{ - register __m128 vec = _mm_set_ps1(((float *)(scalar->data))[0]); - register __m128 c0 = _mm_mul_ps(right->xmm[0], vec); - register __m128 c1 = _mm_mul_ps(right->xmm[1], vec); - register __m128 c2 = _mm_mul_ps(right->xmm[2], vec); - register __m128 c3 = _mm_mul_ps(right->xmm[3], vec); - - ans->xmm[0] = c0; - ans->xmm[1] = c1; - ans->xmm[2] = c2; - ans->xmm[3] = c3; -} - -DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, avx, scalar_mul) -{ - register __m256 vec = _mm256_broadcast_ss(((float *)(scalar->data))); - for (size_t i = 0; i < count; i++) { - register __m256 c0 = _mm256_mul_ps(right[i].ymm[0], vec); - register __m256 c1 = _mm256_mul_ps(right[i].ymm[1], vec); - - ans[i].ymm[0] = c0; - ans[i].ymm[1] = c1; - } -} - -DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(float, 512, scalar_mul) -{ - register __m512 vec = _mm512_broadcastss_ps(((__m128 *)(scalar->data))[0]); - for (size_t i = 0; i < count; i++) { - register __m512 c0 = _mm512_mul_ps(right[i].zmm[0], vec); - - ans[i].zmm[0] = c0; - } -} diff --git a/StgSharpDebug/Program.cs b/StgSharpDebug/Program.cs index b1309fbb..f21e8f8b 100644 --- a/StgSharpDebug/Program.cs +++ b/StgSharpDebug/Program.cs @@ -58,11 +58,11 @@ namespace StgSharp unchecked { hlsf = new((nuint)(64 * (ulong)10000 * 10000)); } - Matrix m = Matrix.Create(4000, 4000, MatrixLayout.DenseSquare, hlsf); + Matrix m = Matrix.Create(4000, 4000, MatrixLayout.DenseRectangle, hlsf); MatrixCompute.Fill(m, 1.0f); - Matrix n = Matrix.Create(4000, 4000, MatrixLayout.DenseSquare, hlsf); + Matrix n = Matrix.Create(4000, 4000, MatrixLayout.DenseRectangle, hlsf); MatrixCompute.Fill(n, 1.0f); - Matrix p = Matrix.Create(4000, 4000, MatrixLayout.DenseSquare, hlsf); + Matrix p = Matrix.Create(4000, 4000, MatrixLayout.DenseRectangle, hlsf); // MatrixCompute.Fill(p, 0.0f); /* diff --git a/StgSharpDevelop.sln b/StgSharpDevelop.sln index 1811afab..e099905a 100644 --- a/StgSharpDevelop.sln +++ b/StgSharpDevelop.sln @@ -46,8 +46,8 @@ Global {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.Debug|x64.Build.0 = Debug|x64 {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.PerformanceDebug|ARM64.ActiveCfg = PerformanceDebug|ARM64 {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.PerformanceDebug|ARM64.Build.0 = PerformanceDebug|ARM64 - {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.PerformanceDebug|x64.ActiveCfg = PerformanceDebug|x64 - {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.PerformanceDebug|x64.Build.0 = PerformanceDebug|x64 + {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.PerformanceDebug|x64.ActiveCfg = Release|x64 + {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.PerformanceDebug|x64.Build.0 = Release|x64 {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.Release|ARM64.ActiveCfg = Release|ARM64 {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.Release|ARM64.Build.0 = Release|ARM64 {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.Release|x64.ActiveCfg = Release|x64 @@ -58,8 +58,8 @@ Global {610B992B-BB34-49C3-9993-676C595FC12E}.Debug|x64.Build.0 = Debug|x64 {610B992B-BB34-49C3-9993-676C595FC12E}.PerformanceDebug|ARM64.ActiveCfg = PerformanceDebug|ARM64 {610B992B-BB34-49C3-9993-676C595FC12E}.PerformanceDebug|ARM64.Build.0 = PerformanceDebug|ARM64 - {610B992B-BB34-49C3-9993-676C595FC12E}.PerformanceDebug|x64.ActiveCfg = PerformanceDebug|x64 - {610B992B-BB34-49C3-9993-676C595FC12E}.PerformanceDebug|x64.Build.0 = PerformanceDebug|x64 + {610B992B-BB34-49C3-9993-676C595FC12E}.PerformanceDebug|x64.ActiveCfg = Release|x64 + {610B992B-BB34-49C3-9993-676C595FC12E}.PerformanceDebug|x64.Build.0 = Release|x64 {610B992B-BB34-49C3-9993-676C595FC12E}.Release|ARM64.ActiveCfg = Release|ARM64 {610B992B-BB34-49C3-9993-676C595FC12E}.Release|ARM64.Build.0 = Release|ARM64 {610B992B-BB34-49C3-9993-676C595FC12E}.Release|x64.ActiveCfg = Release|x64 @@ -69,8 +69,8 @@ Global {20CBFF26-6746-402E-992C-7B643E9423EB}.Debug|x64.Build.0 = Debug|x64 {20CBFF26-6746-402E-992C-7B643E9423EB}.PerformanceDebug|ARM64.ActiveCfg = PerformanceDebug|x64 {20CBFF26-6746-402E-992C-7B643E9423EB}.PerformanceDebug|ARM64.Build.0 = PerformanceDebug|x64 - {20CBFF26-6746-402E-992C-7B643E9423EB}.PerformanceDebug|x64.ActiveCfg = PerformanceDebug|x64 - {20CBFF26-6746-402E-992C-7B643E9423EB}.PerformanceDebug|x64.Build.0 = PerformanceDebug|x64 + {20CBFF26-6746-402E-992C-7B643E9423EB}.PerformanceDebug|x64.ActiveCfg = Release|x64 + {20CBFF26-6746-402E-992C-7B643E9423EB}.PerformanceDebug|x64.Build.0 = Release|x64 {20CBFF26-6746-402E-992C-7B643E9423EB}.Release|ARM64.ActiveCfg = Release|ARM64 {20CBFF26-6746-402E-992C-7B643E9423EB}.Release|ARM64.Build.0 = Release|ARM64 {20CBFF26-6746-402E-992C-7B643E9423EB}.Release|x64.ActiveCfg = Release|x64 @@ -81,8 +81,8 @@ Global {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.Debug|x64.Build.0 = Debug|x64 {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.PerformanceDebug|ARM64.ActiveCfg = PerformanceDebug|x64 {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.PerformanceDebug|ARM64.Build.0 = PerformanceDebug|x64 - {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.PerformanceDebug|x64.ActiveCfg = PerformanceDebug|x64 - {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.PerformanceDebug|x64.Build.0 = PerformanceDebug|x64 + {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.PerformanceDebug|x64.ActiveCfg = Release|x64 + {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.PerformanceDebug|x64.Build.0 = Release|x64 {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.Release|ARM64.ActiveCfg = Release|x64 {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.Release|ARM64.Build.0 = Release|x64 {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.Release|x64.ActiveCfg = Release|x64 @@ -93,8 +93,8 @@ Global {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.Debug|x64.Build.0 = Debug|x64 {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.PerformanceDebug|ARM64.ActiveCfg = PerformanceDebug|x64 {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.PerformanceDebug|ARM64.Build.0 = PerformanceDebug|x64 - {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.PerformanceDebug|x64.ActiveCfg = PerformanceDebug|x64 - {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.PerformanceDebug|x64.Build.0 = PerformanceDebug|x64 + {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.PerformanceDebug|x64.ActiveCfg = Release|x64 + {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.PerformanceDebug|x64.Build.0 = Release|x64 {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.Release|ARM64.ActiveCfg = Release|x64 {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.Release|ARM64.Build.0 = Release|x64 {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.Release|x64.ActiveCfg = Release|x64 @@ -105,8 +105,8 @@ Global {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.Debug|x64.Build.0 = Debug|x64 {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.PerformanceDebug|ARM64.ActiveCfg = PerformanceDebug|x64 {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.PerformanceDebug|ARM64.Build.0 = PerformanceDebug|x64 - {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.PerformanceDebug|x64.ActiveCfg = PerformanceDebug|x64 - {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.PerformanceDebug|x64.Build.0 = PerformanceDebug|x64 + {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.PerformanceDebug|x64.ActiveCfg = Release|x64 + {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.PerformanceDebug|x64.Build.0 = Release|x64 {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.Release|ARM64.ActiveCfg = Release|ARM64 {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.Release|ARM64.Build.0 = Release|ARM64 {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.Release|x64.ActiveCfg = Release|x64 @@ -117,8 +117,8 @@ Global {9946599F-4D34-440F-840D-F9443D5AEFAA}.Debug|x64.Build.0 = Debug|x64 {9946599F-4D34-440F-840D-F9443D5AEFAA}.PerformanceDebug|ARM64.ActiveCfg = PerformanceDebug|ARM64 {9946599F-4D34-440F-840D-F9443D5AEFAA}.PerformanceDebug|ARM64.Build.0 = PerformanceDebug|ARM64 - {9946599F-4D34-440F-840D-F9443D5AEFAA}.PerformanceDebug|x64.ActiveCfg = PerformanceDebug|x64 - {9946599F-4D34-440F-840D-F9443D5AEFAA}.PerformanceDebug|x64.Build.0 = PerformanceDebug|x64 + {9946599F-4D34-440F-840D-F9443D5AEFAA}.PerformanceDebug|x64.ActiveCfg = Release|x64 + {9946599F-4D34-440F-840D-F9443D5AEFAA}.PerformanceDebug|x64.Build.0 = Release|x64 {9946599F-4D34-440F-840D-F9443D5AEFAA}.Release|ARM64.ActiveCfg = Release|ARM64 {9946599F-4D34-440F-840D-F9443D5AEFAA}.Release|ARM64.Build.0 = Release|ARM64 {9946599F-4D34-440F-840D-F9443D5AEFAA}.Release|x64.ActiveCfg = Release|x64