| 563 | } |
| 564 | |
| 565 | ceres::Solver::Summary SolveWithGpuFallback( |
| 566 | const BundleAdjustmentOptions& options, |
| 567 | const BundleAdjustmentConfig& config, |
| 568 | ceres::Problem* problem) { |
| 569 | const ceres::Solver::Options solver_options = |
| 570 | options.ceres->CreateSolverOptions(config, *problem); |
| 571 | |
| 572 | ceres::Solver::Summary ceres_summary; |
| 573 | ceres::Solve(solver_options, problem, &ceres_summary); |
| 574 | |
| 575 | if (ceres_summary.termination_type == ceres::FAILURE && |
| 576 | options.ceres->use_gpu) { |
| 577 | const std::string& msg = ceres_summary.message; |
| 578 | if (msg.find("CUDA initialization failed") != std::string::npos || |
| 579 | msg.find("non-numeric") != std::string::npos || |
| 580 | msg.find("Unable to create Jacobian") != std::string::npos) { |
| 581 | LOG(WARNING) << "GPU bundle adjustment failed (" << msg |
| 582 | << "), retrying with CPU."; |
| 583 | auto cpu_options = |
| 584 | std::make_shared<CeresBundleAdjustmentOptions>(*options.ceres); |
| 585 | cpu_options->use_gpu = false; |
| 586 | const ceres::Solver::Options cpu_solver_options = |
| 587 | cpu_options->CreateSolverOptions(config, *problem); |
| 588 | ceres::Solve(cpu_solver_options, problem, &ceres_summary); |
| 589 | } |
| 590 | } |
| 591 | |
| 592 | return ceres_summary; |
| 593 | } |
| 594 | |
| 595 | class DefaultBundleAdjuster : public CeresBundleAdjuster { |
| 596 | public: |
no test coverage detected