用于非常小方阵的特征线性求解器
Eigen Linear Solver for very small square matrix
我正在C++程序上使用本征求解非常小的方阵(4X4(的线性方程。
我的测试代码是这样的
template<template <typename MatrixType> typename EigenSolver>
Vertor3d solve(){
//Solve Ax = b and A is a real symmetric matrix and positive semidefinite
... // Construct 4X4 square matrix A and 4X1 vector b
EigenSolver<Matrix4d> solver(A);
auto x = solver.solve(b);
... // Compute relative error for validating
}
我测试了一些特征求解器,其中包括:
- 全像素LU
- 部分皮夫LU
- 房主二维码
- 科尔皮夫户主QR
- 科尔皮夫户主QR
- 完全正交分解
- LDLT
- 直接逆
直接逆是:
template<typename MatrixType>
struct InverseSolve
{
private:
MatrixType inv;
public:
InverseSolve(const MatrixType &matrix) :inv(matrix.inverse()) {
}
template<typename VectorType>
auto solve(const VectorType & b) {
return inv * b;
}
};
我发现快速方法是DirectInverse,即使我将 Eigen 与 MKL 链接,结果也没有改变。
这是测试结果
- 全像素LU : 477 ms
- 部分皮夫LU : 468 ms
- 户主QR : 849 ms
- ColPivHouseholderQR : 766 ms
- ColPivHouseholderQR : 857 ms
- 完全正交分解 : 832 ms
- LDLT : 477 ms
- 直接反转 : 88 ms
它们都使用 1000000 个矩阵,从均匀分布 [0,100] 随机双精度。我小心翼翼地构造上三角形,然后复制到下三角形。
DirectInverse的唯一问题是它的相对误差略大于其他求解器,但可以接受。
我的程序是否有更快或更优雅的解决方案?DirectInverse 是我的程序的快速解决方案吗?
DirectInverse不使用对称信息,那么为什么DirectInverse比LDLT快得多呢?
尽管许多人建议当你只想求解线性系统时,永远不要显式计算逆,但对于非常小的矩阵,这实际上是有益的,因为有使用协因子的闭式解。
您测试的所有其他替代方案都会变慢,因为它们将进行透视(这意味着分支(,即使对于小型固定大小的矩阵也是如此。此外,它们中的大多数会导致更多的除法,并且不能像直接计算那样向量化。
为了提高精度(如果需要,这种技术实际上可以独立于求解器使用(,您可以通过使用残差再次求解系统来优化初始解:
Eigen::Vector4d solveDirect(const Eigen::Matrix4d& A, const Eigen::Vector4d& b)
{
Eigen::Matrix4d inv = A.inverse();
Eigen::Vector4d x = inv * b;
x += inv*(b-A*x);
return x;
}
我不认为 Eigen 直接提供了一种利用这里A
对称性的方法(对于直接计算的逆(。您可以尝试通过将A
的自伴随视图显式复制到临时视图中来暗示这一点,并希望编译器足够聪明以找到常见的子表达式:
Eigen::Matrix4d tmp = A.selfadjointView<Eigen::Upper>();
Eigen::Matrix4d inv = tmp.inverse();
为了减少一些划分,你也可以用-freciprocal-math
(在 gcc 或 clang 上(进行编译,这当然会略微降低准确性。
如果这确实对性能至关重要,请尝试实现手动调整的inverse_4x4_symmetric
方法。 利用inv * b
的对称性不太可能对如此小的矩阵有益。
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 特征::矩阵<双精度,1,3> 结构类型函数中的返回类型函数
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 向量上的线性搜索
- 特征命名访问向量段
- 将特征矩阵的向量设置为0
- 特征:模板函数中矩阵的平面图
- basic_string的前导/尾部不区分空格的特征
- 特征 3 类的模板专用化
- 特征 c++:复矩阵的面积双曲正切(atanh)
- C++ 中的特征向量计算
- 用于非常小方阵的特征线性求解器
- 使用特征 3 线性系统求解器的错误结果
- 使用特征/英特尔 MKL 求解稀疏线性系统
- 特征库,简单的线性代数操作,具有稀疏的矩阵,增加了其分配的尺寸
- 特征 3 断言在求解线性系统时失败 - 据我所知,这是由于特征中的无效索引
- 如何在特征中实现高性能分段线性传递函数
- 无法访问特征线性系统解的元素
- 特征线性代数求解器似乎很慢
- 用c++特征库求解线性最小二乘方程(动态分配)