【问题标题】:Mixing Scalar Types in Eigen在 Eigen 中混合标量类型
【发布时间】:2017-01-05 20:39:57
【问题描述】:
#include <iostream>

#include <Eigen/Core>

namespace Eigen {

// float op double -> double
template <typename BinaryOp>
struct ScalarBinaryOpTraits<float, double, BinaryOp> {
  enum { Defined = 1 };
  typedef double ReturnType;
};

// double op float -> double
template <typename BinaryOp>
struct ScalarBinaryOpTraits<double, float, BinaryOp> {
  enum { Defined = 1 };
  typedef double ReturnType;
};

}

int main() {
    Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> m1(2, 2);
    m1 << 1, 2, 3, 4;

    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> m2(2, 2);
    m2 << 1, 2, 3, 4;

    std::cerr << m1 * m2 <<std::endl;  // <- boom!!
}

我想知道为什么上面的代码不能编译。 Here 是完整的错误消息。请注意,如果我将 m1m2 定义为具有固定大小,则可以正常工作。

我正在使用Eigen3.3.1。它在运行 OSX-10.12 并使用 Apple 的 clang-800.0.42.1 的 Mac 上进行了测试。

【问题讨论】:

    标签: eigen eigen3


    【解决方案1】:

    这是因为一般的matrix-matrix产品经过了高度优化,采用了激进的手动向量化、流水线、多级缓存等。这部分不支持混合float和double。您可以使用m1.lazyProduct(m2) 绕过这个高度优化的实现,它对应于用于小型固定大小矩阵的实现,但这样做只有缺点:ALU 不支持混合浮点和双精度,因此必须提升浮点值无论如何加倍,你将失去矢量化。最好将浮点数显式转换为双精度:

    m1.cast<double>() * m2
    

    【讨论】:

    • 实际上,我真正的问题是定义自定义标量类型T1T2。我发现使用ScalarBinaryOpTraits 最有效,但不适用于T1T2 的两个动态大小的特征矩阵的乘法。我使用doublefloat 来简化示例。
    • 我想知道以下其中一项是否适合您: 1. 为 T1T2 的特征矩阵显式提供运算符重载 operator*(可能在它) 2. 为T1T2 提供Eigen::internal::general_matrix_matrix_product 的专业化。如果这是要走的路,有没有这样做的好例子?
    • 我们真的应该绕过自定义标量类型的繁重代码。这将是 3.4 的情况,并且可能向后移植到某些 3.3.x 版本。同时,您确实可以将general_matrix_matrix_product 专业化为there,或者也可以关注此piece of code
    • @ggael Stan(和我)are discussing this matrix multiplication issue 的开发人员在他们的论坛上在他们的自动微分类型上实现了std::complex 数学。希望您有任何想法(无论是那里还是这里)。
    • @ggael 不确定我是否在最后一条评论中正确地标记了你,所以我只是确保我正确地完成了它。对不起,如果它双重通知你。
    猜你喜欢
    • 2016-09-07
    • 2017-03-18
    • 2011-02-12
    • 2015-11-04
    • 1970-01-01
    • 2019-07-02
    • 1970-01-01
    • 2014-01-10
    • 2018-05-12
    相关资源
    最近更新 更多