首页 > 解决方案 > Eigen3:如何在性能关键操作中访问矩阵系数?

问题描述

我正在尝试优化依赖 Eigen3 的 C++ 中的关键操作。我不清楚哪种类型的系数访问操作会导致运行时性能成本,或者编译器什么时候才能做好。为了找出我困惑的根源,我在下面发布了一个以几种不同方式实现的示例,以及每种方式的一些假设。

这里还有一些细节:

有人可以澄清哪种方法在性能方面是最好的吗?我可能对引用、取消引用等的影响成本感到困惑。

选项 1:直接访问矩阵系数

#include <Eigen/Dense>
class A{
    A(){
        // Assume M has the right numbers
    }

    // This function will be called many many times, inside loops
    inline void critical_function()
    {
        // Do many operations using M(1, 1), for example:
        double y = 1 / M(1, 1);
        // ... some more code using M(1, 1)
    }
private:
    Eigen::Matrix3d M;
};

假设

选项 2:创建我们关心的系数的副本

#include <Eigen/Dense>
class A{
    A(){
        // Assume M has the right numbers
        x = M(1, 1);
    }

    // This function will be called many many times, inside loops
    inline void critical_function()
    {
        // Do many operations using x, for example:
        double y = 1 / x;
        // ... some more code using x
    }
private:
    double x;
    Eigen::Matrix3d M;
};

假设

选项 3:利用参考资料

#include <Eigen/Dense>
class A{
    A(){
        // Assume M has the right numbers
    }

    // This function will be called many many times, inside loops
    inline void critical_function()
    {
        auto & x = M(1, 1);
        // Do many operations using x, for example:
        double y = 1 / x;
        // ... some more code using x
    }
private:
    Eigen::Matrix3d M;
};

假设

编辑

类型已更正为双精度(从 int 或 float),以与 Matrix3d 保持一致。

标签: c++optimizationcompiler-optimizationeigen3

解决方案


简而言之,不要打扰和写M(1,1)

如果您正在处理编译时矩阵(如Matrix3d编译时已知的索引),那么所涉及的索引计算M(1,1)将被任何编译器完全优化掉。换句话说,以下两个片段将生成相同的程序集:

struct A {
  Matrix3d M;
  void foo() { double x = M(1,1); }
};

struct A {
  double a, b, c, d, e, f, g, h, i;
  void foo() { double x = e; }
};

所以选项 2 会更糟,选项 3 也可能因为引入指针而降低性能。


推荐阅读