为何Eigen中4x4矩阵乘法速度是3x3的两倍以上?
3x3与4x4矩阵乘法性能异常:为何4x4乘法更快?
测试背景
在开启-O3优化的前提下,使用Eigen库对比3x3(Matrix3d)与4x4(Matrix4d)矩阵乘法的性能,意外发现4x4矩阵乘法的速度是3x3的两倍以上。但在ARM设备上,3x3乘法速度符合预期地比4x4更快。
测试环境与编译命令
编译命令:
g++ -O3 -I/usr/include/eigen3 tmp.cpp
硬件与工具信息:
- CPU:Intel Xeon Silver 4210R(2.4GHz,10核20线程,支持AVX-512F、AVX-512VL等高级SIMD指令集)
- g版本:g (Ubuntu 13.1.0-8ubuntu1~20.04.2) 13.1.0
测试代码
#include <Eigen/Dense> #include <Eigen/Geometry> #include <iostream> #include <vector> #include <chrono> #include <random> #include <valgrind/callgrind.h> void benchmark_matrix3d_multiplication(const std::vector<Eigen::Matrix3d>& matrices) { auto start = std::chrono::high_resolution_clock::now(); Eigen::Matrix3d result = Eigen::Matrix3d::Identity(); for(size_t i = 0; i < matrices.size(); i++) { asm("# 3dmat mult start"); result = result * matrices[i]; asm("# 3dmat mult end"); } auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start); std::cout << "Matrix3d: " << duration.count() << " microseconds" << std::endl; std::cout << result << std::endl; // 防止编译器优化掉计算逻辑 } void benchmark_matrix4d_multiplication(const std::vector<Eigen::Matrix4d>& matrices4) { auto start = std::chrono::high_resolution_clock::now(); Eigen::Matrix4d result = Eigen::Matrix4d::Identity(); for(size_t i = 0; i < matrices4.size(); i++) { asm("# 4dmat mult start"); result = result * matrices4[i]; asm("# 4dmat mult end"); } auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start); std::cout << "Matrix4d: " << duration.count() << " microseconds" << std::endl; std::cout << result << std::endl; // 防止编译器优化掉计算逻辑 } void benchmark_matrix_multiplication() { const int num_matrices = 100000; std::vector<Eigen::Matrix3d> matrices(num_matrices); for(size_t i = 0; i < num_matrices; i++) { auto q = Eigen::Quaterniond::UnitRandom(); matrices[i] = q.toRotationMatrix(); } std::vector<Eigen::Matrix4d> matrices4(num_matrices); for(size_t i = 0; i < num_matrices; i++) { matrices4[i].block<3,3>(0,0) = matrices[i]; } CALLGRIND_START_INSTRUMENTATION; // 启动callgrind分析 benchmark_matrix3d_multiplication(matrices); benchmark_matrix4d_multiplication(matrices4); } int main() { benchmark_matrix_multiplication(); }
测试结果
两种矩阵乘法的计算结果一致,性能数据如下:
Matrix3d: 2008 microseconds 0.440386 -0.897765 -0.00889435 0.808307 0.400777 -0.431298 0.390768 0.182748 0.902166 Matrix4d: 833 microseconds 0.440386 -0.897765 -0.00889435 0 0.808307 0.400777 -0.431298 0 0.390768 0.182748 0.902166 0 0 0 0 0
关键观察
- 通过添加
asm("# 3dmat mult start")等标记定位汇编代码,确认乘法操作未被编译器优化。 - 4x4矩阵乘法对应的汇编指令行数更多,但执行速度反而远超3x3乘法。
问题
该场景下4x4矩阵乘法显著更快的原因是什么?是否存在测试误差?
内容的提问来源于stack exchange,提问作者HiroIshida
相关产品推荐
相关产品推荐

