C++ Eigen填充矩阵时可否效仿Matlab向量化减少嵌套for循环?
Eigen向量化填充矩阵的实现方案
完全可以实现目标的两种向量化写法,不管是对齐Matlab逻辑仅去掉一层嵌套循环,还是完全消掉两层手写循环的纯向量化填充,Eigen都原生支持,且性能通常优于手写双层循环(自动触发SIMD指令优化)。
对齐Matlab逻辑:仅保留一层外层循环
这种写法和你给出的Matlab示例逻辑完全一致,只需预先生成存储列索引的行向量,遍历行索引时直接给整行赋值即可,不需要手写内层的列循环。对应C++代码如下:
int M = 3; int N = 4; MatrixXd A(M, N); // 生成和Matlab N_Vec 等价的行向量,元素值为0,1,2,...N-1 RowVectorXd N_Vec = RowVectorXd::LinSpaced(N, 0, N-1); // 仅保留一层外层循环,和Matlab示例逻辑完全对齐 for (int i = 0; i < M; i++) { // i为标量,自动广播到整行位置,逐元素计算sin A.row(i) = (i + N_Vec).array().sin(); }
执行过程和Matlab的逐行赋值完全等价,Eigen会自动将标量i广播到整行所有列的位置,不需要手动编写列索引的循环逻辑。
纯向量化实现:完全去掉两层手写循环
该写法利用Eigen的广播机制+表达式模板,不需要编写任何手写for循环即可完成全矩阵填充,实现逻辑如下:
- 生成存储行索引的列向量:形状为
M×1,元素值从0到M-1 - 生成存储列索引的行向量:形状为
1×N,元素值从0到N-1 - 不同形状的向量相加时,Eigen会自动按广播规则生成
M×N形状的矩阵,再通过数组接口逐元素计算sin,得到目标矩阵
对应代码如下:
int M = 3; int N = 4; // 生成行索引列向量:M行1列,值为0,1,...M-1 VectorXd M_Vec = VectorXd::LinSpaced(M, 0, M-1); // 生成列索引行向量:1行N列,值为0,1,...N-1 RowVectorXd N_Vec = RowVectorXd::LinSpaced(N, 0, N-1); // 全向量化生成矩阵:自动广播后逐元素计算sin MatrixXd A = (M_Vec + N_Vec).array().sin().matrix();
整个计算过程由Eigen的表达式模板在编译期完成优化,不会产生中间临时矩阵的内存拷贝,性能通常优于手动编写的双层循环。
注意:逐元素的数学函数(如
sin、cos)需要通过.array()接口将矩阵/向量转为Eigen的Array类型才能调用,原生Matrix类型的接口仅支持线性代数类运算,不提供逐元素的数学函数。
内容的提问来源于stack exchange,提问作者csss
相关产品推荐
相关产品推荐

