SimdLinq is a drop-in replacement of LINQ aggregation operations(Sum
, Average
, Min
, Max
) extremely faster with SIMD.
.NET 7 LINQ supports SIMD but it is very limited, due to compatibility and safety issues, it is only enabled for int[]
Average
, Min
, Max
and long[]
Min
, Max
.
SimdLinq accelerates many methods (Sum
, LongSum
, Average
, Min
, Max
, MinMax
, Contains
, SequenceEqual
) and types (byte
, sbyte
, short
, ushort
, int
, uint
, long
, ulong
, float
, double
). It can also be used with List<T>
, Span<T>
, ReadOnlySpan<T>
, Memory<T>
, ReadOnlyMemory<T>
in addition to T[]
.
Using the overload resolution priority, all target methods are automatically SIMD by simply referencing the library and setting global using.
This library is distributed via NuGet.
PM> Install-Package SimdLinq
Note that this library requires .NET 7 or above because this library uses static abstract members and the new cross platform .NET 7 SIMD Api.
using SimdLinq; // enable SimdLinq extension methods
var array = Enumerable.Range(1, 100000).ToArray();
var sum = array.Sum(); // uses SimdLinqExtensions.Sum
To enable SimdLinq per file, add the using SimdLinq;
using directive. To enable SimdLinq across the project, use global usings in the csproj file.
<ItemGroup>
<Using Include="SimdLinq" />
</ItemGroup>
SimdLinqExtensions
has methods for concrete data types, like int[]
or Span<double>
, with the same names as LINQ's methods. If a method is eligible for SIMD optimization (such as the Sum of int[]), the SimdLinqExtensions
method will be used for improved performance.
Unlike base LINQ, SimdLinq supports Span<T>
, allowing you to call methods such as Sum
, Min
, etc. on Span<T>
or ReadOnlySpan<T>
collections.
(double Min, double Max) GetMinMax(Span<double> span)
{
return span.MinMax();
}
MinMax
is an original SimdLinq extension, that returns a tuple of Min
and Max
.
One of the reasons why LINQ's SIMD support in .NET 7 is incomplete, is compatibility. SimdLinq prioritises performance over some safety features and full compatibility with LINQ. Please note the following differences.
LINQ Sum is checked
but SimdLinq is unchecked
(SIMD operation is not supported overflow). To reduce the risk of overflow, Sum
and Average
only support types that are 32-bit or higher(int
, long
, uint
, ulong
, double
, float
).
SimdLinq provides LongSum
for int
and uint
, that returns long
/ulong
so avoid overflow.
Unlike LINQ, SimdLinq does not check for NaN in float/double Min/Max calculations. Additionally, the order of calculation for Sum is not sequential, leading to slight differences in floating-point operations compared to regular LINQ. For instance, LINQ returns 1.5710588F, while SimdLinq returns 1.5710589F. If compatibility is not a concern, this difference is not significant, but be aware of potential small tolerance differences.
T[]
, List<T>
, Span<T>
, Memory<T>
, ReadOnlyMemory<T>
, Span<T>
, ReadOnlySpan<T>
.
Sum
forint
,uint
,long
,ulong
,float
,double
LongSum
forint
,uint
Average
forint
,uint
,long
,ulong
,float
,double
Min
forbyte
,sbyte
,short
,ushort
,int
,uint
,long
,ulong
,float
,double
Max
forbyte
,sbyte
,short
,ushort
,int
,uint
,long
,ulong
,float
,double
MinMax
forbyte
,sbyte
,short
,ushort
,int
,uint
,long
,ulong
,float
,double
Contains
forbyte
,sbyte
,short
,ushort
,int
,uint
,long
,ulong
,float
,double
SequenceEqual
forbyte
,sbyte
,short
,ushort
,int
,uint
,long
,ulong
,float
,double
SIMD with LINQ requires primitive array(or Span). Cysharp/StructureOfArraysGenerator makes easy to create SoA array to use SIMD easily.
This library is licensed under the MIT License.