微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

什么是特征中的伪表达式?

如何解决什么是特征中的伪表达式?

完整使用该术语的文档,例如

Pseudo expression providing partial reduction operations
Pseudo expression providing matrix output with given format

但我找不到它的意思。

解决方法

我相信 Eigen 文档所指的“伪表达式”实际上是“expression templates”的实例。

在 C++ 中,在实现数学库或任何领域中的真正库时,使用表达式模板是一种常用技术,在这些领域中,用户将多个计算连接在一起以构建一个值。

表达式模板的想法是,它们是一种将计算推迟到实际需要计算的方法,并允许对计算的实际执行方式进行额外程度的控制,例如如果可以在不改变输入参数的情况下逐项执行整个计算,则您可能不需要为临时可能较大的对象分配内存。

无论如何,就作为 Eigen 的用户而言,除了一个细节之外,您实际上并不需要了解它对表达式模板的使用。永远不要写这样的代码:

auto to_canonical_coords = get_rotation_matrix(theta) * get_translation_matrix(offset);

问题在于对操作进行类型推导,这里的 operator* 返回一个表达式模板实例。表达式模板实例是短暂的;这样的赋值会将表达式模板实例分配给一个变量,其中它可能比它通过引用引用的对象更长寿或导致其他问题。而是像上面那样写

Eigen::Matrix<double,3,3> to_canonical_coords = get_rotation_matrix(theta) * get_translation_matrix(offset);

或对 Eigen::Matrix<double,3> 使用类型别名的等效项。

Eigen 文档提到了问题 here。此外,我相信 Scott Meyers 在Effective Modern C++ 中的某个地方通常会讨论这个问题。

,

我认为示例是展示其工作原理的好方法。想象一下这样的代码片段:

void print_types(const Eigen::Matrix<double,3>& test) {
    std::cout << typeid(test).name() << "\n";
    std::cout << typeid(test.transpose()).name() << "\n";
    std::cout << typeid(test.transpose().eval()).name() << "\n";
}

如果没有 Eigen 所做的表达式模板编程,您会期望所有这三个都打印出相同的内容:Eigen::Matrix<double,3>

但是转置操作实际上不需要在使用之前需要进行评估 - 就像如果您要执行 A.T * B,您实际上永远不需要存储转置A 矩阵,您可以更改条目相乘的顺序。所以第二个打印输出的实际解混结果是Eigen::Transpose<Eigen::Matrix<double,3>>Eigen::Transpose<...> 的行为与普通的 Eigen::Matrix 非常相似,但实际上并不需要计算转置。对于简单的 3x3 矩阵,大多数情况下可能不会有很大的改进,但对于巨型矩阵,跳过计算可能会带来非常大的性能提升。

调用 .eval()(就像在第三个打印输出中)会将任何中间特征类型转换回实际的矩阵类型(通过实际进行计算),因此第三行将打印相同的 Eigen::Matrix<double,3>

这也适用于其他表达式,例如 typeid(test * test + test).name(),您会看到:

Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<double,double>,Eigen::Product<Eigen::Matrix<double,3>,Eigen::Matrix<double,0> const,3> const>

这允许 Eigen 更好地优化最终结果的计算方式,但跳过任何中间计算。

我希望这是有道理的,如果没有,请随时发表评论!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。