-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
While testing different scenarios for #2891/#2892, I ran into this issue:
When running benchmarks accepting parameters that were mixed jagged/multidimensional arrays, the order of the arrays seems to get mixed up somewhere in the benchmarking pipeline.
For example, running this example:
BenchmarkRunner.Run<MatrixBenchmarks>();
public class MatrixBenchmarks
{
private static double[][,] GenerateRandomMatrix(Random rng, int m, int n)
{
double scale = 10;
double[,] matrix = new double[m, n];
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
matrix[i, j] = scale * rng.NextDouble();
}
}
double[][,] ret = new double[1][,];
ret[0] = matrix;
return ret;
}
[Benchmark(Baseline = true)]
[ArgumentsSource(nameof(MultiDimMatrices))]
[WarmupCount(0)]
[IterationCount(1)]
[EvaluateOverhead(false)]
public double[][,] NaiveMatrixMultiply(double[][,] a, double[][,] b)
{
return a;
}
[Benchmark]
[ArgumentsSource(nameof(MultiDimMatrices))]
[WarmupCount(0)]
[IterationCount(1)]
[EvaluateOverhead(false)]
public double[][,] CacheBlockedMultiDimMatrixMultiply(double[][,] a, double[][,] b)
{
return a;
}
public IEnumerable<object[]> MultiDimMatrices()
{
var rng = new Random(32);
yield return new object[] { GenerateRandomMatrix(rng, 3, 3), GenerateRandomMatrix(rng, 3, 3) };
yield return new object[] { GenerateRandomMatrix(rng, 9, 9), GenerateRandomMatrix(rng, 9, 9) };
yield return new object[] { GenerateRandomMatrix(rng, 1, 10), GenerateRandomMatrix(rng, 10, 1) };
yield return new object[] { GenerateRandomMatrix(rng, 1024, 1024), GenerateRandomMatrix(rng, 1024, 1024) };
}
}results in this log output (notice that the order of [,] and [] are switched):
// Found 8 benchmarks:
// MatrixBenchmarks.NaiveMatrixMultiply: DefaultJob [a=Double[,][1], b=Double[,][1]]
// MatrixBenchmarks.CacheBlockedMultiDimMatrixMultiply: DefaultJob [a=Double[,][1], b=Double[,][1]]
// MatrixBenchmarks.NaiveMatrixMultiply: DefaultJob [a=Double[,][1], b=Double[,][1]]
// MatrixBenchmarks.CacheBlockedMultiDimMatrixMultiply: DefaultJob [a=Double[,][1], b=Double[,][1]]
// MatrixBenchmarks.NaiveMatrixMultiply: DefaultJob [a=Double[,][1], b=Double[,][1]]
// MatrixBenchmarks.CacheBlockedMultiDimMatrixMultiply: DefaultJob [a=Double[,][1], b=Double[,][1]]
// MatrixBenchmarks.NaiveMatrixMultiply: DefaultJob [a=Double[,][1], b=Double[,][1]]
// MatrixBenchmarks.CacheBlockedMultiDimMatrixMultiply: DefaultJob [a=Double[,][1], b=Double[,][1]]And subsequent similarly related compilation errors like error CS1503: Argument 1: cannot convert from 'double[*,*][]' to 'double[][*,*]'.
A similar issue happens if the code uses double[,][] as opposed to double[][,] and somewhere the type gets switched/misinterpreted as double[][,] (again, the array order seems swapped here).
I suppose this has something to do with code generation since it's producing compilation errors.
Possible Workaround
Declaring the methods to accept/return object instead works fine for running the benchmarks, but the user should then cast it back to double[][,] within the method. However, when displaying the results table, the arrays are again displayed backwards.