Eigen:引用ArrayWrapper的有效方式

时间:2018-03-12 09:52:40

标签: c++ c++11 eigen eigen3

我正在使用原始指针连接一些代码。所以我广泛使用了地图类:

void foo(T* raw_pointer){
    const int rows = ...;
    const int cols = ...;
    Map<Matrix<T, rows, cols>> mat(raw_pointer);

    // DO some stuff with "mat"
}

现在我想在foo中应用一些cwise操作,我使用.array()完成了这些操作。但是,由于函数中散布的所有.array()调用,它看起来非常混乱。例如,为了论证,让我们假设函数看起来像这样:

void foo(T* raw_pointer){
    const int rows = ...;
    const int cols = ...;
    Map<Matrix<T, rows, cols>> mat(raw_pointer);

    for (int i = 0 ; i < 1000 ; ++i)
        ... something = i * mat.row(1).array() * sin(mat.row(4).array()) + mat.col(1).array();
}

这个问题的部分原因是很难清楚代码实际上在做什么。如果给出变量名称会更好:

void foo(T* raw_pointer){
    const int rows = ...;
    const int cols = ...;
    Map<Matrix<T, rows, cols>> mat(raw_pointer);

    Matrix<T, 1, cols> thrust = mat.row(1);
    Matrix<T, 1, cols> psi = mat.row(4);
    Matrix<T, 1, cols> bias = mat.row(2);

    for (int i = 0 ; i < 1000 ; ++i)
        ... something = i * thrust.array() * sin(psi.array()) + bias.array();
}

但如果我可以直接获得对ArrayWrapper的引用,那么它会更好,这样我们就不会制作任何副本。但是,我能弄清楚如何使其工作的唯一方法是使用auto

void foo(T* raw_pointer){
    const int rows = ...;
    const int cols = ...;
    Map<Matrix<T, rows, cols>> mat(raw_pointer);

    auto thrust = mat.row(1).array();
    auto psi = mat.row(4).array();
    auto bias = mat.row(2).array();

    for (int i = 0 ; i < 1000 ; ++i)
        ... something = i * thrust * sin(psi) + bias;
}

此代码有效,并且在测试时似乎引用指针中的条目(而不是像上一个代码片段那样制作副本)。然而, 自Eigen文档explicitly suggests NOT doing this以来,我对其效率感到担忧。那么有人可以在这样的情况下,首先定义变量类型的首选方法是什么?

在我看来,我应该在这里使用Ref,但我无法弄清楚如何让它发挥作用。具体来说,我尝试用

替换auto
Eigen::Ref<Eigen::Array<T, 1, cols>>

Eigen::Ref<Eigen::ArrayWrapper<Eigen::Matrix<T, 1, cols>>>

但编译器并不喜欢其中任何一个。

2 个答案:

答案 0 :(得分:3)

为避免每次使用array()时都必须写Map<Eigen::Matrix...,您可以使用Map<Eigen::Array...代替/。这将使用默认的逐元素运算符而不是矩阵运算符。要使用矩阵运算符,您可以使用map.matrix()(类似于帖子mat.array()中的内容)。

答案 1 :(得分:2)

auto thrust = [](auto&&mat){return mat.row(1).array();};
auto psi = [](auto&&mat){return mat.row(4).array();};
auto bias = [](auto&&mat){return mat.row(2).array();};

for (int i = 0 ; i < 1000 ; ++i)
    ... something = i * thrust(mat) * sin(psi(mat)) + bias(mat)

有名字。并且数组包装器不会持久存在。