Eigen中高效的矩阵转置乘法

7

我可以使用多个矩阵库,但是在这个项目中,我选择使用Eigen,因为它具有编译时定义和包含SVD的功能。

现在,我正在执行以下操作:

Eigen::Matrix<double,M,N> A;     // populated in the code

Eigen::Matrix<double,N,N> B = A.transpose() * A;

据我理解,这个操作是将A进行转置并形成其副本,然后再与A相乘。该操作在相对较小的矩阵上执行(M=20-30,N=3),但每秒要执行数百万次,因此必须尽可能快。
据我了解,使用以下方式会更快:
B.noalias() = A.transpose() * A;

我可以编写自己的子程序来接受A作为输入并填充B,但我想知道是否存在一种高效的现有实现,可以使用最少的周期。


请考虑查看以下内容:http://scicomp.stackexchange.com/questions/25283/beating-typical-blas-libraries-matrix-multiplication-performance - The Quantum Physicist
这个有帮助吗?https://dev59.com/Uprga4cB1Zd3GeqPuPC4 - kennytm
1个回答

7

首先,由于Eigen依赖于模板表达式,A.transpose()不会转化为临时变量。

其次,在:

Matrix<double,N,N> B = A.transpose() * A;

Eigen 知道表达式中不可能出现 B(因为这里编译器调用了 B 的构造函数),因此根本不会创建任何临时对象。这相当于:
Matrix<double,N,N> B;             // declare first
B.noalias() = A.transpose() * A;  // eval later

最后,对于这样的小矩阵,我不认为使用B.selfadjointView().rankUpdate(A)会有所帮助(正如kennytm评论中建议的那样)。

另一方面,当N=3时,值得尝试懒惰实现:

B = A.transpose().lazyProduct(A)

只是为了确保。Eigen内置了启发式算法来选择最佳的乘积实现,但由于启发式算法必须简单快速地评估,因此可能不是100%正确。


谢谢。懒惰项目提示非常有用。现在,我做了完全不同的事情,因为我发现在GPU上,Eigen不能在cuda中工作。虽然我喜欢这个库,但最有效的方法是根本不构建A,这就是我所做的。 - Dar Cos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接