Eigen 开源线性代数库深度实战:从零到一写出高性能矩阵代码
一、Eigen 是什么?先打个通俗的比方
假设你要做一道"土豆炖牛肉",需要自己种土豆、养牛、切菜、生火、调味……这就是手写矩阵运算:一个矩阵乘法要自己写三层 for 循环,还要操心内存对齐、缓存命中、SIMD(单指令多数据)优化。
而 Eigen 就像一间"中央厨房":你只需要说"我要两斤土豆、一斤牛肉,按菜谱做",后厨就帮你把洗、切、炖、调味全部搞定。
官方一句话:Eigen 是一个纯 C++ 模板实现的线性代数库,提供矩阵、向量、数值求解器以及相关算法。它是开源免费的(MPL2 许可证),几乎只靠头文件就能用。
它最与众不同的地方是:把"数学表达式"编译成"最优机器码",性能可以媲美手写汇编级别的 BLAS 库(如 Intel MKL、OpenBLAS),但用法却像数学公式一样自然。
二、为什么要用 Eigen?(使用优点)
2.1 性能极佳:表达式模板(Expression Templates)
Eigen 的核心魔法是 表达式模板。普通写法 A = B + C + D 会创建多个临时矩阵:
temp1 = B + C // 第一次分配内存 temp2 = temp1 + D // 第二次分配内存 A = temp2 // 第三次拷贝
Eigen 会把整个表达式揉成一个"惰性求值"的表达式对象,最终只遍历一次、只写一次内存,中间不产生任何临时矩阵。这在数值计算里是数量级的性能差距。
2.2 无依赖、跨平台、头文件即用
Eigen 不需要编译安装(传统用法),你只需要把头文件目录 include 进来。Windows / Linux / macOS / Android / iOS 全平台可用,编译时也几乎不需要额外链接库(个别模块除外)。
2.3 自动 SIMD 加速与对齐优化
在 x86 上,Eigen 会自动使用 SSE / AVX / AVX2 指令集;在 ARM 上自动使用 NEON。你不需要写一行汇编,只要开启优化编译选项即可。
2.4 API 像数学公式一样直观
矩阵乘法在 Eigen 里就是 A * B,转置就是 A.transpose(),求逆就是 A.inverse()。代码可读性极高,几乎不会引入"行数/列数写反"这种低级错误——因为 Eigen 在编译期就帮你检查维度是否匹配。
2.5 生态成熟、被工业界广泛采用
Eigen 被无数重量级项目使用:ROS(机器人操作系统)、Ceres Solver(谷歌的优化库)、TensorFlow 的早期版本、OpenCV 的一部分、游戏引擎等。遇到问题有大量社区资料可查。
三、Eigen 适合用在哪些场景?(使用场景)
| 场景 | 具体例子 | 为什么选 Eigen |
|---|---|---|
| 机器人 / SLAM 定位 | 姿态矩阵、坐标变换、卡尔曼滤波 | 矩阵运算密集 + 实时性要求高 |
| 机器学习/深度学习算子 | 全连接层 W*x + b、激活函数、归一化 | 高性能矩阵乘法 + 易与 Eigen 张量模块配合 |
| 计算机视觉 | 相机内参标定、透视变换、单应矩阵 | 与 OpenCV 无缝互转(Map 零拷贝) |
| 物理引擎 / 游戏 | 刚体动力学、碰撞检测中的矩阵运算 | 实时性 + 固定尺寸矩阵零堆分配 |
| 金融量化 | 协方差矩阵、PCA 主成分分析、线性回归 | 有稠密/稀疏矩阵、特征值分解等全套工具 |
| 科学计算 | 解线性方程组、最小二乘、插值拟合 | 数值稳定算法齐全(LU/QR/Cholesky/SVD) |
| 嵌入式 / 移动端 | IMU 姿态解算、传感器融合 | 头文件库、可裁剪、支持 NEON 加速 |
一句话总结:凡是"要算矩阵/向量/解方程"的 C++ 项目,都可以考虑 Eigen。
四、快速上手:安装 Eigen(5 种方式)
方式 1:直接下载头文件(最省事,推荐新手)
- 打开官网:https://eigen.tuxfamily.org
- 下载最新稳定版压缩包(如 eigen-3.4.0.tar.gz)
- 解压后,把 Eigen/ 目录复制到你的项目 include 路径下即可
# 假设解压到 D:\libs\eigen-3.4.0,里面有一个 Eigen 子目录
# 编译时只需要指定头文件路径,不需要链接任何库
g++ -I D:/libs/eigen-3.4.0 main.cpp -o main.exe # -I 指定头文件搜索目录
方式 2:vcpkg(Windows 首选)
vcpkg install eigen3 # 安装 Eigen 3
vcpkg integrate install # 自动集成到 MSBuild
方式 3:Conan
conan install eigen/3.4.0@ # 在 conanfile.txt 或命令行安装
方式 4:Linux apt
sudo apt install libeigen3-dev # Ubuntu / Debian 系
安装后头文件位于 /usr/include/eigen3/Eigen/,编译时:
g++ -I /usr/include/eigen3 main.cpp -o main # 需要显式指定 eigen3 子目录
方式 5:CMake 集成(项目级推荐)
find_package(Eigen3 REQUIRED) # 查找 Eigen3 配置
add_executable(demo main.cpp) # 添加可执行文件目标
target_link_libraries(demo Eigen3::Eigen) # 链接 Eigen(实际只加头文件路径)
⚠️ 预警 1:Eigen 是模板库,几乎全部实现都在头文件里,所以编译时间会比较长。首次编译请耐心,后续增量编译会快很多。
五、具体使用方式:小白分步实操
下面所有示例都基于以下标准头文件:
#include <iostream>
#include <Eigen/Dense> // 稠密矩阵/向量:最常用,包含所有核心功能
// 如果还需要稀疏矩阵,再加:
// #include <Eigen/Sparse>
第 1 步:声明矩阵和向量
#include <iostream>
#include <Eigen/Dense>
int main() {
// 1.1 固定尺寸矩阵:3 行 3 列,编译期就定死,零堆分配,性能最好
Eigen::Matrix3d m3; // double 类型的 3x3 矩阵(d=double)
// 1.2 动态尺寸矩阵:行数列数运行时决定,可随时 resize
Eigen::MatrixXd m; // 动态大小的 double 矩阵(X=动态,d=double)
m.resize(4, 5); // 变成 4 行 5 列
// 1.3 向量本质就是 Nx1 或 1xN 的矩阵
Eigen::Vector3d v; // 3 维列向量(double)
Eigen::VectorXd vd(10); // 10 维动态列向量
Eigen::RowVector3d rv; // 3 维行向量
// 1.4 整数/浮点/复数也可以:MatrixXi 是 int 矩阵,MatrixXcf 是复数矩阵
Eigen::MatrixXi mi(2, 2); // int 类型的 2x2 矩阵
return 0;
}
命名规则速记(非常重要,记不住就看这个表):
| 类型写法 | 含义 |
|---|---|
| Matrix3d | 固定 3×3,double |
| Matrix3f | 固定 3×3,float |
| MatrixXd | 动态大小,double |
| Vector3d | 固定 3 维列向量,double |
| VectorXf | 动态列向量,float |
| RowVector4i | 固定 4 维行向量,int |
| MatrixXcf | 动态矩阵,复数 float |
前缀 Matrix 后第一个数字是"固定行数",第二个是"固定列数";字母 X 表示动态。d/f/i/cf/cd 表示元素类型(double/float/int/complex/complex)。
第 2 步:给矩阵赋值
#include <iostream>
#include <Eigen/Dense>
int main() {
// 2.1 用逗号初始化器(Comma Initializer)直接填数:按行填入
Eigen::Matrix2d A;
A << 1.0, 2.0,
3.0, 4.0; // 结果:[[1,2],[3,4]]
std::cout << "A =\n" << A << std::endl;
// 2.2 用括号按行、列索引赋值
Eigen::MatrixXd B(3, 3);
B(0, 0) = 10; // 第 0 行第 0 列
B(1, 2) = 20; // 第 1 行第 2 列
// 2.3 向量下标赋值(向量只有一个维度,用圆括号或方括号都行)
Eigen::Vector3d v;
v(0) = 1.0; // 第 0 个分量
v[1] = 2.0; // 第 1 个分量(方括号也可)
v(2) = 3.0;
// 2.4 特殊矩阵一行搞定
Eigen::Matrix3d Zero = Eigen::Matrix3d::Zero(); // 全零矩阵
Eigen::Matrix3d One = Eigen::Matrix3d::Ones(); // 全一矩阵
Eigen::Matrix3d I = Eigen::Matrix3d::Identity();// 单位矩阵(对角为 1)
Eigen::Matrix3d Rnd = Eigen::Matrix3d::Random(); // 随机矩阵(-1~1 均匀分布)
std::cout << "单位矩阵 I =\n" << I << std::endl;
return 0;
}
第 3 步:矩阵与向量的基本运算
#include <iostream>
#include <Eigen/Dense>
int main() {
Eigen::Matrix3d A;
A << 1, 2, 3,
4, 5, 6,
7, 8, 9;
Eigen::Vector3d v(1, 2, 3);
// 3.1 加减法:要求维度完全一致,Eigen 在编译期就检查
Eigen::Matrix3d B = A + A; // 矩阵加法
Eigen::Matrix3d C = A - A; // 矩阵减法
// 3.2 标量乘除
Eigen::Matrix3d D = A * 2.0; // 每个元素乘以 2
Eigen::Matrix3d E = A / 4.0; // 每个元素除以 4
// 3.3 矩阵乘法(这才是核心)
Eigen::Matrix3d F = A * A; // 矩阵乘矩阵(数学意义的标准乘法)
Eigen::Vector3d y = A * v; // 矩阵乘向量
// 3.4 逐元素运算(component-wise),注意和 3.3 的区别!
Eigen::Matrix3d G = A.cwiseProduct(A); // 逐元素相乘(Hadamard 积)
Eigen::Matrix3d H = A.cwiseQuotient(A); // 逐元素相除
// 3.5 转置、求逆、行列式、迹
Eigen::Matrix3d At = A.transpose(); // 转置
Eigen::Matrix3d Ai = A.inverse(); // 逆矩阵(能求出来但不推荐频繁用,见 FAQ)
double det = A.determinant(); // 行列式
double tr = A.trace(); // 迹(对角线元素之和)
std::cout << "A * v =\n" << y << std::endl;
std::cout << "det(A) = " << det << std::endl;
return 0;
}
第 4 步:块操作(Block)与切片——处理子矩阵
#include <iostream>
#include <Eigen/Dense>
int main() {
Eigen::MatrixXd M(4, 4);
M << 1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16;
// 4.1 取连续块:第 1 行第 1 列开始,取 2 行 2 列
Eigen::MatrixXd block = M.block<2, 2>(1, 1); // 编译期定大小的块,性能最优
Eigen::MatrixXd block2 = M.block(1, 1, 2, 2); // 运行时定大小的块
// 4.2 取某一行 / 某一列
Eigen::VectorXd row1 = M.row(1); // 第 1 行(返回 1x4)
Eigen::VectorXd col2 = M.col(2); // 第 2 列(返回 4x1)
// 4.3 取左上角 / 右下角等(固定尺寸版)
Eigen::MatrixXd tl = M.topLeftCorner<2, 2>(); // 左上角 2x2
Eigen::MatrixXd br = M.bottomRightCorner<2, 2>(); // 右下角 2x2
// 4.4 块不仅能读,还能写!这行把左上角 2x2 全部改成 0
M.block<2, 2>(0, 0).setZero();
std::cout << "修改后的 M =\n" << M << std::endl;
return 0;
}
第 5 步:解线性方程组 A·x = b(工程中最常见需求)
背景:解方程组是最常见的数值计算任务。Eigen 提供了多种求解器,不同求解器适合不同矩阵类型,用错了性能会差很多甚至解不出来。
#include <iostream>
#include <Eigen/Dense>
int main() {
// 5.1 构建方程组:2x + y = 5
// x + 3y = 10
Eigen::Matrix2d A;
A << 2, 1,
1, 3;
Eigen::Vector2d b(5, 10);
// 5.2 方式一:PartialPivLU(部分主元 LU 分解),通用型,最保险
Eigen::Vector2d x1 = A.partialPivLu().solve(b); // x1 = [1, 3]
// 5.3 方式二:QR 分解,对"病态"(接近奇异)矩阵更稳
Eigen::Vector2d x2 = A.colPivHouseholderQr().solve(b);
// 5.4 方式三:LLT(Cholesky 分解),要求 A 是"对称正定"矩阵,速度最快
// 先构造一个对称正定矩阵:S = A^T * A
Eigen::Matrix2d S = A.transpose() * A;
Eigen::Vector2d x3 = S.llt().solve(A.transpose() * b);
std::cout << "解 x1 = " << x1.transpose() << std::endl;
std::cout << "解 x2 = " << x2.transpose() << std::endl;
std::cout << "解 x3 = " << x3.transpose() << std::endl;
return 0;
}
求解器选择速查表:
| 求解器 | 对矩阵的要求 | 速度 | 适用场景 |
|---|---|---|---|
| partialPivLu() | 方阵、可逆 | 中 | 通用首选,矩阵不特殊时用它 |
| colPivHouseholderQr() | 任意(含非方阵、最小二乘) | 中 | 最稳,病态矩阵用它 |
| llt() | 对称正定 | 快 | 协方差、能量最小化问题 |
| ldlt() | 对称(允许半正定) | 快 | 比 LLT 更通用 |
| fullPivLu() | 方阵 | 慢 | 需要秩信息时 |
| bdcSvd() | 任意 | 慢 | 最稳但最慢,一般最后选 |
⚠️ 预警 2:不要用 A.inverse() * b 解方程!它会先完整求逆矩阵(O(n³) 且数值误差大),再乘向量。正确做法永远是 A.partialPivLu().solve(b) 这类"分解后求解",速度快一个数量级且更稳定。
第 6 步:特征值与特征向量(PCA、振动分析的核心)
#include <iostream>
#include <Eigen/Dense>
int main() {
// 6.1 构造一个对称矩阵(特征值一定是实数,便于演示)
Eigen::Matrix2d S;
S << 2, 1,
1, 2;
// 6.2 用 SelfAdjointEigenSolver 求特征值和特征向量
// 注意:该求解器要求矩阵对称(自伴),这能保证数值稳定性
Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> solver(S);
if (solver.info() != Eigen::Success) { // 检查求解是否成功
std::cout << "特征值求解失败" << std::endl;
return 1;
}
Eigen::Vector2d eigenvalues = solver.eigenvalues(); // 特征值(升序排列)
Eigen::Matrix2d eigenvectors = solver.eigenvectors(); // 每一列是一个特征向量
std::cout << "特征值 = " << eigenvalues.transpose() << std::endl;
std::cout << "特征向量矩阵 =\n" << eigenvectors << std::endl;
// 6.3 验证:S * v = λ * v(误差应该接近 0)
Eigen::Vector2d v0 = eigenvectors.col(0); // 取第 0 个特征向量
double lambda0 = eigenvalues(0); // 对应的特征值
Eigen::Vector2d err = S * v0 - lambda0 * v0;
std::cout << "验证误差 = " << err.norm() << std::endl; // 应为接近 0 的小数
return 0;
}
第 7 步:与 std::vector / 原始数组 零拷贝互转(Map)
真实项目里,数据往往来自 std::vector、传感器驱动数组或 OpenCV 的 cv::Mat。Eigen 提供 Map(映射)类,可以直接"套壳"已有内存,不拷贝数据,性能零损失。
#include <iostream>
#include <vector>
#include <Eigen/Dense>
int main() {
// 7.1 从 std::vector 映射成 Eigen 矩阵(行主序,比如按行存放的 3x3 数据)
std::vector<double> raw = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// 参数:首元素指针, 行数, 列数;默认按列主序,需指定 RowMajor 表示"行主序"
Eigen::Map<Eigen::Matrix<double, 3, 3, Eigen::RowMajor>> mat(raw.data());
std::cout << "映射后的矩阵 =\n" << mat << std::endl;
// 7.2 从原始数组映射成向量
double arr[4] = {1.0, 2.0, 3.0, 4.0};
Eigen::Map<Eigen::Vector4d> vec(arr); // 直接包住 arr,没有拷贝
std::cout << "映射向量 = " << vec.transpose() << std::endl;
// 7.3 反向操作:把 Eigen 矩阵写回 std::vector
Eigen::MatrixXd M = Eigen::MatrixXd::Random(2, 3);
std::vector<double> back(M.data(), M.data() + M.size()); // 拷贝到 vector
return 0;
}
⚠️ 预警 3:Map 只是"套壳",不拥有内存。原数组/vector 的生命周期必须比 Map 对象更长,否则 Map 就成了悬空指针,读到垃圾数据甚至崩溃。另外 Eigen 默认列主序(column-major)存储,和 C 语言的行主序数组互转时务必用 RowMajor 或仔细核对索引。
第 8 步:性能优化四板斧(决定快慢的关键)
// 8.1 编译时务必开启优化(这是 Eigen 性能的第一前提)
// g++ -O2 -march=native main.cpp -o main
// -O2:开启优化;-march=native:让编译器使用本机 CPU 的全部指令集(AVX2 等)
// 8.2 固定尺寸矩阵优先(编译期尺寸 = 零堆分配 + 全内联)
Eigen::Matrix4d fixed; // ✅ 推荐:栈上分配,几乎无开销
Eigen::MatrixXd dynamic(4, 4); // ⚠️ 动态尺寸会走堆分配,性能略低
// 8.3 善用 noalias() 避免不必要的临时对象
// 当目标矩阵不会与右侧运算重叠时,告诉 Eigen 可以直接写
Eigen::MatrixXd X = Eigen::MatrixXd::Random(100, 100);
Eigen::MatrixXd Y = Eigen::MatrixXd::Random(100, 100);
Eigen::MatrixXd Z(100, 100);
Z.noalias() = X * Y; // ✅ 直接写入 Z,不生成临时矩阵
// Z = X * Z; // ⚠️ 右边有 Z 时不要用 noalias,会算错!
// 8.4 按需开启向量化检查(x86 上可打印所用指令集)
std::cout << Eigen::SimdInstructionSetsInUse() << std::endl; // 显示 SSE/AVX 等
性能对比实测思路(一段可运行的对比代码):
#include <iostream>
#include <chrono>
#include <Eigen/Dense>
int main() {
const int N = 300; // 矩阵规模 300x300
Eigen::MatrixXd A = Eigen::MatrixXd::Random(N, N);
Eigen::MatrixXd B = Eigen::MatrixXd::Random(N, N);
// 手写三重循环(普通 C++ 写法,模拟"没有 Eigen"的版本)
auto t0 = std::chrono::high_resolution_clock::now();
Eigen::MatrixXd C = Eigen::MatrixXd::Zero(N, N);
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
for (int k = 0; k < N; ++k)
C(i, j) += A(i, k) * B(k, j); // 教科书式 i-j-k 循环
auto t1 = std::chrono::high_resolution_clock::now();
// Eigen 一行搞定(内部自动分块、SIMD、缓存优化)
Eigen::MatrixXd D = A * B;
auto t2 = std::chrono::high_resolution_clock::now();
auto ms1 = std::chrono::duration<double, std::milli>(t1 - t0).count();
auto ms2 = std::chrono::duration<double, std::milli>(t2 - t1).count();
std::cout << "手写三重循环耗时: " << ms1 << " ms" << std::endl;
std::cout << "Eigen 矩阵乘法耗时: " << ms2 << " ms" << std::endl;
std::cout << "加速比: " << ms1 / ms2 << " 倍" << std::endl;
// 再验证一下结果是否一致(误差应极小)
std::cout << "最大误差: " << (C - D).cwiseAbs().maxCoeff() << std::endl;
return 0;
}
用 -O2 -march=native 编译后,300×300 矩阵乘法一般能获得 5~20 倍加速,规模越大差距越明显。
六、对比表格:Eigen 与其他方案的横向对比
| 维度 | Eigen | Armadillo | OpenCV (cv::Mat) | 手写循环 |
|---|---|---|---|---|
| 定位 | 专业线性代数库 | 类 MATLAB 线性代数库 | 计算机视觉库(含矩阵) | 无 |
| 许可证 | MPL2(宽松) | Apache 2.0 | Apache 2.0 | — |
| 安装难度 | 头文件即用,几乎零依赖 | 需编译/链接库 | 需完整安装(体积大) | 无 |
| 矩阵乘法性能 | ★★★★★(表达式模板) | ★★★★(底层也调 BLAS) | ★★★(侧重图像) | ★(一般慢 5~20 倍) |
| 解线性方程组 | 全套求解器(LU/QR/Cholesky/SVD) | 有,接口类似 MATLAB | 较基础 | 需自己实现 |
| 稀疏矩阵 | 支持(Sparse 模块) | 支持 | 有限 | 极难 |
| 与 std::vector 互转 | Map 零拷贝 | 需要拷贝 | 需要拷贝 | — |
| 学习曲线 | 平缓(API 接近数学符号) | 平缓(接近 MATLAB 语法) | 陡(概念多) | 陡(易错) |
| 典型场景 | 数值计算/机器人/金融 | 科研/教学/快速原型 | 图像处理/视频分析 | 教学 |
结论:如果你的核心需求是"数值计算/矩阵运算",Eigen 综合最优;如果只是偶尔在图像处理里用矩阵,OpenCV 也够;科研快速原型图省事可以选 Armadillo;而手写循环——请只在写作业时使用。
七、常见易错点汇总(⚠️ 预警集中营)
- ⚠️ 忘记 -O2 编译:不开启优化时 Eigen 性能断崖式下跌,甚至比手写循环还慢。性能测试前先开 -O2 -march=native。
- ⚠️ 用 A.inverse() * b 解方程:慢且数值不稳定,一律改用 A.lu().solve(b) / A.colPivHouseholderQr().solve(b)。
- ⚠️ 维度不匹配:Eigen 在编译期就能拦住大部分错误,但动态矩阵的运行时错误需要 assert 或异常来捕获;发布版可用 EIGEN_NO_DEBUG 关闭检查提速。
- ⚠️ 滥用 noalias():只有当 C 不与右侧表达式重叠时才可写 C.noalias() = A * B;重叠时(如 A.noalias() = A * B)结果未定义。
- ⚠️ Map 生命周期:Map 不拥有数据,原数组被释放后继续使用 Map = 悬空指针。
- ⚠️ 行列主序混淆:C 数组是行主序,Eigen 默认列主序。互转时用 Eigen::RowMajor 或仔细核对。
- ⚠️ 对齐问题(旧版/特定平台):Eigen 对固定尺寸的 SIMD 类型有 16 字节对齐要求。C++17 及以上用 Eigen::aligned_allocator 配合 std::vector<Eigen::Vector4d>;new 一个含 Eigen 成员的类时最好重载 operator new 或使用 Eigen::aligned_allocator(新版 Eigen 在 C++17 下已大幅缓解)。
- ⚠️ 编译器版本:建议 GCC ≥ 7 / Clang ≥ 6 / MSVC ≥ 2017,旧编译器可能触发部分模块兼容问题。
八、常见问题速查表(FAQ)
| 问题 | 一句话答案 |
|---|---|
| 编译报错 Eigen: no such file or directory | 检查 -I 是否指向包含 Eigen 子目录的父目录(如 -I D:/libs/eigen-3.4.0)。 |
| 为什么我用了 Eigen 还是很慢? | 99% 是没开 -O2/-O3,或没加 -march=native。 |
| 如何求逆矩阵? | A.inverse() 可以直接用,但解方程请用 A.partialPivLu().solve(b)。 |
| 如何把 Eigen 矩阵转成 std::vector? | std::vector<double> v(m.data(), m.data()+m.size());(行主序注意顺序)。 |
| 如何创建随机矩阵? | Eigen::MatrixXd::Random(rows, cols)(元素范围 -1~1)。 |
| 如何做逐元素乘法? | A.cwiseProduct(B),不是 A * B。 |
| Eigen 和 OpenCV 怎么互转? | OpenCV 的 cv::eigen2cv / cv::cv2eigen 或通过 Map 零拷贝转换。 |
| 需要安装吗? | 传统用法不需要,头文件即可;若用 vcpkg/Conan 则按包管理器方式集成。 |
| 能否商用? | 可以,Eigen 是 MPL2 许可证,商用友好,保留版权声明即可。 |
| 求特征值用哪个类? | 对称矩阵用 SelfAdjointEigenSolver;非对称用 EigenSolver;复数用 ComplexEigenSolver。 |
| 稀疏矩阵怎么用? | #include <Eigen/Sparse>,用 Eigen::SparseMatrix<double> + SparseLU/BiCGSTAB 等求解器。 |
| 编译太慢怎么办? | 预编译头文件(PCH)缓存 Eigen 头文件;或用 -std=c++17 减少旧兼容代码。 |
九、总结与下一步
一句话回顾:Eigen = "开箱即用的高性能线性代数中央厨房",用接近数学符号的 API,白嫖到 SIMD/表达式模板级别的性能,是 C++ 数值计算的首选库。
上手路线建议:
- 先跑通第 5 步的解方程组示例,建立手感;
- 用 Map 接上你项目里已有的 std::vector 数据;
- 写一个矩阵乘法的对比测试,亲眼看到性能差距;
- 再按需深入稀疏矩阵、几何模块(四元数/欧拉角)或张量模块。
延伸阅读(均为官方资源):
- Eigen 官方文档:https://eigen.tuxfamily.org/dox/
- Eigen 快速参考(Cheat Sheet):https://eigen.tuxfamily.org/dox/group__QuickRefPage.html
- GitHub 镜像:libeigen / eigen · GitLab
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)