[API Proposal]: MemoryMarshal.GetAlignmentOffset for safe SIMD loop peeling
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
### Background and motivation
Vectorizing a loop over a GC-allocated array is often ~15% slower (up to 30% in some cases) than it should be: the GC only guarantees 8-byte alignment, so `Vector512` loads cross a cache line every iteration and pay a misalignment penalty. Occasionally the GC hands back a 64-byte-aligned buffer, which also makes benchmarks very unstable.
```csharp
[MethodImpl(MethodImplOptions.NoInlining)]
public static int SumSafe(Span span)
{
int sum = 0;
if (Vector128.IsHardwareAccelerated)
{
var acc512 = Vector512.Zero;
while (span.Length > Vector512.Count)
{
acc512 += Vector512.Create(span);
span = span.Slice(Vector512.Count);
}
sum = Vector512.Sum(acc512);
}
foreach (int value in span)
sum += value;
return sum;
}
```
### API Proposal
```diff
namespace System.Runtime.InteropServices
{
public static partial class MemoryMarshal
{
+ // Number of leading elements to skip so the rest is `alignment`-byte aligned.
+ // Returns [0, span.Length]. Best-effort for non-pinned memory. `alignment` must be pow2.
+ public static int GetOpportunisticAlignmentOffset(ReadOnlySpan span, nuint alignment);
+ public static int GetOpportunisticAlignmentOffset(Span span, nuint alignment);
}
}
```
### API Usage
```csharp
int offset = MemoryMarshal.GetAlignmentOffset(span, 64);
for (int i = 0; i < offset; i++) // scalar prologue
sum += span[i];
span = span.Slice(offset); // aligned body follows
```
### Alternative Designs
* Move to `MemoryExtensions` or `Unsafe`?
* Add `Opportunistic` into the API name? to imply the GC issue.
### Risks
- Opportunistic only: GC may relocate the buffer, so it's a hint. Same caveat as the existing internal helper. Presumably, it shouldn't be an issue for 100% safe code.
- What if input is Span of misaligned elements - should we return 0?
Contributor guide
Research direction
No implementation file or test is named. Start by reviewing the proposed MemoryMarshal overloads, the alternative API locations, and the existing internal alignment helper mentioned in the risks; done means resolving the API name, placement, alignment semantics, and relocation caveat.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- backend-api-design, performance
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100