Skip to content

Commit

Permalink
#641 - Use SIMD instructions for Vector/Matrix calculations.
Browse files Browse the repository at this point in the history
  • Loading branch information
sys27 committed Jul 10, 2023
1 parent bb3902c commit bae6534
Show file tree
Hide file tree
Showing 8 changed files with 315 additions and 36 deletions.
2 changes: 1 addition & 1 deletion xFunc.Benchmark/Benchmarks/ProcessorBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public void Setup()

[Benchmark]
public IExpression Parse()
=> processor.Parse("(100.1 + 2(3sin(4cos(5tan(6ctg(10x)))) * 3) / (func(a, b, c) ^ 2)) - (cos(y) - 111.3) & (true | false impl true eq false) + (det({{1, 2}, {3, 4}}) * 10log(2, 3)) + re(3 + 2i) - im(2 - 9i) + (9 + 2i)");
=> processor.Parse("(100.1 + 2 * (3 * sin(4 * cos(5 * tan(6 * ctg(10 * x)))) * 3) / (func(a, b, c) ^ 2)) - (cos(y) - 111.3) & (true | false impl true eq false) + (det({{1, 2}, {3, 4}}) * 10 * log(2, 3)) + re(3 + 2 * i) - im(2 - 9 * i) + (9 + 2 * i)");

[Benchmark]
public NumberResult Solve()
Expand Down
4 changes: 4 additions & 0 deletions xFunc.Benchmark/Benchmarks/VectorBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ private Vector CreateVector()
return new Vector(vector.ToImmutableArray());
}

[Benchmark]
public object AbsVector()
=> new Abs(vector1).Execute();

[Benchmark]
public object AddVectors()
=> new Add(vector1, vector2).Execute();
Expand Down
33 changes: 0 additions & 33 deletions xFunc.Maths/Expressions/Matrices/VectorExtensions.cs

This file was deleted.

53 changes: 51 additions & 2 deletions xFunc.Maths/Expressions/Matrices/VectorValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Text;
using Simd = System.Numerics;

namespace xFunc.Maths.Expressions.Matrices;

Expand Down Expand Up @@ -160,6 +161,27 @@ public NumberValue[] ToArray()
return copy;
}

/// <summary>
/// Computes the average of a sequence of numeric values.
/// </summary>
/// <returns>The average value.</returns>
public NumberValue Average()
=> Sum() / Size;

/// <summary>
/// Computes the sum of a sequence of numeric values.
/// </summary>
/// <returns>The sum of the values in the vector.</returns>
public NumberValue Sum()
{
var sum = NumberValue.Zero;

for (var i = 0; i < Size; i++)
sum += array[i];

return sum;
}

/// <summary>
/// Gets the size of the current vector.
/// </summary>
Expand All @@ -173,9 +195,36 @@ public int Size
/// <returns>Return the absolute value of vector.</returns>
public static object Abs(VectorValue vector)
{
var sum = vector.array.Aggregate(NumberValue.Zero, (acc, value) => acc + value * value);
var size = Simd.Vector<double>.Count;

if (Simd.Vector.IsHardwareAccelerated && vector.Size >= size)
{
var span = Unsafe.As<double[]>(vector.array).AsSpan();

var v = Simd.Vector<double>.Zero;
var i = 0;

for (; i <= span.Length - size; i += size)
{
var chunkVector = new Simd.Vector<double>(span[i..]);
v += chunkVector * chunkVector;
}

var sum = Simd.Vector.Sum(v);

for (; i < span.Length; i++)
sum += span[i] * span[i];

return NumberValue.Sqrt(new NumberValue(sum));
}
else
{
var sum = NumberValue.Zero;
for (var i = 0; i < vector.Size; i++)
sum += vector[i] * vector[i];

return NumberValue.Sqrt(sum);
return NumberValue.Sqrt(sum);
}
}

/// <summary>
Expand Down
6 changes: 6 additions & 0 deletions xFunc.Maths/Processor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ IExpression expression
Lambda lambda
=> new LambdaResult(lambda),

VectorValue vectorValue
=> new VectorValueResult(vectorValue),

MatrixValue matrixValue
=> new MatrixValueResult(matrixValue),

_ => throw new InvalidResultException(),
};
}
Expand Down
25 changes: 25 additions & 0 deletions xFunc.Maths/Results/MatrixValueResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Dmytro Kyshchenko. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace xFunc.Maths.Results;

/// <summary>
/// Represents the matrix result.
/// </summary>
public class MatrixValueResult : IResult
{
/// <summary>
/// Initializes a new instance of the <see cref="MatrixValueResult"/> class.
/// </summary>
/// <param name="value">The representation of result.</param>
public MatrixValueResult(MatrixValue value) => Result = value;

/// <inheritdoc />
public override string ToString() => Result.ToString();

/// <inheritdoc cref="IResult.Result" />
public MatrixValue Result { get; }

/// <inheritdoc />
object IResult.Result => Result;
}
25 changes: 25 additions & 0 deletions xFunc.Maths/Results/VectorValueResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Dmytro Kyshchenko. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace xFunc.Maths.Results;

/// <summary>
/// Represents the vector result.
/// </summary>
public class VectorValueResult : IResult
{
/// <summary>
/// Initializes a new instance of the <see cref="VectorValueResult"/> class.
/// </summary>
/// <param name="value">The representation of result.</param>
public VectorValueResult(VectorValue value) => Result = value;

/// <inheritdoc />
public override string ToString() => Result.ToString();

/// <inheritdoc cref="IResult.Result" />
public VectorValue Result { get; }

/// <inheritdoc />
object IResult.Result => Result;
}

0 comments on commit bae6534

Please sign in to comment.