Skip to content

Mixed multidimensional & jagged arrays cause compilation errors #2893

@User0332

Description

@User0332

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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions