Skip to content

RowMajor `visit` causes non-optimal transversal

Summary

Calling visit() on a row-major array results in a non-optimal transversal of the data (col major). The docs imply that this method will transverse the data in the most optimal way.

Environment

  • Operating System : Linux (Godbolt online compiler)
  • Architecture : x64
  • Eigen Version : 3.4.0
  • Compiler Version : Gcc 10.3
  • Compile Flags : -O3
  • Vector Extension :

Minimal Example

#include<iostream>
#include<Eigen/Dense>

using namespace Eigen;
using namespace std;

int main(int numargs, char** args)
{
    float data[]={1, 2, 3, 4, 5, 6, 7, 8, 9};
    Map<Array<float, Dynamic, Dynamic, RowMajor>> map(data, 3, 3);

    struct Visitor {
        void init(const float& v, int i, int j) { return Visitor::operator()(v,i,j); }
        void operator()(float v, int i, int j) {
            cout << "map(" << i << ", " << j << ") = " << v << endl;
        }
    } visitor;
    map.visit(visitor);
}

Steps to reproduce

Run the above code and observe that the data is iterated not in the order of the native array. This will result in major performance hits for traversing large row-major arrays (common for CV applications where most images are row-major).

What is the current bug behavior?

Row major arrays are traversed in column major order when using the visit method

What is the expected correct behavior?

The backing array should be traversed in native order for optimal cache performance

Relevant logs

map(0, 0) = 1
map(1, 0) = 4
map(2, 0) = 7
map(0, 1) = 2
map(1, 1) = 5
map(2, 1) = 8
map(0, 2) = 3
map(1, 2) = 6
map(2, 2) = 9
Edited by Matt Fetig