如何在Eigen中高效存储矩阵乘法结果以降低内存占用
优化Eigen矩阵乘法内存占用的方案
问题根源
你当前的代码中,每次循环执行A.transpose() * B时,Eigen会创建一个临时矩阵存储乘法结果,之后再通过reshaped转成视图并赋值给C.row(i)。即使使用noalias(),也只是避免了赋值时的临时拷贝,但乘法本身产生的临时矩阵依然会占用额外内存,循环多次后内存占用会显著上升。
核心优化思路
让Eigen直接将矩阵乘法的结果写入C.row(i)的内存空间,完全跳过中间临时矩阵的创建。关键是让乘法表达式的输出维度与目标内存的维度匹配,或者通过转置目标来匹配乘法结果的维度。
具体实现方案
假设A.transpose() * B的计算结果是C_col×1的列向量(这也是你需要reshaped(1, C_col)转成行向量的原因),可以直接将C.row(i)转置为列向量作为乘法的输出目标:
for (int i = 0; i < C_row; ++i) { // 直接将乘法结果写入C.row(i)的内存,无临时矩阵 C.row(i).transpose().noalias() = A.transpose() * B; }
为什么这样有效?
C.row(i).transpose()返回的是C.row(i)内存的列向量视图,没有额外内存开销。noalias()告诉Eigen不需要创建临时矩阵,可以直接将A.transpose() * B的计算结果写入目标内存。- 彻底消除了原代码中乘法步骤产生的临时矩阵,内存占用会大幅降低。
其他补充优化
- 确保内存连续访问:你的
C是RowMajor布局的Map,C.row(i)本身是连续内存块,符合Eigen的高效计算要求,无需额外调整。 - 编译优化:开启编译器的O2/O3优化选项,Eigen会进一步优化表达式模板的执行,减少不必要的内存操作。
- 复用临时内存(备选):如果因为维度匹配问题无法直接写入目标内存,可以预先分配一个临时向量循环复用,避免每次循环重新分配:
Eigen::Matrix<float, -1, 1> temp(C_col); for (int i = 0; i < C_row; ++i) { temp.noalias() = A.transpose() * B; C.row(i) = temp.transpose(); }
内容的提问来源于stack exchange,提问作者Lei Gao
相关产品推荐
相关产品推荐

