0

I have a large Eigen::ArrayXXd and need to repeatedly operate on pairs of continuous segments of that array. Typically, I need to use operations that only involve one coefficient at one index of each segment (the segments always have the same size). This happens in the most performance critical portion of my code, so I'm looking for a fast solution.

One example of such operations on both segments is to get the minimum coefficient between both segments for each position. Here's an MWE for that operation:

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

using namespace Eigen;

using Array1Xd = Array<double, 1, Dynamic>;
using Array2Xd = Array<double, 2, Dynamic>;

using Array1XdMap = Eigen::Map<Array1Xd>;

void minCoeffLoop(
    const Array1XdMap& a,
    const Array1XdMap& b,
    Array1Xd& out
){
    for ( Index i{0}; i<out.size(); ++i ){
        out[i] = std::min(a[i], b[i]);
    }
}

void minCoeffCopy(
    const Array1XdMap& a,
    const Array1XdMap& b,
    Array1Xd& out
){
    Array2Xd copy ( 2, a.size() );
    copy.row(0) = a;
    copy.row(1) = b;
    out = copy.colwise().minCoeff();
}

int main(){
    /* pretend this is some large array */
    ArrayXXd arr (100, 100);

    Index len {10};

    /* map to contiguous memory segments of that array */
    Array1XdMap
        a { &(arr(10,10)), len },
        b { &(arr(10,11)), len };
    
    a.setLinSpaced(0, len-1);
    b.setLinSpaced(len-1, 0);

    Array1Xd out (len);
    
    minCoeffLoop(a, b, out);
    std::cout << "out after loop: " << out << "\n";
    minCoeffCopy(a, b, out);
    std::cout << "out after copy: " << out << "\n";

    return 0;
}

In one function, I use a loop and std::min, and in the other, I copy both segments into the rows of a Matrix, which then enables me to use Eigen's builtin functions (here: .colwise().minCoeff()).

Is there a way to use Eigen functions for this situation?

Otherwise, any comments on achieving fast operations in this situation are also appreciated.

Note: These segments can overlap, if that's important.

Note2: Concatenation via an NullaryExpr as shown here appears to be slower than either copying or using the raw loop.

RL-S
  • 734
  • 6
  • 21
  • 2
    Probably, I don't understand what you actually want to do, but in your MRE you could just do `a.min(b)`. – chtz Sep 21 '21 at 15:11
  • +1 That certainly helps already. The docs appear to know ```min``` only in the context of ```AlignedBox``` :/ I still have many other instances, where that's not quite applicable, will amend the question tmr. – RL-S Sep 21 '21 at 15:26
  • I gave up on the original idea and am working around it. Your comment was nonetheless helpful :) – RL-S Sep 22 '21 at 17:50
  • @RL-S Eigen's online docs seem a bit broken as of late, especially the search function. I guess doxygen can't handle Eigen's template magic. You might want to use an IDE with good autocompletion to find appropriate methods until this is fixed. – Homer512 Nov 19 '21 at 17:21
  • I guess it's just the (bad|good) old doxygen search function.. The `min` function is mentioned in the quick reference guide (https://eigen.tuxfamily.org/dox-devel/group__QuickRefPage.html#QuickRef_Coeffwise), but could really use some visibility. I guess it would have a good chance as a PR though. – RL-S Nov 19 '21 at 21:31

0 Answers0