繁体   English   中英

特征3:如何在性能至关重要的操作中访问矩阵系数?

[英]Eigen3: How to access matrix coefficients in performance critical operations?

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

这里有更多细节:

  • 矩阵M在整个程序中将保持恒定
  • 确实多次调用了critical_function ,这就是为什么将其内联

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

选项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;
};

假设

  • M(1,1)导致不断的解引用,从而产生成本,因为将周期添加到计算偏移量(这不是数组,但尚不清楚编译器如何管理它)

选项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;
};

假设

  • 与访问M(1,1)相比 ,访问x产生的周期更少,因此,它比选项1更可取。
  • x确实包含与M(1,1)相同的值,但是承担着确保重复此数据的重要风险,因此在代码维护时需要避免这种情况。

选项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;
};

假设

  • 与在函数范围内不断引用M(1,1)相比,具有单个引用x所产生的循环要少。
  • 这种潜在的优化仅在critical_function内部产生影响,而不会在外部范围内延续,例如多次调用该函数的循环。

编辑

将类型更正为double(从int或float),以与Matrix3d一致。

简而言之,不要打扰写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也可能会降低性能,因为您引入了指针。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM