艾根C++;就地矩阵乘法
Eigen C++; In-place matrix multiplication
使用特征C++矩阵库,如何才能有效地 将 n x n 矩阵A与n x m矩阵B相乘并将结果存储在A中?也就是说,我该如何避免 生成一个临时的n x m矩阵,改为存储 结果直接在B中?
适用于m非常大的应用(例如 100000) 比n(例如 3),这绝对是有意义的,因为它避免了 非常大的阵列的应用。
下面的代码,我无法开始工作:
B.noalias() = A * B;
我认为,内部必须发生的事情是 以下。B的每一列都应单独处理。 必须将考虑column_i
列复制到备份 列column_tmp
.然后
B(row_i, column_i) = A.row(row_i) * column_tmp; // dot-product
对于所有column_i
=0 到 m。有没有办法在特征中做到这一点 高效并从其优化中获利?
告诉 Eigen 您希望产品"就地"发生的最明确方式可能是:
B.transpose() *= A.transpose();
// or B.applyOnTheLeft(A);
也就是说,不能保证这不会在任何临时情况下产生,您必须为此信任内部特征成本逻辑(特征设计师可能更了解:)......或者通过调试器自己检查,在适当的分析表明这是一个真正的问题而不仅仅是过早的优化之后)。
在我的 Eigen 副本 (3.2.7) 上,上面的直接在Transpose
表达式上调用MatrixBase::applyThisOnTheRight
,这反过来又可悲地减少到内部B=A*B
;applyOnTheLeft
也是如此,所以在这种情况下你不走运。
如果您确实需要避免任何nxm 临时,您可以手动按矢量执行产品,如下所示:
for(auto i=0;i<B.cols();++i)
B.col(i) = A * B.col(i);
假设B.rows()
<<B.cols()
,这将消耗更少的额外内存, 但您可能会在这里错过一些重要的优化;事实上,我想有一个临时仍然可以在这里给出最好的权衡。
是的,对于 3x3 乘以 3xHuge,您的逐列评估确实有意义,但在一般情况下并非如此。例如,如果 n=m=1000,则逐列计算将比当前特征逻辑慢几个数量级。
如果你写:
B.noalias() = A * B;
Eigen 将遵循逐个 col 的计算(因为 A 在编译时很小),但结果将是错误的,因为 B 确实有别名,基本上它会生成:
for j = 0..m-1
B.col(j).noalias() = A * B.col(j);
为了优雅地解决这个问题,我们需要一种方法来说明只有不同的列不别名......提议:
B.transpose() *= A.transpose();
确实是一个选项,让 Eigen 在编译时知道这种信息,尽管必须转置双方有点麻烦。而正确的评估逻辑仍然需要在艾根这边实现。目前未利用此信息。
您的B.noalias() = A * B;
示例与"将结果存储在 A 中"不匹配。您所需要的只是A *= B;
.如果你确实打算覆盖B
,那么你是在撒谎.noalias()
- 有根的二进制搜索树.保留与其父级的链接
- 根中的组合
- 套接字连接"Operation not permitted"错误,甚至使用升压/平发器根.cpp
- 比根<操作员
- 使用根/C++时出错:没有匹配的构造函数来初始化'TTree'
- 在字符数组 (C++/根) 中查找双精度值
- 如何从命令行使用 cmake 为有根的安卓设备制作可执行文件?
- 从网站复制证书,并使用脚本将其添加到受信任的根证书颁发机构
- 可以告诉艾达不要抓住EXCEPTION_ACCESS_VIOLATION吗?
- 从根权限进程创建可访问的文件
- 提升图库示例 凯文培根的六度:示例中的 Vertex() 是什么
- 当包含头文件的文件不在根项目文件夹中时,如何包含它
- 如何遍历几个每小时一次的根(.root)文件,并将它们组合成更大的每日数据.root文件?
- 为什么我的二叉树会覆盖其根的叶子?
- C++没有标准功能的立方体根查找器
- 艾根C++;就地矩阵乘法
- 我可以将艾根·莱文伯格·马夸特与线性方程和常数雅可比矩阵一起使用吗?
- 艾根·雅各比 SVD
- 艾根的胆汁从国会议员中受益吗?
- 记忆在艾根中是如何布局的