Repository navigation
Closed
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIdocumentationDocumentation bug or enhancement, does not impact product or test codeDocumentation bug or enhancement, does not impact product or test codereduce-unsafe
Milestone
Description
The vectorization guidelines heavily relies on unsafe code in its examples. Recently, we landed a few improvements in the JIT that allows to use safe code with SIMD without extra checks. It might not be enough for all shapes currently used with SIMD, but should be OK to stop promoting the unsafe code, e.g. the existing example from the guidelines:
int Sum(Span<int> buffer)
{
Debug.Assert(Vector128.IsHardwareAccelerated && buffer.Length >= Vector128<int>.Count);
Vector128<int> sum = Vector128<int>.Zero;
ref int searchSpace = ref MemoryMarshal.GetReference(buffer);
nuint elementOffset = 0;
nuint oneVectorAwayFromEnd = (nuint)(buffer.Length - Vector128<int>.Count);
for (; elementOffset <= oneVectorAwayFromEnd; elementOffset += (nuint)Vector128<int>.Count)
{
Vector128<int> loaded = Vector128.LoadUnsafe(ref searchSpace, elementOffset);
sum += loaded;
}
int result = Vector128.Sum(sum);
while (elementOffset < (nuint)buffer.Length)
{
result += buffer[(int)elementOffset];
elementOffset++;
}
return result;
}can be rewritten into 100% safe code:
int Sum(Span<int> data)
{
Vector128<int> sum = default;
while (data.Length >= Vector128<int>.Count)
{
sum += Vector128.Create(data);
data = data.Slice(Vector128<int>.Count);
}
int result = Vector128.Sum(sum);
foreach (var t in data)
result += t;
return result;
}after #127117 was merged.
See the benchmark below. The results imply there is no perf difference between the safe and the unsafe versions.
Reacted by Paulus Pärssinen and OmariO
Metadata
Metadata
Assignees
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIdocumentationDocumentation bug or enhancement, does not impact product or test codeDocumentation bug or enhancement, does not impact product or test codereduce-unsafe
Activity
dotnet-policy-service commentedon Apr 28, 2026
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.
EgorBo commentedon Apr 28, 2026
@EgorBot -arm -amd -commits main
dotnet-policy-service commentedon Apr 28, 2026
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.
unsafePtr commentedon Jul 23, 2026
@EgorBo Tried to rewrite some internal code. I don't get the perf benefit of the safe way on .net11
tannergooding commentedon Jul 23, 2026
The guidelines (https://github.com/dotnet/runtime/blob/main/docs/coding-guidelines/vectorization-guidelines.md) have since been rewritten and now largely defer to the public docs (https://learn.microsoft.com/en-us/dotnet/standard/simd)
The examples all center around the safe patterns and require no
unsafe. There is still an explicit callout (under https://learn.microsoft.com/en-us/dotnet/standard/simd#load-and-store-vectors-safely) that if code absolutely must use the unsafe APIs, there are some patterns that can help mitigate failures. But that most code can and should be using the span based APIs instead.tannergooding commentedon Jul 23, 2026
@unsafePtr, you'll want to follow what is more akin to the
whileloop pattern given. This also allows you to trivial handle the trailing data efficiently.You are not prevented from using the
forpattern you have, but the general flow and checks still need to generally match how thewhilepattern is setup.EgorBo commentedon Jul 23, 2026
Yes, it's being worked on still (#111309), I do plan to optimize shapes like
for (; i <= upper; i += Vector256<ulong>.Count)in fact I already fixed it locally, but it didn't make it to .NET 11.0 unfortunately.For now I recommend using
@unsafePtr I've rewritten your safe impl and kicked off benchmarks here: EgorBot/Benchmarks#401
As you can see, it's already as fast as unsafe on mac.