190 lines
5.9 KiB
C#
190 lines
5.9 KiB
C#
using BenchmarkDotNet.Attributes;
|
|
|
|
namespace Just.PreciseMath.Benchmarks;
|
|
|
|
/// <summary>Measures independent array operations, including loads, stores, and loop overhead.</summary>
|
|
[MemoryDiagnoser]
|
|
[CategoriesColumn]
|
|
public class ArithmeticThroughputBenchmarks
|
|
{
|
|
private DoubleDouble[] _left = [];
|
|
private DoubleDouble[] _right = [];
|
|
private double[] _scalarLeft = [];
|
|
private double[] _scalarRight = [];
|
|
private readonly DoubleDouble[] _results = new DoubleDouble[ArithmeticInputs.Count];
|
|
private readonly double[] _doubleResults = new double[ArithmeticInputs.Count];
|
|
|
|
[Params("BinaryExact", "DecimalResidual", "BothResidual", "Mixed", "SignsAndScales", "Cancellation")]
|
|
public string Scenario { get; set; } = "BothResidual";
|
|
|
|
[GlobalSetup]
|
|
public void Setup()
|
|
{
|
|
ArithmeticInputs inputs = ArithmeticInputs.Create(Scenario, false);
|
|
_left = inputs.Left;
|
|
_right = inputs.Right;
|
|
_scalarLeft = Array.ConvertAll(_left, value => value.High);
|
|
_scalarRight = Array.ConvertAll(_right, value => value.High);
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Addition")]
|
|
public DoubleDouble[] DDAdd()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_results[i] = _left[i] + _right[i];
|
|
}
|
|
return _results;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Addition")]
|
|
public DoubleDouble[] DDScalarAdd()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_results[i] = _left[i] + _scalarRight[i];
|
|
}
|
|
return _results;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Addition")]
|
|
public DoubleDouble[] ScalarDDAdd()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_results[i] = _scalarLeft[i] + _right[i];
|
|
}
|
|
return _results;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Addition")]
|
|
public double[] DoubleAdd()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_doubleResults[i] = _scalarLeft[i] + _scalarRight[i];
|
|
}
|
|
return _doubleResults;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Subtraction")]
|
|
public DoubleDouble[] DDSubtract()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_results[i] = _left[i] - _right[i];
|
|
}
|
|
return _results;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Subtraction")]
|
|
public DoubleDouble[] DDScalarSubtract()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_results[i] = _left[i] - _scalarRight[i];
|
|
}
|
|
return _results;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Subtraction")]
|
|
public DoubleDouble[] ScalarDDSubtract()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_results[i] = _scalarLeft[i] - _right[i];
|
|
}
|
|
return _results;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Subtraction")]
|
|
public double[] DoubleSubtract()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_doubleResults[i] = _scalarLeft[i] - _scalarRight[i];
|
|
}
|
|
return _doubleResults;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Multiplication")]
|
|
public DoubleDouble[] DDMultiply()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_results[i] = _left[i] * _right[i];
|
|
}
|
|
return _results;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Multiplication")]
|
|
public DoubleDouble[] DDScalarMultiply()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_results[i] = _left[i] * _scalarRight[i];
|
|
}
|
|
return _results;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Multiplication")]
|
|
public DoubleDouble[] ScalarDDMultiply()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_results[i] = _scalarLeft[i] * _right[i];
|
|
}
|
|
return _results;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Multiplication")]
|
|
public double[] DoubleMultiply()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_doubleResults[i] = _scalarLeft[i] * _scalarRight[i];
|
|
}
|
|
return _doubleResults;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Division")]
|
|
public DoubleDouble[] DDDivide()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_results[i] = _left[i] / _right[i];
|
|
}
|
|
return _results;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Division")]
|
|
public DoubleDouble[] DDScalarDivide()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_results[i] = _left[i] / _scalarRight[i];
|
|
}
|
|
return _results;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Division")]
|
|
public DoubleDouble[] ScalarDDDivide()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_results[i] = _scalarLeft[i] / _right[i];
|
|
}
|
|
return _results;
|
|
}
|
|
|
|
[Benchmark(OperationsPerInvoke = ArithmeticInputs.Count), BenchmarkCategory("Division")]
|
|
public double[] DoubleDivide()
|
|
{
|
|
for (int i = 0; i < ArithmeticInputs.Count; i++)
|
|
{
|
|
_doubleResults[i] = _scalarLeft[i] / _scalarRight[i];
|
|
}
|
|
return _doubleResults;
|
|
}
|
|
}
|