mathnet-numerics
mathnet-numerics copied to clipboard
Performance issue with LinearAlgebraControl.Provider.ScaleArray (MKL)
I am trying to multiply a large Complex array with a scalar using the ScaleArray function of the LinearAlgebraControl class. The provider is {Intel MKL (x64; revision 15; MKL 2022.0)}. The ScaleArray call eventually calls the z_scale function of the libMathNetNumericsMKL.dll.
Compared to the simple loop implementation, MKL version is at least 2 times slower.
.NET loop average run time: 76,5 ms. Math.NET average run time: 170 ms.
Here is my test code:
class ScaleTest
{
public static void Run()
{
MathNet.Numerics.Control.UseNativeMKL();
int iterations = 100;
var stopwatch = new Stopwatch();
double averageTime = 0;
var rand = new Random(0);
var arr = Enumerable.Range(0, 10000000).Select(i => new Complex(rand.NextDouble(), rand.NextDouble())).ToArray();
double scaleFactor = 0.2;
//
// with simple loop
//
stopwatch.Restart();
for (int i = 0; i < iterations; i++)
{
var arr2 = arr.ToArray();
ScaleWithLoop(arr2, scaleFactor);
}
stopwatch.Stop();
averageTime = (double)stopwatch.ElapsedMilliseconds / iterations;
Console.WriteLine($".NET loop average run time: {averageTime} ms.");
//
// with Math.NET LinearAlgebraProvider (MKL) ScaleArray
//
stopwatch.Restart();
for (int i = 0; i < iterations; i++)
{
var arr2 = arr.ToArray();
ScaleWithMKL(arr2, scaleFactor);
}
stopwatch.Stop();
// Calculate the average run time in milliseconds
averageTime = (double)stopwatch.ElapsedMilliseconds / iterations;
Console.WriteLine($"Math.NET average run time: {averageTime} ms.");
}
/// <summary>
/// Divides each element by the given scaleFactor IN-PLACE.
/// </summary>
/// <param name="arr"></param>
/// <param name="scaleFactor"></param>
public static void ScaleWithMKL(Complex[] arr, double scaleFactor)
{
Complex factor = 1.0 / scaleFactor;
LinearAlgebraControl.Provider.ScaleArray(factor, arr, arr);
}
/// <summary>
/// Divides each element by the given scaleFactor IN-PLACE.
/// </summary>
/// <param name="arr"></param>
/// <param name="scaleFactor"></param>
public static void ScaleWithLoop(Complex[] arr, double scaleFactor)
{
var factor = 1.0 / scaleFactor;
int len = arr.Length;
for (int i = 0; i < len; i++)
{
arr[i] = new Complex(factor * arr[i].Real, factor * arr[i].Imaginary);
}
}
}