使用 Eigen C ++ Matrix库,如何有效地使用它 将 n x n 矩阵 A 与 n x m 矩阵 B 相乘 并将结果存储在 A 中?也就是说,我该怎样才能避免 生成一个临时的 n x m 矩阵,而不是存储 结果直接在 B ?
对于 m 非常大的应用程序(例如100000) 比 n (例如3),这绝对有意义,因为它避免了 应用非常大的阵列。
以下代码,我无法开始工作:
#define FOO 2
我认为,内部必须发生的事情是
下列。 B 的每一列应单独处理。
必须将正在考虑的列 B.noalias() = A * B;
复制到备份中
专栏column_i
。然后,
column_tmp
适用于所有 B(row_i, column_i) = A.row(row_i) * column_tmp; // dot-product
= 0到m 。在 Eigen 中有没有办法做到这一点
有效地从优化中获利?
答案 0 :(得分:4)
告诉Eigen你希望产品“就地”发生的最明显方式可能是:
B.transpose() *= A.transpose();
// or B.applyOnTheLeft(A);
说,不能保证这不会导致任何临时,你必须相信内部的本征成本逻辑(Eigen设计师可能知道更好:) ...或检查通过适当的分析表明这是一个真正的问题,而不仅仅是过早的优化),它通过调试器自己完成。
在我的Eigen副本(3.2.7)上,上面直接在MatrixBase::applyThisOnTheRight
表达式上调用Transpose
,这反过来又可能在内部减少到B=A*B
;与applyOnTheLeft
相同,所以在这种情况下你运气不好。
如果你真的需要避免任何 nxm临时,你可以手动执行产品,例如:
for(auto i=0;i<B.cols();++i)
B.col(i) = A * B.col(i);
假设B.rows()
&lt;&lt; B.cols()
,这将消耗更少的额外内存,
但是你可能会错过一些重要的优化;事实上,我想暂时还是可以在这里做出最好的权衡。
答案 1 :(得分:2)
是的3x3倍3xHuge你的逐列评估确实有意义,但不是一般情况下。例如,如果n = m = 1000,那么逐列评估将比当前的本征逻辑慢几个数量级。
如果你写:
B.noalias() = A * B;
Eigen将遵循col-by-col评估(因为A在编译时很小),但结果将是错误的,因为B确实是别名,基本上它会生成:
for j = 0..m-1
B.col(j).noalias() = A * B.col(j);
为了优雅地解决这个问题,我们需要一种方式来说只有不同的列不能别名...建议:
B.transpose() *= A.transpose();
确实是一个选项,让Eigen在编译时知道这种信息,虽然必须转置双方有点麻烦。并且需要在Eigen方面实施适当的评估逻辑。目前,此信息未被利用。
答案 2 :(得分:1)
B.noalias() = A * B;
的示例与“#34”不匹配&#34;将结果存储在A&#34;中。 所需要的只是A *= B;
。如果你改为做打算覆盖B
,那么你撒谎 .noalias()