Add CUDA based bundle adjustment tests.
Also refactor the logic for generating ba tests a bit
breaking it into dense, sparse and iterative tests.
Change-Id: I6b33e3b047ef900b12907bd150febe4744779b7a
diff --git a/internal/ceres/generate_bundle_adjustment_tests.py b/internal/ceres/generate_bundle_adjustment_tests.py
index 86b4fcb..29a9297 100644
--- a/internal/ceres/generate_bundle_adjustment_tests.py
+++ b/internal/ceres/generate_bundle_adjustment_tests.py
@@ -41,27 +41,37 @@
MULTI_THREADED = "4"
THREAD_CONFIGS = [SINGLE_THREADED, MULTI_THREADED]
-SOLVER_CONFIGS = [
- # Linear solver Sparse backend Preconditioner
- ('DENSE_SCHUR', 'NO_SPARSE', 'IDENTITY'),
- ('ITERATIVE_SCHUR', 'NO_SPARSE', 'JACOBI'),
- ('ITERATIVE_SCHUR', 'NO_SPARSE', 'SCHUR_JACOBI'),
- ('ITERATIVE_SCHUR', 'SUITE_SPARSE', 'CLUSTER_JACOBI'),
- ('ITERATIVE_SCHUR', 'EIGEN_SPARSE', 'CLUSTER_JACOBI'),
- ('ITERATIVE_SCHUR', 'CX_SPARSE', 'CLUSTER_JACOBI'),
- ('ITERATIVE_SCHUR', 'ACCELERATE_SPARSE','CLUSTER_JACOBI'),
- ('ITERATIVE_SCHUR', 'SUITE_SPARSE', 'CLUSTER_TRIDIAGONAL'),
- ('ITERATIVE_SCHUR', 'EIGEN_SPARSE', 'CLUSTER_TRIDIAGONAL'),
- ('ITERATIVE_SCHUR', 'CX_SPARSE', 'CLUSTER_TRIDIAGONAL'),
- ('ITERATIVE_SCHUR', 'ACCELERATE_SPARSE','CLUSTER_TRIDIAGONAL'),
- ('SPARSE_NORMAL_CHOLESKY', 'SUITE_SPARSE', 'IDENTITY'),
- ('SPARSE_NORMAL_CHOLESKY', 'EIGEN_SPARSE', 'IDENTITY'),
- ('SPARSE_NORMAL_CHOLESKY', 'CX_SPARSE', 'IDENTITY'),
- ('SPARSE_NORMAL_CHOLESKY', 'ACCELERATE_SPARSE','IDENTITY'),
- ('SPARSE_SCHUR', 'SUITE_SPARSE', 'IDENTITY'),
- ('SPARSE_SCHUR', 'EIGEN_SPARSE', 'IDENTITY'),
- ('SPARSE_SCHUR', 'CX_SPARSE', 'IDENTITY'),
- ('SPARSE_SCHUR', 'ACCELERATE_SPARSE','IDENTITY'),
+DENSE_SOLVER_CONFIGS = [
+ # Linear solver Dense backend
+ ('DENSE_SCHUR', 'EIGEN'),
+ ('DENSE_SCHUR', 'LAPACK'),
+ ('DENSE_SCHUR', 'CUDA'),
+]
+
+SPARSE_SOLVER_CONFIGS = [
+ # Linear solver Sparse backend
+ ('SPARSE_NORMAL_CHOLESKY', 'SUITE_SPARSE'),
+ ('SPARSE_NORMAL_CHOLESKY', 'EIGEN_SPARSE'),
+ ('SPARSE_NORMAL_CHOLESKY', 'CX_SPARSE'),
+ ('SPARSE_NORMAL_CHOLESKY', 'ACCELERATE_SPARSE'),
+ ('SPARSE_SCHUR', 'SUITE_SPARSE'),
+ ('SPARSE_SCHUR', 'EIGEN_SPARSE'),
+ ('SPARSE_SCHUR', 'CX_SPARSE'),
+ ('SPARSE_SCHUR', 'ACCELERATE_SPARSE'),
+]
+
+ITERATIVE_SOLVER_CONFIGS = [
+ # Linear solver Sparse backend Preconditioner
+ ('ITERATIVE_SCHUR', 'NO_SPARSE', 'JACOBI'),
+ ('ITERATIVE_SCHUR', 'NO_SPARSE', 'SCHUR_JACOBI'),
+ ('ITERATIVE_SCHUR', 'SUITE_SPARSE', 'CLUSTER_JACOBI'),
+ ('ITERATIVE_SCHUR', 'EIGEN_SPARSE', 'CLUSTER_JACOBI'),
+ ('ITERATIVE_SCHUR', 'CX_SPARSE', 'CLUSTER_JACOBI'),
+ ('ITERATIVE_SCHUR', 'ACCELERATE_SPARSE','CLUSTER_JACOBI'),
+ ('ITERATIVE_SCHUR', 'SUITE_SPARSE', 'CLUSTER_TRIDIAGONAL'),
+ ('ITERATIVE_SCHUR', 'EIGEN_SPARSE', 'CLUSTER_TRIDIAGONAL'),
+ ('ITERATIVE_SCHUR', 'CX_SPARSE', 'CLUSTER_TRIDIAGONAL'),
+ ('ITERATIVE_SCHUR', 'ACCELERATE_SPARSE','CLUSTER_TRIDIAGONAL'),
]
FILENAME_SHORTENING_MAP = dict(
@@ -69,6 +79,9 @@
ITERATIVE_SCHUR='iterschur',
SPARSE_NORMAL_CHOLESKY='sparsecholesky',
SPARSE_SCHUR='sparseschur',
+ EIGEN='eigen',
+ LAPACK='lapack',
+ CUDA='cuda',
NO_SPARSE='', # Omit sparse reference entirely for dense tests.
SUITE_SPARSE='suitesparse',
EIGEN_SPARSE='eigensparse',
@@ -85,7 +98,7 @@
COPYRIGHT_HEADER = (
"""// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2018 Google Inc. All rights reserved.
+// Copyright 2022 Google Inc. All rights reserved.
// http://ceres-solver.org/
//
// Redistribution and use in source and binary forms, with or without
@@ -134,6 +147,7 @@
Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
options->num_threads = %(num_threads)s;
options->linear_solver_type = %(linear_solver)s;
+ options->dense_linear_algebra_library_type = %(dense_backend)s;
options->sparse_linear_algebra_library_type = %(sparse_backend)s;
options->preconditioner_type = %(preconditioner)s;
if (%(ordering)s) {
@@ -153,6 +167,7 @@
def generate_bundle_test(linear_solver,
+ dense_backend,
sparse_backend,
preconditioner,
ordering,
@@ -164,6 +179,10 @@
if linear_solver != 'ITERATIVE_SCHUR':
preconditioner_tag = ''
+ dense_backend_tag = dense_backend
+ if linear_solver != 'DENSE_SCHUR':
+ dense_backend_tag=''
+
# Omit references to the sparse backend when one is not in use.
sparse_backend_tag = sparse_backend
if sparse_backend == 'NO_SPARSE':
@@ -172,6 +191,7 @@
# Use a double underscore; otherwise the names are harder to understand.
test_class_name = '_'.join(filter(lambda x: x, [
camelcasify(linear_solver),
+ camelcasify(dense_backend_tag),
camelcasify(sparse_backend_tag),
camelcasify(preconditioner_tag),
ordering[1:], # Strip 'k'
@@ -180,6 +200,7 @@
# Initial template parameters (augmented more below).
template_parameters = dict(
linear_solver=linear_solver,
+ dense_backend=dense_backend,
sparse_backend=sparse_backend,
preconditioner=preconditioner,
ordering=ordering,
@@ -202,6 +223,13 @@
preprocessor_conditions_begin.append('#ifdef CERES_USE_EIGEN_SPARSE')
preprocessor_conditions_end.insert(0, '#endif // CERES_USE_EIGEN_SPARSE')
+ if dense_backend == "LAPACK":
+ preprocessor_conditions_begin.append('#ifndef CERES_NO_LAPACK')
+ preprocessor_conditions_end.insert(0, '#endif // CERES_NO_LAPACK')
+ elif dense_backend == "CUDA":
+ preprocessor_conditions_begin.append('#ifndef CERES_NO_CUDA')
+ preprocessor_conditions_end.insert(0, '#endif // CERES_NO_CUDA')
+
# Accumulate appropriate #ifdef/#ifndefs for threading conditions.
if thread_config == MULTI_THREADED:
preprocessor_conditions_begin.append('#ifndef CERES_NO_THREADS')
@@ -223,10 +251,12 @@
# Substitute variables into the test template, and write the result to a file.
filename_tag = '_'.join(FILENAME_SHORTENING_MAP.get(x) for x in [
linear_solver,
+ dense_backend_tag,
sparse_backend_tag,
preconditioner_tag,
ordering]
if FILENAME_SHORTENING_MAP.get(x))
+
if (thread_config == MULTI_THREADED):
filename_tag += '_threads'
@@ -244,16 +274,37 @@
if __name__ == '__main__':
# Iterate over all the possible configurations and generate the tests.
generated_files = []
- for linear_solver, sparse_backend, preconditioner in SOLVER_CONFIGS:
- for ordering in ORDERINGS:
- for thread_config in THREAD_CONFIGS:
+
+ for ordering in ORDERINGS:
+ for thread_config in THREAD_CONFIGS:
+ for linear_solver, dense_backend in DENSE_SOLVER_CONFIGS:
generated_files.append(
generate_bundle_test(linear_solver,
+ dense_backend,
+ 'NO_SPARSE',
+ 'IDENTITY',
+ ordering,
+ thread_config))
+
+ for linear_solver, sparse_backend, in SPARSE_SOLVER_CONFIGS:
+ generated_files.append(
+ generate_bundle_test(linear_solver,
+ 'EIGEN',
+ sparse_backend,
+ 'IDENTITY',
+ ordering,
+ thread_config))
+
+ for linear_solver, sparse_backend, preconditioner, in ITERATIVE_SOLVER_CONFIGS:
+ generated_files.append(
+ generate_bundle_test(linear_solver,
+ 'EIGEN',
sparse_backend,
preconditioner,
ordering,
thread_config))
+
# Generate the CMakeLists.txt as well.
with open('generated_bundle_adjustment_tests/CMakeLists.txt', 'w') as fd:
fd.write(COPYRIGHT_HEADER.replace('//', '#').replace('http:#', 'http://'))