HLSF done, working on matrix
This commit is contained in:
@@ -1,251 +0,0 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="ConcurrentStackBuffer.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. 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.Threading;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
public static class ConcurrentStackBufferBuilder
|
||||
{
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ConcurrentStackBuffer<T> BuildStack<T>(ReadOnlySpan<T> span)
|
||||
where T: unmanaged
|
||||
{
|
||||
return new ConcurrentStackBuffer<T>(span);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[CollectionBuilder(
|
||||
builderType: typeof(ConcurrentStackBufferBuilder),
|
||||
methodName: nameof(ConcurrentStackBufferBuilder.BuildStack))]
|
||||
public unsafe class ConcurrentStackBuffer<T> : IDisposable where T: unmanaged
|
||||
{
|
||||
|
||||
private byte* _buffer;
|
||||
private readonly BufferExpansionLock _lock = new();
|
||||
private ulong _count;
|
||||
|
||||
internal ConcurrentStackBuffer(ReadOnlySpan<T> span)
|
||||
{
|
||||
AllocateBuffer(span.Length);
|
||||
Span<T> targe = new(_buffer + sizeof(Header), span.Length);
|
||||
span.CopyTo(targe);
|
||||
}
|
||||
|
||||
public ConcurrentStackBuffer(int capacity)
|
||||
{
|
||||
if (capacity <= 0) {
|
||||
throw new ArgumentOutOfRangeException(nameof(capacity));
|
||||
}
|
||||
|
||||
AllocateBuffer(capacity);
|
||||
}
|
||||
|
||||
public ulong Count
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => Volatile.Read(ref _count);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Header* header = (Header*)_buffer;
|
||||
_lock.EnterExpansionProcess();
|
||||
try
|
||||
{
|
||||
header->Top = 0;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitExpansionProcess();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_lock.Dispose();
|
||||
Marshal.FreeHGlobal((nint)_buffer);
|
||||
}
|
||||
|
||||
public T Pop()
|
||||
{
|
||||
Header* header = (Header*)_buffer;
|
||||
while (true)
|
||||
{
|
||||
nuint oldTop = Volatile.Read(ref header->Top);
|
||||
if (oldTop <= 0) {
|
||||
throw new InvalidOperationException("Stack underflow");
|
||||
}
|
||||
|
||||
if (Interlocked.CompareExchange(ref header->Top, oldTop - 1, oldTop) == oldTop)
|
||||
{
|
||||
_lock.EnterBufferRead();
|
||||
try
|
||||
{
|
||||
T* dataStart = (T*)(_buffer + sizeof(Header));
|
||||
_ = Interlocked.Decrement(ref _count);
|
||||
return dataStart[oldTop - 1];
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitBufferRead();
|
||||
}
|
||||
}
|
||||
Thread.Sleep(0); // Yield to avoid busy waiting
|
||||
}
|
||||
}
|
||||
|
||||
public void Push(T item)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
_lock.EnterMetaDataRead();
|
||||
try
|
||||
{
|
||||
Header* header = (Header*)_buffer;
|
||||
nuint oldTop = Volatile.Read(ref header->Top);
|
||||
nuint cap = Volatile.Read(ref header->Capacity);
|
||||
if (oldTop >= cap)
|
||||
{
|
||||
_lock.ExitMetaDataRead();
|
||||
_lock.EnterExpansionProcess();
|
||||
try
|
||||
{
|
||||
header = (Header*)_buffer;
|
||||
if (header->Top >= header->Capacity)
|
||||
{
|
||||
nuint newCap = header->Capacity * 2;
|
||||
nuint newSize = (nuint)sizeof(Header) + (newCap * (nuint)sizeof(T));
|
||||
|
||||
_lock.EnterBufferCopy();
|
||||
try
|
||||
{
|
||||
_buffer = (byte*)NativeMemory.Realloc(_buffer, newSize);
|
||||
((Header*)_buffer)->Capacity = newCap;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitBufferCopy();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitExpansionProcess();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Interlocked.CompareExchange(ref header->Top, oldTop + 1, oldTop) == oldTop)
|
||||
{
|
||||
_lock.EnterBufferRead();
|
||||
try
|
||||
{
|
||||
T* dataStart = (T*)(_buffer + sizeof(Header));
|
||||
dataStart[oldTop] = item;
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitBufferRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_lock.IsThreadReadingMetaData) {
|
||||
_lock.ExitMetaDataRead();
|
||||
}
|
||||
}
|
||||
Thread.Sleep(0); // Yield to avoid busy waiting
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryPop(out T value)
|
||||
{
|
||||
Header* header = (Header*)_buffer;
|
||||
while (true)
|
||||
{
|
||||
nuint oldTop = Volatile.Read(ref header->Top);
|
||||
if (oldTop <= 0)
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Interlocked.CompareExchange(ref header->Top, oldTop - 1, oldTop) == oldTop)
|
||||
{
|
||||
_lock.EnterBufferRead();
|
||||
try
|
||||
{
|
||||
T* dataStart = (T*)(_buffer + sizeof(Header));
|
||||
value = dataStart[oldTop - 1];
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitBufferRead();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Thread.Sleep(0); // Yield to avoid busy waiting
|
||||
}
|
||||
}
|
||||
|
||||
private void AllocateBuffer(int capacity)
|
||||
{
|
||||
nuint size = (nuint)sizeof(Header) + ((nuint)capacity * (nuint)sizeof(T));
|
||||
_buffer = (byte*)NativeMemory.Alloc(size);
|
||||
Header* header = (Header*)_buffer;
|
||||
header->Top = 0;
|
||||
header->Capacity = (nuint)capacity;
|
||||
}
|
||||
|
||||
private struct Header
|
||||
{
|
||||
|
||||
public nuint Capacity; // max capacity of the stack (number of elements)
|
||||
public nuint Top; // next available index in the stack
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -28,17 +28,12 @@
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using StgSharp.Entities;
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Drawing;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Allocator = StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocator;
|
||||
|
||||
@@ -48,7 +43,6 @@ namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
|
||||
internal readonly byte* BufferPointer;
|
||||
|
||||
internal readonly Allocator.Entry* EntryHandle;
|
||||
public readonly uint AllocSize;
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace StgSharp.HighPerformance.Memory
|
||||
if (byteSize < 64) {
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
_entries = SlabAllocator<Entry>.Create(64, BufferLayout.Chunked);
|
||||
_entries = SlabAllocator<Entry>.Create(64, SlabBufferLayout.Chunked, false);
|
||||
_size = byteSize;
|
||||
m_Buffer = (byte*)NativeMemory.AlignedAlloc(byteSize, 16);
|
||||
_align = 16;
|
||||
@@ -75,7 +75,7 @@ namespace StgSharp.HighPerformance.Memory
|
||||
throw new ArgumentException(
|
||||
"Alignment must be a power of two and at least 8 bytes.");
|
||||
}
|
||||
_entries = SlabAllocator<Entry>.Create(64, BufferLayout.Chunked);
|
||||
_entries = SlabAllocator<Entry>.Create(64, SlabBufferLayout.Chunked);
|
||||
m_Buffer = (byte*)NativeMemory.AlignedAlloc(byteSize, (nuint)align);
|
||||
_align = align;
|
||||
_size = byteSize;
|
||||
|
||||
@@ -32,12 +32,9 @@ using StgSharp.Threading;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
@@ -45,8 +42,8 @@ namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
|
||||
private readonly BufferExpansionLock _lock = new();
|
||||
private ConcurrentStackBuffer<nuint> _buffers;
|
||||
private ConcurrentStackBuffer<nuint> _recycle;
|
||||
private BufferStack<nuint> _buffers;
|
||||
private BufferStack<nuint> _recycle;
|
||||
private readonly int _elementSize = Unsafe.SizeOf<T>();
|
||||
|
||||
private nuint _currentBuffer;
|
||||
@@ -67,7 +64,7 @@ namespace StgSharp.HighPerformance.Memory
|
||||
span[i] = _currentBuffer + (nuint)(i * _elementSize);
|
||||
}
|
||||
_buffers = new(4);
|
||||
_recycle = new(span);
|
||||
_recycle = BufferStackBuilder.Create(span);
|
||||
_currentCapacity = count;
|
||||
_currentIndex = (nuint)initCount;
|
||||
}
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="SlabAllocator.Sequencial.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. 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.Threading;
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
public sealed unsafe class SequentialSlabAllocator<T> : SlabAllocator<T> where T: unmanaged
|
||||
{
|
||||
|
||||
private T* _buffer;
|
||||
|
||||
private readonly BufferExpansionLock _lock = new();
|
||||
private readonly ConcurrentStackBuffer<nuint> _stack;
|
||||
private readonly int _elementSize;
|
||||
private nuint _highestAllocated;
|
||||
private ulong _capacity;
|
||||
|
||||
public SequentialSlabAllocator(nuint initialCapacity)
|
||||
{
|
||||
_elementSize = Unsafe.SizeOf<T>();
|
||||
_capacity = initialCapacity;
|
||||
_highestAllocated = 0;
|
||||
|
||||
_buffer = (T*)NativeMemory.Alloc((nuint)_capacity * (nuint)_elementSize);
|
||||
int initCount = _capacity switch
|
||||
{
|
||||
<= 4 => 4,
|
||||
> 64 => 64,
|
||||
_ => (int)_capacity / 4
|
||||
};
|
||||
Span<nuint> span = stackalloc nuint[initCount];
|
||||
for (int i = 0; i < initCount; i++) {
|
||||
span[i] = (nuint)i;
|
||||
}
|
||||
_stack = new(span);
|
||||
_highestAllocated += (nuint)initCount;
|
||||
}
|
||||
|
||||
internal T* BasePointer
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _buffer;
|
||||
}
|
||||
|
||||
public override nuint Allocate()
|
||||
{
|
||||
if (_stack.TryPop(out nuint index)) {
|
||||
return index;
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
index = Volatile.Read(ref _highestAllocated);
|
||||
_lock.EnterMetaDataRead();
|
||||
try
|
||||
{
|
||||
if (index >= _capacity)
|
||||
{
|
||||
_lock.ExitMetaDataRead();
|
||||
_lock.EnterExpansionProcess();
|
||||
try
|
||||
{
|
||||
_capacity = Volatile.Read(ref _capacity) * 2;
|
||||
nuint newSize = (nuint)_capacity * (nuint)_elementSize;
|
||||
_lock.EnterBufferCopy();
|
||||
try
|
||||
{
|
||||
_buffer = (T*)NativeMemory.Realloc(_buffer, newSize);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitBufferCopy();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitExpansionProcess();
|
||||
}
|
||||
}
|
||||
_ = Interlocked.Increment(ref Unsafe.As<nuint, ulong>(ref _highestAllocated));
|
||||
return index;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_lock.IsThreadReadingMetaData) {
|
||||
_lock.ExitMetaDataRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
_stack.Dispose();
|
||||
NativeMemory.Free(_buffer);
|
||||
_lock.Dispose();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void EnterBufferReading()
|
||||
{
|
||||
_lock.EnterBufferRead();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void ExitBufferReading()
|
||||
{
|
||||
_lock.ExitBufferRead();
|
||||
}
|
||||
|
||||
public override void Free(nuint index)
|
||||
{
|
||||
_stack.Push(index);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override SlabAllocationHandle<T> ReadAllocation()
|
||||
{
|
||||
EnterBufferReading();
|
||||
return new SlabAllocationHandle<T>(this, true);
|
||||
}
|
||||
|
||||
~SequentialSlabAllocator()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -28,17 +28,7 @@
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using StgSharp.HighPerformance.Memory;
|
||||
using StgSharp.Threading;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
@@ -47,12 +37,62 @@ namespace StgSharp.HighPerformance.Memory
|
||||
|
||||
public abstract nuint Allocate();
|
||||
|
||||
public static SlabAllocator<T> Create(nuint count, BufferLayout layout)
|
||||
/// <summary>
|
||||
/// Creates a new SLAB allocator instance with the specified configuration.
|
||||
/// </summary>
|
||||
/// <param name="count">
|
||||
/// Initial number of objects that can be allocated.
|
||||
/// </param>
|
||||
/// <param name="layout">
|
||||
/// Memory layout strategy for the SLAB allocator.
|
||||
/// </param>
|
||||
/// <param name="concurrentSupport">
|
||||
/// Whether to enable concurrent access support.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A new SLAB allocator instance.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when an invalid layout is specified.
|
||||
/// </exception>
|
||||
/// <exception cref="NotSupportedException">
|
||||
/// Thrown when requesting unsupported configurations.
|
||||
/// </exception>
|
||||
/// <remarks>
|
||||
/// <para><strong> Important Threading Considerations: </strong></para> <para> While SLAB
|
||||
/// allocators themselves may be designed for single-threaded use, allocated objects are
|
||||
/// frequently shared across multiple threads in real-world applications. Due to the
|
||||
/// special implementation of expandable concurrent sequential SLAB allocators, they rely
|
||||
/// on internal expansion locks to ensure that memory buffer expansions (which involve
|
||||
/// copying the entire buffer to a new location) do not occur while other threads are
|
||||
/// reading from allocated regions.</para> <para><strong> Sequential Layout Limitations:
|
||||
/// </strong><br /> Sequential layout SLAB allocators cannot provide a single-threaded
|
||||
/// version because:<list type="bullet"><item><description> They use contiguous memory
|
||||
/// layout that requires buffer expansion when capacity is exceeded
|
||||
/// </description></item><item><description> Buffer expansion involves copying all
|
||||
/// existing data to a new memory location </description></item><item><description>
|
||||
/// Without proper synchronization, concurrent access to allocated objects during
|
||||
/// expansion would cause memory corruption </description></item><item><description> The
|
||||
/// expansion lock mechanism is essential even if allocation itself is single-threaded
|
||||
/// </description></item></list></para> <para><strong> Chunked Layout: </strong><br />
|
||||
/// Chunked layout allocators can optionally provide single-threaded versions since they
|
||||
/// don't require buffer expansion and copying. Each chunk is allocated independently,
|
||||
/// avoiding the memory relocation issues present in sequential layouts.</para>
|
||||
/// </remarks>
|
||||
public static SlabAllocator<T> Create(nuint count, SlabBufferLayout layout, bool concurrentSupport = true)
|
||||
{
|
||||
if (concurrentSupport) {
|
||||
return layout switch
|
||||
{
|
||||
SlabBufferLayout.Sequential => new ConcurrentSequentialSlabAllocator<T>(count),
|
||||
SlabBufferLayout.Chunked => new ConcurrentChunkedSlabAllocator<T>(count),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(layout), layout, null)
|
||||
};
|
||||
}
|
||||
return layout switch
|
||||
{
|
||||
BufferLayout.Sequential => new SequentialSlabAllocator<T>(count),
|
||||
BufferLayout.Chunked => new ChunkedSlabAllocator<T>(count),
|
||||
SlabBufferLayout.Sequential => throw new NotSupportedException("Non-concurrent version of sequential layout SLAB is not supported due to expansion lock requirements for memory safety during buffer expansion."),
|
||||
SlabBufferLayout.Chunked => new ChunkedSlabAllocator<T>(count),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(layout), layout, null)
|
||||
};
|
||||
}
|
||||
@@ -69,12 +109,11 @@ namespace StgSharp.HighPerformance.Memory
|
||||
|
||||
}
|
||||
|
||||
public enum BufferLayout
|
||||
public enum SlabBufferLayout
|
||||
{
|
||||
|
||||
Sequential,
|
||||
Chunked,
|
||||
HybridLayerSegregatedFit
|
||||
Chunked
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,17 +29,21 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using StgSharp.HighPerformance;
|
||||
using StgSharp.HighPerformance.Memory;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using hlsfHandle = StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocationHandle;
|
||||
|
||||
namespace StgSharp.Mathematics
|
||||
{
|
||||
public abstract unsafe partial class Matrix
|
||||
public abstract unsafe partial class Matrix<T> where T: unmanaged, INumber<T>
|
||||
{
|
||||
|
||||
public abstract ref float this[int column, int row]
|
||||
@@ -49,10 +53,8 @@ namespace StgSharp.Mathematics
|
||||
|
||||
public abstract MatrixKernel* GetMatrixKernel(int column, int row);
|
||||
|
||||
[Obsolete(
|
||||
"This method does not contain boarder check, so be careful on size or use indexer instead.",
|
||||
false)]
|
||||
public abstract float* UnsafeIndex(int column, int row);
|
||||
[Obsolete("This method does not contain boarder check, so be careful on size or use indexer instead.", false)]
|
||||
public abstract T* UnsafeIndex(int column, int row);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="VecAny.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. 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 System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Mathematics
|
||||
{
|
||||
[CollectionBuilder(typeof(VecAnyBuilder), nameof(VecAnyBuilder.Build))]
|
||||
public class VecAny : IEnumerable<float>
|
||||
{
|
||||
|
||||
private float[] _values;
|
||||
|
||||
internal VecAny(ReadOnlySpan<float> values)
|
||||
{
|
||||
_values = values.ToArray();
|
||||
}
|
||||
|
||||
public VecAny(int size)
|
||||
{
|
||||
if (size <= 0) {
|
||||
throw new ArgumentOutOfRangeException(
|
||||
nameof(size), "Size must be greater than zero.");
|
||||
}
|
||||
_values = new float[size];
|
||||
}
|
||||
|
||||
public VecAny? this[ReadOnlySpan<MatrixIndexLabel> span]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (span.Length == 0) {
|
||||
return null;
|
||||
}
|
||||
int size = 0;
|
||||
foreach (MatrixIndexLabel label in span) {
|
||||
size += label.Length(_values.Length);
|
||||
}
|
||||
return new VecAny(size);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<float> GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<float>)_values).GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return _values.GetEnumerator();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class VecAnyBuilder
|
||||
{
|
||||
|
||||
public static VecAny Build(ReadOnlySpan<float> span)
|
||||
{
|
||||
return new VecAny(span);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
<PropertyGroup>
|
||||
<_LastSelectedProfileId>D:\NitloadIndustry\研究项目\1-Flagship\TH2020\ProjectFile\内核源代码\StgSharp.Common\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -45,7 +45,7 @@ namespace StgSharp.Timing
|
||||
public sealed class TimeSpanAwaitingToken : IDisposable
|
||||
{
|
||||
|
||||
private static readonly ConcurrentStackBuffer<int> s_unusedID = new(1);
|
||||
private static readonly ConcurrentBufferStack<int> s_unusedID = new(1);
|
||||
|
||||
private static int s_maxID;
|
||||
|
||||
|
||||
@@ -63,9 +63,13 @@ namespace StgSharp
|
||||
/**/
|
||||
World.Init();
|
||||
|
||||
// HLSF test arena
|
||||
Console.WriteLine("StgSharp 内存分配器综合性能评估系统");
|
||||
Console.WriteLine("===============================================\n");
|
||||
|
||||
// HLSF test arena (保留原始测试)
|
||||
Console.WriteLine($"\n{new string('=', 80)}");
|
||||
Console.WriteLine(
|
||||
"=== HLSF (Hybrid Layer Segregated Fit Allocator) Single-threaded Stress Test ===\n");
|
||||
"=== HLSF (Hybrid Layer Segregated Fit Allocator) Original Stress Test ===\n");
|
||||
|
||||
|
||||
// 使用适中的内存池大小
|
||||
|
||||
Reference in New Issue
Block a user