【问题标题】:Eigen custom expression type (or CWise Op functor?)Eigen 自定义表达式类型(或 CWise Op 仿函数?)
【发布时间】:2020-04-19 23:10:17
【问题描述】:

考虑这个简单的函数(一种伪代码):

template <typename Derived>
void f (const MatrixBase<Derived>& input1,
        const MatrixBase<Derived>& input2,
        const MatrixBase<Derived>& input3,
        Vec6& output)
{
    part1(output) = <an expr using the three inputs>;
    part2(output) = <another expr using the three inputs>;
}

其中part1part2 是分别选择output 的前3 行和后3 行的块表达式。我知道output总是一个有6个系数的列向量。

我想避免传递 output 参数。但我也想避免返回明确的Vec6,以避免临时副本。

因此,我想返回其中一个神奇的特征表达式对象,它只存储对输入的引用,并且仅在需要时才实际进行计算。

我的问题:

  1. 值得吗?鉴于它是一个“小”的 6 维向量(例如,文档说使用小的 3 维向量,编译器通常能够优化掉临时变量,因此没有太多避免它们的意义)

  2. 我可以使用自定义函子和CWiseNullaryOp 实现我的返回表达式类型,还是真的需要自定义表达式类型?

谢谢


编辑:所以我们确定临时对象已被优化(参见 cmets);这回答了问题 1,并使问题 2 不相关。

但是,为了好奇和更多地了解 Eigen,是否有人对我的函数的可行表达式类型有一些提示? (假设值得设计一个)

【问题讨论】:

    标签: c++ eigen


    【解决方案1】:

    假设 Vec6 的设计“正确”(参见 例如 Rule Of Zero),那么如果您的函数 f() 采用以下形式

    Vec6 f(const MatrixBase<Derived>& input1,
           const MatrixBase<Derived>& input2,
           const MatrixBase<Derived>& input3)
    {
        Vec6 answer;
    
        //Manipulate answer
        //...
    
        return answer; 
    }
    

    然后在大多数现代编译器上启用优化不会发生复制。请参阅关于返回值优化here 的 Wikipedia 部分。

    (要使用您的对象和编译器测试理论,您可以将 Vec6 包装在您自己的类中,让所有构造函数在执行时打印,并检查您是否获得了预期的构造函数调用次数。)

    【讨论】:

    • 我刚刚玩了一个使用 g++ 7.4 版的玩具示例。它基本上做了复制省略(如我所料),但即使没有启用优化。要显式禁用它,您将设置标志-fno-elide-constructors。这会产生正在构建和销毁的临时副本,这与您想要的相反。
    • 谢谢@ianinini。我的Vec6 只是eigen::Matrix&lt;double, 6,1&gt;,所以我猜它有资格“设计得当”。我将重复您的实验以亲自查看复制省略。
    • @L. Bruce 我也相信 Eigen 设计得很好(但不要自己使用它)所以你几乎肯定是正确的。
    • 我可以确认@ianinini 的发现,即使没有-O 选项(我使用g++ 5.4),临时文件也被优化掉了。另一方面,开关-fno-elide-constructors 强制复制构造函数和临时对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多