标签: ceres-solver

为什么C++编译器不能做更好的常量折叠?

我正在研究加速大部分C++代码的方法,这些代码具有用于计算jacobians的自动衍生产品.这涉及在实际残差中做一些工作,但大部分工作(基于异形执行时间)是在计算雅可比人.

这使我感到惊讶,因为大多数雅各比人都是从0和1向前传播,因此工作量应该是功能的2-4倍,而不是10-12倍.为了模拟大量的jacobian工作是什么样的,我用一个点积(而不是sin,cos,sqrt和更多将在真实情况下)制作了一个超级极小的例子,编译器应该能够优化到单个返回值:

#include <Eigen/Core>
#include <Eigen/Geometry>

using Array12d = Eigen::Matrix<double,12,1>;

double testReturnFirstDot(const Array12d& b)
{
    Array12d a;
    a.array() = 0.;
    a(0) = 1.;
    return a.dot(b);
}
Run Code Online (Sandbox Code Playgroud)

哪个应该是一样的

double testReturnFirst(const Array12d& b)
{
    return b(0);
}
Run Code Online (Sandbox Code Playgroud)

我很失望地发现,如果没有启用快速数学运算,GCC 8.2,Clang 6或MSVC 19都无法对具有0的矩阵的天真点积进行任何优化.即使使用快速数学(https://godbolt.org/z/GvPXFy),GCC和Clang中的优化也很差(仍然涉及乘法和加法),并且MSVC根本不做任何优化.

我没有编译器的背景,但是有这个原因吗?我相当肯定,即使恒定折叠本身不会导致加速,在很大比例的科学计算中能够做更好的恒定传播/折叠会使更多的优化变得明显.

虽然我有兴趣解释为什么在编译器方面没有这样做,但我也对在实际方面可以做什么感兴趣,以便在面对这些模式时更快地使我自己的代码.

c++ compiler-construction automatic-differentiation eigen ceres-solver

59
推荐指数
3
解决办法
5127
查看次数

何时在 Ceres 中定义多个 Residual 块?

我正在阅读 Ceres Solver教程

鲍威尔函数

鲍威尔的函数映射自R^4 -> R^4,因此定义一个接受 4 元素数组x并填充 4 元素数组 的残差块似乎很直观residual

相反,教程中的示例定义了映射 的 4 个不同的残差块R^2 -> R^1

当然,如果我们试图最小化1/2 || F(x) ||^2,那么最小化 的每个元素F将隐式产生与直接最小化相同的解决方案1/2 || F(x) ||^2(即我的建议是返回单个残差向量F而不是F1...F4单独)。(我已经通过使用下面的成本函子验证了这一点)。

struct F {
    template<typename T>
    bool operator() (const T* const x, T* residual) const {

        residual[0] = x[0] + 10.0 * x[1];
        residual[1] = sqrt(5.0) * (x[2] - x[3]);
        residual[2] …
Run Code Online (Sandbox Code Playgroud)

mathematical-optimization nonlinear-optimization ceres-solver

7
推荐指数
1
解决办法
2423
查看次数

Ceres Solver:无法禁用日志记录(google glog)

我正在使用ceres求解器进行项目,当我调用该ceres::Solve函数时,库开始输出如下这样的行:

iterative_schur_complement_solver.cc:88 No parameter blocks left in the schur complement.
wall_time.cc:74 

IterativeSchurComplementSolver::Solve
                                   Delta   Cumulative
                           Total :    0.00001      0.00001
Run Code Online (Sandbox Code Playgroud)

我试图禁用这些中间步骤的记录,但到目前为止我没有成功.我在我班级的构造函数中调用这一行:

google::InitGoogleLogging("my-project");
Run Code Online (Sandbox Code Playgroud)

我调用求解器时设置的选项是:

ceres::Solver::Options options;
options.preconditioner_type = ceres::SCHUR_JACOBI;
options.linear_solver_type = ceres::ITERATIVE_SCHUR;
options.logging_type = SILENT;
options.minimizer_progress_to_stdout = false;
ceres::Solver::Summary summary;
ceres::Solve(options, &problem, &summary);
Run Code Online (Sandbox Code Playgroud)

在我看来,ceres日志记录被有效禁用,但其依赖库(即:SuiteSparse)的日志记录却没有.

有人知道如何禁用这个烦人的日志吗?

c++ least-squares glog ceres-solver

5
推荐指数
1
解决办法
3685
查看次数

使C++自动将int转换为double

当我有一个数字类型,它定义operator<为double,但不是int,与int literals的比较不起作用.这是一个问题,作为标准库的一部分,即std::complex包含int文字.

在使用类型时,我可以使编译器将int文字视为double吗?

简化示例:

// the defined operator
template<typename T>
bool operator<(const Type<T> &lhs, const T &rhs);

complex<Type<T>> complex_number;
1.0 / complex_number; // this fails
Run Code Online (Sandbox Code Playgroud)

失败发生在at 的_Div方法中std::complex

template<class _Other> inline
void _Div(const complex<_Other>& _Right)
    // ...
    else if ((_Rightimag < 0 ? -_Rightimag : +_Rightimag)
Run Code Online (Sandbox Code Playgroud)

这会导致错误:

error C2678: binary '<': no operator found which takes a left-hand operand of type 'Type<T>' (or there is no acceptable conversion)
(...)
complex(665): note: while trying to …
Run Code Online (Sandbox Code Playgroud)

c++ implicit-conversion ceres-solver

3
推荐指数
1
解决办法
520
查看次数

我可以用Google Ceres Solver解决非线性方程组吗?

Google Ceres Solver解决了有限的非线性边界约束最小二乘问题.

我可以使用非线性最小二乘解算器来找到非线性方程组的解吗?

来自维基百科:"最小二乘法是超定系统近似解的一种标准方法,即方程组中存在的方程式多于未知数."

现在,由于非线性方程的"正常"系统应该在超定系统的集合中(在未知数的未知数等于方程数的简并情况下),我可以推导出我可以使用非线性最小二乘求解器用于此目的?

这个问题来自于我必须使用Google Ceres Solver库,它似乎只提供非线性最小二乘法.

参考文献:
Ceres Solver教程
非线性最小二乘求解器求解非线性方程组?

math equation nonlinear-functions gsl ceres-solver

2
推荐指数
1
解决办法
1367
查看次数

如何在 ceres 中为同一解决方案创建不同的求解器块?

我想用ceres来计算三角形坐标。

对于这个问题,我需要解决网格中的网格坐标。每个三角形都有自己的顶点,但可以使用三角形(3 个顶点)和边(4 个顶点)等结构。

示例数据(伪代码):

triangles = [[v1, v2, v3], [v4, v5, v6]]
inner_edges = [[[v1, v4], [v2, v5]]]
Run Code Online (Sandbox Code Playgroud)

[v1, v2][v4, v5]最初是相同的,在求解过程中可能会发生变化。

现在我有两个成本函数,一个在三角形上,一个在内边缘上

f([v1, v2, v3]) = res_t1
g([v1, v4, v2, v5]) = res_2
Run Code Online (Sandbox Code Playgroud)

有两种简单的块结构

  • 两个块,一个包含所有三角形残差,一个包含所有边残差。
  • 每个三角形一个块,每个边一个块。

第一个求解具有x所有坐标的向量(2*|V|因为每个顶点有两个坐标),因为块依赖于所有顶点。在第二个中,三角形块应该仅依赖于三个顶点,而边缘块应该依赖于四个顶点。我现在想使用第二个,因为我期望更好的性能和更好的收敛性。

如何设置 ceres 来求解相同的坐标,但仅考虑与当前残差相关的顶点子集?

我尝试使用大小 6 和 8 以及位于正确位置的指针来设置问题x,但 ceres 不允许使用具有不同偏移量的相同结果指针。

接下来我尝试使用SubsetParameterization这样的例子

vector<double> x(mesh.n_faces()*6);
for(int i=0; i < mesh.n_faces(); i++){
    vector<int> const_params;
    for(int j = 0; j < mesh.n_faces(); …
Run Code Online (Sandbox Code Playgroud)

c++ nonlinear-optimization ceres-solver

2
推荐指数
1
解决办法
1349
查看次数