【问题标题】:Big matrix with compile-time known size in Eigen: MatrixXd or Matrix<double, n, m>?Eigen 中具有编译时已知大小的大矩阵:MatrixXd 还是 Matrix<double, n, m>?
【发布时间】:2020-05-15 08:30:45
【问题描述】:

我正在使用 Eigen 编写一些 C++ 线性代数代码。我必须处理一些不那么小的矩阵(大于 4x4,但小于 50x50,如果这很重要),它们的大小在编译时都是完全已知的。

我很想从 Eigen 库可以围绕矩阵运算执行的编译时大小检查中受益,这会在代码中发生不同大小矩阵之间的总和时触发错误,但是我也很害怕如果我不动态分配那些相对较大的对象,我可能会滥用堆栈。性能问题并不困扰我。

Eigen documentation 有一个关于固定和动态大小矩阵的简短段落,其中讨论了我之前的担忧,但不幸的是,我没有强调我愿意维护的编译时检查。文档建议:

在可能的情况下对非常小的尺寸使用固定尺寸,在较大尺寸或必须使用的情况下使用动态尺寸。

最后,我的问题是:在 Eigen 中是否有办法拥有一个编译时已知大小的动态分配矩阵,以保留我们对标准固定大小矩阵进行的通常编译时检查?

类似这样的:

using MyMatrix = MatrixXd<12, 15>; // Currently I can only do Matrix<double, 12, 15>
using MyVector = MatrixXd<14, 1>;
MyMatrix M;
MyVector v;
auto w = M * v; // This should trigger an INVALID_MATRIX_PRODUCT error

MatrixXd&lt;n, m&gt; 是假设的动态分配、编译时已知大小的矩阵,我想使用!

【问题讨论】:

  • 确实不支持具有堆分配存储的固定大小的矩阵(它实际上在移动或交换矩阵对象时也很有用)。也许为此做一个功能请求(API 方面,这可以通过向Options 模板参数添加一个标志来实现)
  • 另外,如果您没有数百个这样的矩阵或在某些嵌入式系统上工作,那么在堆栈上占用几个 KiB 应该没问题。

标签: c++ eigen


【解决方案1】:

您可以滥用从提供类似 Matrix 的包装器的 Eigen 类的继承:

  1. Eigen::Block

    struct MatrixHelper { Eigen::MatrixXd mat; };
    
    template <int Rows, int Cols>
    struct CheckedDynamicMatrix
      : MatrixHelper, Eigen::Block<Eigen::MatrixXd, Rows, Cols>
    {
      using Block = Eigen::Block<Eigen::MatrixXd, Rows, Cols>;
      CheckedDynamicMatrix() :
        MatrixHelper { Eigen::MatrixXd(Rows, Cols) },
        Block { mat.topLeftCorner<Rows, Cols>() }
      {}
    };
    
  2. Eigen::Map

    template <int Rows, int Cols>
    struct CheckedDynamicMatrix
      : Eigen::Map<Eigen::Matrix<double, Rows, Cols>>
    {
      using Map = Eigen::Map<Eigen::Matrix<double, Rows, Cols>>;
      std::unique_ptr<double[]> data;
      CheckedDynamicMatrix() :
        Map { nullptr },
        data { new double[Rows * Cols] }
      {
        new (static_cast<Map*>(this)) Map(data.get(), Rows, Cols);
      }
    };
    

对于完整的功能,您还应该添加必要的构造函数和赋值运算符,如Eigen: Inheriting from Matrix中所述

【讨论】:

    【解决方案2】:

    你无法说服1 Eigen 两者都做,但你可以动态分配一个固定大小的矩阵。

    using MyMatrix = Matrix<double, 12, 15>;
    using MyVector = Matrix<double, 14, 1>;
    auto M = std::make_unique<MyMatrix>();
    auto v = std::make_unique<MyVector>();
    auto w = *M * *v; // compile time error, as desired
    

    脚注 1:没有关于如果将 MaxRowsMaxCols 设置为固定大小 Matrix 会发生什么的文档,因此您可以尝试 Matrix&lt;double, 12, 15, 0, Dynamic, Dynamic&gt; 看看会发生什么,但要注意以下行为这可能会在没有警告的情况下更改,或者可能导致未定义的行为。

    【讨论】:

    • Dynamic 作为固定大小矩阵的最后一个参数将导致编译错误:godbolt.org/z/VJBT6C
    猜你喜欢
    • 1970-01-01
    • 2021-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多