Last active
March 31, 2018 10:02
-
-
Save gfoidl/9138af7412b0adcab134a7cbc850d589 to your computer and use it in GitHub Desktop.
Pointer alignment
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
| using System; | |
| using System.Numerics; | |
| using System.Runtime.CompilerServices; | |
| using System.Runtime.InteropServices; | |
| namespace ConsoleApp1 | |
| { | |
| class Program | |
| { | |
| static unsafe void Main(string[] args) | |
| { | |
| double[] arr = new double[1_000]; // is aligned (from GC / runtime) | |
| Span<double> span = arr.AsSpan(1); // is not aligned by slicing, so next boundary will be at +3 = 4 again | |
| fixed (double* pArr = &MemoryMarshal.GetReference(span)) | |
| { | |
| double* ptr = pArr; | |
| int elementsToAlign = PointerHelper.GetElementsToAlign<double>(ptr); | |
| #if DEBUG | |
| Console.WriteLine(elementsToAlign); | |
| #endif | |
| while (elementsToAlign > 0) | |
| { | |
| elementsToAlign--; | |
| ptr++; | |
| } | |
| elementsToAlign = PointerHelper.GetElementsToAlign<double>(ptr); | |
| #if DEBUG | |
| Console.WriteLine(elementsToAlign); | |
| #endif | |
| } | |
| } | |
| } | |
| //------------------------------------------------------------------------- | |
| internal static unsafe class PointerHelper | |
| { | |
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | |
| public static int GetElementsToAlign<T>(void* ptr) where T : struct | |
| { | |
| //const int elementsPerByte = sizeof(double) / sizeof(byte); | |
| int elementsPerByte = Unsafe.SizeOf<T>() / sizeof(byte); | |
| int sizeOfVector = Unsafe.SizeOf<Vector<T>>(); | |
| int vectorElements = Vector<T>.Count; | |
| int address = (int)ptr; | |
| int unalignedBytes = address & (sizeOfVector - 1); | |
| int unalignedElements = unalignedBytes / elementsPerByte; | |
| // (vectorElements - unalignedElements) would be OK, but only in the case | |
| // unalignedElements > 0. For the 0-case the % has to be done. | |
| int elementsToAlign = (vectorElements - unalignedElements) & (vectorElements - 1); | |
| return elementsToAlign; | |
| /* | |
| * Bit hack for modulus: https://graphics.stanford.edu/~seander/bithacks.html#ModulusDivisionEasy | |
| * a % b = a & (b - 1) | |
| * is way faster :-) | |
| * | |
| * See also: | |
| * https://github.com/ahsonkhan/coreclr/blob/46b075fc1877e7087da53579c13c8c9069058b42/src/mscorlib/shared/System/SpanHelpers.Char.cs#L95-L97 | |
| * https://github.com/ahsonkhan/coreclr/blob/46b075fc1877e7087da53579c13c8c9069058b42/src/mscorlib/shared/System/SpanHelpers.Char.cs#L131 | |
| */ | |
| } | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
JIT will produce