-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Improve vectorization of Enumerable.Min/Max #76144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Tagging subscribers to this area: @dotnet/area-system-linq Issue Details
// Int32Tests (int was previously vectorized)
// ByteTests (bytes weren't previously vectorized)
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System;
using System.Linq;
public partial class Program
{
static void Main(string[] args) => BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
}
public class Int32Tests
{
[Params(1, 4, 7, 23, 1024)]
public int Count { get; set; }
private int[] _values;
[GlobalSetup]
public void Setup()
{
var r = new Random(42);
_values = Enumerable.Range(0, Count).Select(_ => r.Next()).ToArray();
}
[Benchmark]
public int Max() => _values.Max();
}
public class ByteTests
{
[Params(1, 16, 28, 92, 4096)]
public int Count { get; set; }
private byte[] _values;
[GlobalSetup]
public void Setup()
{
var r = new Random(42);
_values = Enumerable.Range(0, Count).Select(_ => (byte)r.Next()).ToArray();
}
[Benchmark]
public byte Max() => _values.Max();
}
|
- Expand it to all supported types with `Enumerable.Min<T>`/`Max<T>` - Combine Min/Max into a single method using a static abstract interface with generic specialization to differentiate - Use `Vector128<T>` and `Vector256<T>` instead of `Vector<T>` - Improve test coverage
35ec905
to
7106575
Compare
I suspect that LINQ Max/Min are not IEEE754 compatible for floating points due to usage of So e.g. Ah, looks like it's always been like that, reproduces on .net 5.0 and .net472 |
This PR isn't using vector for floating point. |
May I ask why then? Since it won't break the current behavior |
This pr is focused on the MaxInteger method, which doesn't have to be concerned with nans. |
@EgorBo, FYI, I just tried vectorizing Max's use (still handling the search for the first non-NaN sequentially and then vectorizing the rest), and it breaks existing tests around NaN. |
Ah I see, thanks for trying it! I assume we need to raise an issue for this behavior since it's not consistent, will wait @tannergooding's feedback whether if it's expected or there is already an issue (I failed to find one) I assume the IEEE754 Max simd function might look like this: static Vector128<float> Max(Vector128<float> v1, Vector128<float> v2) =>
(Vector128.Max(v1, v2) & Vector128.Max(v1, v2)) | Sse.CompareUnordered(v1, v2); and just |
This is a "downside" of the Realistically, we should have the In an "ideal" world, I'd take the break here and consider exposing a |
Regressions for Windows x64: dotnet/perf-autofiling-issues#8818 (comment) |
Enumerable.Min<T>
/Max<T>
(byte, sbyte, short, ushort, uint, ulong, nuint, nint) beyond the int/long already supportedVector128<T>
andVector256<T>
instead ofVector<T>
// Int32Tests (int was previously vectorized)
// ByteTests (bytes weren't previously vectorized)