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;
|
||||||
using System.Buffers;
|
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Drawing;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
using Allocator = StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocator;
|
using Allocator = StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocator;
|
||||||
|
|
||||||
@@ -48,7 +43,6 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
{
|
{
|
||||||
|
|
||||||
internal readonly byte* BufferPointer;
|
internal readonly byte* BufferPointer;
|
||||||
|
|
||||||
internal readonly Allocator.Entry* EntryHandle;
|
internal readonly Allocator.Entry* EntryHandle;
|
||||||
public readonly uint AllocSize;
|
public readonly uint AllocSize;
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
if (byteSize < 64) {
|
if (byteSize < 64) {
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
_entries = SlabAllocator<Entry>.Create(64, BufferLayout.Chunked);
|
_entries = SlabAllocator<Entry>.Create(64, SlabBufferLayout.Chunked, false);
|
||||||
_size = byteSize;
|
_size = byteSize;
|
||||||
m_Buffer = (byte*)NativeMemory.AlignedAlloc(byteSize, 16);
|
m_Buffer = (byte*)NativeMemory.AlignedAlloc(byteSize, 16);
|
||||||
_align = 16;
|
_align = 16;
|
||||||
@@ -75,7 +75,7 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
throw new ArgumentException(
|
throw new ArgumentException(
|
||||||
"Alignment must be a power of two and at least 8 bytes.");
|
"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);
|
m_Buffer = (byte*)NativeMemory.AlignedAlloc(byteSize, (nuint)align);
|
||||||
_align = align;
|
_align = align;
|
||||||
_size = byteSize;
|
_size = byteSize;
|
||||||
|
|||||||
@@ -32,12 +32,9 @@ using StgSharp.Threading;
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace StgSharp.HighPerformance.Memory
|
namespace StgSharp.HighPerformance.Memory
|
||||||
{
|
{
|
||||||
@@ -45,8 +42,8 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
{
|
{
|
||||||
|
|
||||||
private readonly BufferExpansionLock _lock = new();
|
private readonly BufferExpansionLock _lock = new();
|
||||||
private ConcurrentStackBuffer<nuint> _buffers;
|
private BufferStack<nuint> _buffers;
|
||||||
private ConcurrentStackBuffer<nuint> _recycle;
|
private BufferStack<nuint> _recycle;
|
||||||
private readonly int _elementSize = Unsafe.SizeOf<T>();
|
private readonly int _elementSize = Unsafe.SizeOf<T>();
|
||||||
|
|
||||||
private nuint _currentBuffer;
|
private nuint _currentBuffer;
|
||||||
@@ -67,7 +64,7 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
span[i] = _currentBuffer + (nuint)(i * _elementSize);
|
span[i] = _currentBuffer + (nuint)(i * _elementSize);
|
||||||
}
|
}
|
||||||
_buffers = new(4);
|
_buffers = new(4);
|
||||||
_recycle = new(span);
|
_recycle = BufferStackBuilder.Create(span);
|
||||||
_currentCapacity = count;
|
_currentCapacity = count;
|
||||||
_currentIndex = (nuint)initCount;
|
_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;
|
||||||
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
|
namespace StgSharp.HighPerformance.Memory
|
||||||
{
|
{
|
||||||
@@ -47,12 +37,62 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
|
|
||||||
public abstract nuint Allocate();
|
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
|
return layout switch
|
||||||
{
|
{
|
||||||
BufferLayout.Sequential => new SequentialSlabAllocator<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."),
|
||||||
BufferLayout.Chunked => new ChunkedSlabAllocator<T>(count),
|
SlabBufferLayout.Chunked => new ChunkedSlabAllocator<T>(count),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(layout), layout, null)
|
_ => throw new ArgumentOutOfRangeException(nameof(layout), layout, null)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -69,12 +109,11 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum BufferLayout
|
public enum SlabBufferLayout
|
||||||
{
|
{
|
||||||
|
|
||||||
Sequential,
|
Sequential,
|
||||||
Chunked,
|
Chunked
|
||||||
HybridLayerSegregatedFit
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,17 +29,21 @@
|
|||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
using StgSharp.HighPerformance;
|
using StgSharp.HighPerformance;
|
||||||
|
using StgSharp.HighPerformance.Memory;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using hlsfHandle = StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocationHandle;
|
||||||
|
|
||||||
namespace StgSharp.Mathematics
|
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]
|
public abstract ref float this[int column, int row]
|
||||||
@@ -49,10 +53,8 @@ namespace StgSharp.Mathematics
|
|||||||
|
|
||||||
public abstract MatrixKernel* GetMatrixKernel(int column, int row);
|
public abstract MatrixKernel* GetMatrixKernel(int column, int row);
|
||||||
|
|
||||||
[Obsolete(
|
[Obsolete("This method does not contain boarder check, so be careful on size or use indexer instead.", false)]
|
||||||
"This method does not contain boarder check, so be careful on size or use indexer instead.",
|
public abstract T* UnsafeIndex(int column, int row);
|
||||||
false)]
|
|
||||||
public abstract float* 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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<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>
|
</Project>
|
||||||
@@ -45,7 +45,7 @@ namespace StgSharp.Timing
|
|||||||
public sealed class TimeSpanAwaitingToken : IDisposable
|
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;
|
private static int s_maxID;
|
||||||
|
|
||||||
|
|||||||
@@ -63,9 +63,13 @@ namespace StgSharp
|
|||||||
/**/
|
/**/
|
||||||
World.Init();
|
World.Init();
|
||||||
|
|
||||||
// HLSF test arena
|
Console.WriteLine("StgSharp 内存分配器综合性能评估系统");
|
||||||
|
Console.WriteLine("===============================================\n");
|
||||||
|
|
||||||
|
// HLSF test arena (保留原始测试)
|
||||||
|
Console.WriteLine($"\n{new string('=', 80)}");
|
||||||
Console.WriteLine(
|
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