Eigen问题:为什么模板表达式场景下Map比Vector3d性能更差?
Eigen::Map在表达式中使用的注意事项
你观测到的性能差异本质和Eigen模板表达式的对齐优化策略有关,而非Eigen::Map本身的指针包装有额外开销,具体原因和使用注意事项如下:
初始测试Map性能更差的原因
Eigen::Vector3d是栈上分配的固定大小向量,Eigen默认会保证其内存对齐,在默认编译参数下,这类对齐的小尺寸向量参与模板表达式运算时,会自动启用SIMD向量化优化。而你构造Eigen::Map时用了默认参数,也就是Eigen::Unaligned,不假设指向的std::vector内存是对齐的,所以Eigen不会对这类Map参与的表达式做对齐SIMD优化,运算效率更低。Vector3d构造时会把std::vector里不对齐的内存拷贝到自身对齐的栈内存中,拷贝3个double的开销远低于SIMD优化带来的收益,所以第一次测试中Vector3d版本性能比Map版本更好。
逐元素计算后性能持平的原因
你手动把Eigen模板表达式拆成逐元素算术操作后,相当于绕开了Eigen的表达式优化逻辑,不管是Map还是Vector3d最后都会被编译器处理成标量运算,没有SIMD优化的差异,所以三者性能基本一致。
Eigen::Map参与表达式运算的注意事项
- 主动指定对齐参数:如果你的源内存确实满足对齐要求(比如使用
Eigen::aligned_allocator分配std::vector,或者手动保证每个顶点起始地址符合Eigen的对齐规则),可以给Map显式指定Eigen::Aligned模板参数,即可享受和栈上Vector完全一致的优化,性能没有差异:Eigen::Map<const Eigen::Vector3d, Eigen::Aligned> x0{&V[v0 * 3]}; - 小尺寸向量的特殊处理:对于3维、2维这种极小的向量,如果源内存无法保证对齐,直接构造
Eigen::Vector3d拷贝内存再参与运算,性能反而比直接用未对齐的Map更高,和直觉相反但实测符合性能表现。 - 控制表达式复杂度:如果表达式中嵌套了多个未对齐的Map,Eigen的优化器更容易出现优化失效的情况,对性能敏感的场景可以先把Map显式求值为
Vector3d再参与运算。 - 编译参数影响:如果编译时开启
-DEIGEN_UNALIGNED_VECTORIZE=1选项,Eigen也会对未对齐的内存做向量化处理,此时Map和Vector3d的性能差异会消失,但这类非对齐向量化在部分老旧CPU上反而会出现性能倒退。
内容的提问来源于stack exchange,提问作者luczzz
相关产品推荐
相关产品推荐

