Skip to content

Instantly share code, notes, and snippets.

@zivillian
Last active May 3, 2020 18:29
Show Gist options
  • Select an option

  • Save zivillian/5b91eed0eb1803601f5376cb05366d3c to your computer and use it in GitHub Desktop.

Select an option

Save zivillian/5b91eed0eb1803601f5376cb05366d3c to your computer and use it in GitHub Desktop.
32 byte aligned and pinned MemoryPool<T> without unsafe or fixed context for usage with Vector<T> and AVX
public static class AlignedSizedMemoryPool<T> where T:unmanaged
{
private const int ByteAlignment = 32;
private static readonly int SizeOf = StructSize.GetSize<T>(default);
private static readonly int Alignment = ByteAlignment / SizeOf;
public static IMemoryOwner<T> Rent(int bufferSize)
{
if (SizeOf == -1) throw new InvalidOperationException(String.Format("Type {0} cannot be aligned", typeof(T)));
return new SizedMemoryOwner(ArrayPool<T>.Shared.Rent(bufferSize + Alignment), bufferSize);
}
private class SizedMemoryOwner:IMemoryOwner<T>
{
private T[] _inner;
private MemoryHandle _handle;
private Memory<T> _memory;
public SizedMemoryOwner(T[] inner, int length)
{
_inner = inner;
var memory = inner.AsMemory();
_handle = memory.Pin();
ref T memoryPtr = ref MemoryMarshal.GetReference(memory.Span);
ref T nullPtr = ref MemoryMarshal.GetReference(Span<T>.Empty);
var delta = Unsafe.ByteOffset(ref nullPtr, ref memoryPtr).ToInt64();
//https://meekmaak.blogspot.com/2010/06/c-memory-aligned-array-wrapper-for-fast.html
var offset = (int)(((delta + ByteAlignment - 1) & ~(ByteAlignment - 1)) - delta) / SizeOf;
_memory = memory.Slice(offset, length);
}
public Memory<T> Memory => _memory;
protected virtual void Dispose(bool disposing)
{
if (disposing && !(_inner is null))
{
_handle.Dispose();
ArrayPool<T>.Shared.Return(_inner);
_inner = null;
_memory = null;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
internal static class StructSize
{
//https://docs.microsoft.com/de-de/dotnet/csharp/language-reference/operators/sizeof
internal static int GetSize<T>(T value)
{
if (value is byte) return sizeof(byte);
if (value is int) return sizeof(int);
if (value is long) return sizeof(long);
if (value is char) return sizeof(char);
if (value is double) return sizeof(double);
if (value is short) return sizeof(short);
if (value is ushort) return sizeof(ushort);
if (value is uint) return sizeof(uint);
if (value is ulong) return sizeof(ulong);
if (value is decimal) return sizeof(decimal);
if (value is bool) return sizeof(bool);
if (value is float) return sizeof(float);
if (value is sbyte) return sizeof(sbyte);
return -1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment