代码之家  ›  专栏  ›  技术社区  ›  Daiver

通过外部分配的数据调用特征gemm

  •  0
  • Daiver  · 技术社区  · 6 年前

    Eigen具有惊人的快速GEMM实现,所以我想在我的pet项目张量库中使用它。 如果我理解正确,可以通过eigen::map。我写了一个简单的例子 EIGEN_NO_MALLOC 以确保没有不需要的分配。

    它很适合简单的矩阵乘法 C += A * B 是的。 但不幸的是它不能处理 C += alpha * A * B (gemm-like)情况。

    #include <iostream>
    #include <vector>
    
    #define EIGEN_NO_MALLOC
    #include "Eigen/Core"
    
    int main()
    {
        using Scalar = float;
        using namespace Eigen;
        std::vector<Scalar> aDat = {1, 2, 3, 4};
        std::vector<Scalar> bDat = {1, 2, 3, 4};
        std::vector<Scalar> cDat = {1, 2, 3, 4};
        Map<Matrix<Scalar, -1, -1, RowMajor>, Unaligned> a(aDat.data(), 2, 2);
        Map<Matrix<Scalar, -1, -1, RowMajor>, Unaligned> b(bDat.data(), 2, 2);
        Map<Matrix<Scalar, -1, -1, RowMajor>, Unaligned> c(cDat.data(), 2, 2);
    
        //Ok
        c.noalias() += a * b;
    
        //Assertion `false && "heap allocation is forbidden.....
        c.noalias() += 2 * a * b;
    
        return 0;
    }
    

    c.noalias() += 2 * a * b; 给出以下运行时错误

    a.out: path_to_eigen/Eigen/src/Core/util/Memory.h:129: void Eigen::internal::check_that_malloc_is_allowed(): Assertion `false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)"' failed.
    

    可以打电话吗 c.noalias() += someScalar * a * b; 没有分配?

    PS我的特征版本是 3.3.2 ,请 gcc 版本是 7.2.0

    对不起我英语不好

    1 回复  |  直到 6 年前
        1
  •  3
  •   chtz    6 年前

    这看起来像是一个小规模优化引入的bug。对于产品 (KxM)*(MxN) 哪里 K+M+N < EIGEN_GEMM_TO_COEFFBASED_THRESHOLD (默认为 20 ,eigen切换到一个懒惰的产品实现,它显然认为对临时产品进行评估是一个好主意。你的例子实际上很有效,例如 5x5 * 5x10 产品。

    我为此问题提交了一个bug: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1562

    如果您想快速解决问题,请定义 -D EIGEN_GEMM_TO_COEFFBASED_THRESHOLD=1 ,这将始终使用 大矩阵 -GEMM实施。

    另一方面,如果在编译时知道矩阵的大小,则最好使用相应的固定大小类型( Matrix<Scalar, 2, 2, RowMajor> 在你的情况下)。