Last active
May 3, 2020 18:29
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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