Skip to content

Commit 8246cf5

Browse files
added gpu support (colmap#174)
* added gpu support * add gpu to bundle adjustment * f * add gpu to global positioning and bundle adjustment * format * change back to original glomap naming * keep consistent between gp and ba * change to the workflow to test cuda as well * add option in cmake whether to use cuda * d * d * d * d * d * change version * keep the minimum_num to be consistent with COLMAP --------- Co-authored-by: Linfei Pan <linpan@student.ethz.ch>
1 parent f3b3db9 commit 8246cf5

File tree

11 files changed

+254
-14
lines changed

11 files changed

+254
-14
lines changed

.github/workflows/ubuntu.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
os: ubuntu-22.04,
3636
cmakeBuildType: Release,
3737
asanEnabled: true,
38-
cudaEnabled: false,
38+
cudaEnabled: true,
3939
checkCodeFormat: false,
4040
},
4141
{
@@ -163,6 +163,7 @@ jobs:
163163
-DCMAKE_BUILD_TYPE=${{ matrix.config.cmakeBuildType }} \
164164
-DCMAKE_INSTALL_PREFIX=./install \
165165
-DCMAKE_CUDA_ARCHITECTURES=50 \
166+
-DCUDA_ENABLED=${{ matrix.config.cudaEnabled }} \
166167
-DTESTS_ENABLED=ON \
167168
-DASAN_ENABLED=${{ matrix.config.asanEnabled }}
168169
ninja -k 10000

.github/workflows/windows.yml

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ jobs:
2323
testsEnabled: true,
2424
exportPackage: false,
2525
},
26+
{
27+
os: windows-2022,
28+
cmakeBuildType: Release,
29+
cudaEnabled: true,
30+
testsEnabled: true,
31+
exportPackage: true,
32+
},
2633
{
2734
os: windows-2022,
2835
cmakeBuildType: Release,
@@ -70,6 +77,15 @@ jobs:
7077
7178
.github/workflows/install-ccache.ps1 -Destination "${{ env.COMPILER_CACHE_DIR }}/bin"
7279
80+
- name: Install CUDA
81+
uses: Jimver/cuda-toolkit@v0.2.18
82+
if: matrix.config.cudaEnabled
83+
id: cuda-toolkit
84+
with:
85+
cuda: '12.6.2'
86+
sub-packages: '["nvcc", "nvtx", "cudart", "curand", "curand_dev", "nvrtc_dev"]'
87+
method: 'network'
88+
7389
- name: Install CMake and Ninja
7490
uses: lukka/get-cmake@latest
7591

@@ -96,10 +112,11 @@ jobs:
96112
-DCMAKE_MAKE_PROGRAM=ninja `
97113
-DCMAKE_BUILD_TYPE=Release `
98114
-DTESTS_ENABLED=ON `
99-
-DCUDA_ENABLED=OFF `
115+
-DCUDA_ENABLED=${{ matrix.config.cudaEnabled }} `
100116
-DGUI_ENABLED=OFF `
101117
-DCGAL_ENABLED=OFF `
102118
-DCMAKE_CUDA_ARCHITECTURES=all-major `
119+
-DCUDAToolkit_ROOT="${{ steps.cuda-toolkit.outputs.CUDA_PATH }}" `
103120
-DCMAKE_TOOLCHAIN_FILE="${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake" `
104121
-DVCPKG_TARGET_TRIPLET=x64-windows-release `
105122
-DCMAKE_INSTALL_PREFIX=install
@@ -123,15 +140,27 @@ jobs:
123140
124141
../vcpkg/vcpkg.exe install `
125142
--triplet=x64-windows-release
143+
$(if ($${{ matrix.config.cudaEnabled }}) { echo "--x-feature=cuda" })
126144
../vcpkg/vcpkg.exe export --raw --output-dir vcpkg_export --output glomap
127145
cp vcpkg_export/glomap/installed/x64-windows/bin/*.dll install/bin
128146
cp vcpkg_export/glomap/installed/x64-windows-release/bin/*.dll install/bin
147+
if ($${{ matrix.config.cudaEnabled }}) {
148+
cp "${{ steps.cuda-toolkit.outputs.CUDA_PATH }}/bin/cudart64_*.dll" install/bin
149+
cp "${{ steps.cuda-toolkit.outputs.CUDA_PATH }}/bin/curand64_*.dll" install/bin
150+
}
151+
152+
- name: Upload package
153+
uses: actions/upload-artifact@v4
154+
if: ${{ matrix.config.exportPackage && matrix.config.cudaEnabled }}
155+
with:
156+
name: glomap-x64-windows-cuda
157+
path: build/install
129158

130159
- name: Upload package
131160
uses: actions/upload-artifact@v4
132-
if: ${{ matrix.config.exportPackage }}
161+
if: ${{ matrix.config.exportPackage && !matrix.config.cudaEnabled }}
133162
with:
134-
name: glomap-x64-windows
163+
name: glomap-x64-windows-nocuda
135164
path: build/install
136165

137166
- name: Cleanup compiler cache

CMakeLists.txt

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
11
cmake_minimum_required(VERSION 3.28)
22

3-
project(glomap VERSION 1.0.0)
4-
5-
set(CMAKE_CXX_STANDARD 17)
6-
set(CMAKE_CXX_STANDARD_REQUIRED ON)
7-
8-
set_property(GLOBAL PROPERTY GLOBAL_DEPENDS_NO_CYCLES ON)
9-
3+
option(CUDA_ENABLED "Whether to enable CUDA, if available" ON)
104
option(TESTS_ENABLED "Whether to build test binaries" OFF)
115
option(ASAN_ENABLED "Whether to enable AddressSanitizer flags" OFF)
126
option(CCACHE_ENABLED "Whether to enable compiler caching, if available" ON)
137
option(FETCH_COLMAP "Whether to use COLMAP with FetchContent or with self-installed software" ON)
148
option(FETCH_POSELIB "Whether to use PoseLib with FetchContent or with self-installed software" ON)
159

10+
# Propagate options to vcpkg manifest.
11+
if(CUDA_ENABLED)
12+
list(APPEND VCPKG_MANIFEST_FEATURES "cuda")
13+
endif()
14+
15+
# Initialize the project.
16+
project(glomap VERSION 1.1.0)
17+
18+
set(CMAKE_CXX_STANDARD 17)
19+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
20+
21+
set_property(GLOBAL PROPERTY GLOBAL_DEPENDS_NO_CYCLES ON)
22+
1623
include(cmake/FindDependencies.cmake)
1724

18-
# Propagate options to vcpkg manifest.
1925
if (TESTS_ENABLED)
2026
enable_testing()
2127
endif()
@@ -39,6 +45,7 @@ else()
3945
message(STATUS "Disabling ccache support")
4046
endif()
4147

48+
4249
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
4350
# Some fixes for the Glog library.
4451
add_definitions("-DGLOG_USE_GLOG_EXPORT")

cmake/FindDependencies.cmake

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ FetchContent_Declare(PoseLib
2828
SYSTEM
2929
)
3030
message(STATUS "Configuring PoseLib...")
31-
if (FETCH_POSELIB)
31+
if (FETCH_POSELIB)
3232
FetchContent_MakeAvailable(PoseLib)
3333
else()
3434
find_package(PoseLib REQUIRED)
@@ -42,9 +42,73 @@ FetchContent_Declare(COLMAP
4242
)
4343
message(STATUS "Configuring COLMAP...")
4444
set(UNINSTALL_ENABLED OFF CACHE INTERNAL "")
45-
if (FETCH_COLMAP)
45+
if (FETCH_COLMAP)
4646
FetchContent_MakeAvailable(COLMAP)
4747
else()
4848
find_package(COLMAP REQUIRED)
4949
endif()
5050
message(STATUS "Configuring COLMAP... done")
51+
52+
set(CUDA_MIN_VERSION "7.0")
53+
if(CUDA_ENABLED)
54+
if(CMAKE_VERSION VERSION_LESS 3.17)
55+
find_package(CUDA QUIET)
56+
if(CUDA_FOUND)
57+
message(STATUS "Found CUDA version ${CUDA_VERSION} installed in "
58+
"${CUDA_TOOLKIT_ROOT_DIR} via legacy CMake (<3.17) module. "
59+
"Using the legacy CMake module means that any installation of "
60+
"COLMAP will require that the CUDA libraries are "
61+
"available under LD_LIBRARY_PATH.")
62+
message(STATUS "Found CUDA ")
63+
message(STATUS " Includes : ${CUDA_INCLUDE_DIRS}")
64+
message(STATUS " Libraries : ${CUDA_LIBRARIES}")
65+
66+
enable_language(CUDA)
67+
68+
macro(declare_imported_cuda_target module)
69+
add_library(CUDA::${module} INTERFACE IMPORTED)
70+
target_include_directories(
71+
CUDA::${module} INTERFACE ${CUDA_INCLUDE_DIRS})
72+
target_link_libraries(
73+
CUDA::${module} INTERFACE ${CUDA_${module}_LIBRARY} ${ARGN})
74+
endmacro()
75+
76+
declare_imported_cuda_target(cudart ${CUDA_LIBRARIES})
77+
declare_imported_cuda_target(curand ${CUDA_LIBRARIES})
78+
79+
set(CUDAToolkit_VERSION "${CUDA_VERSION_STRING}")
80+
set(CUDAToolkit_BIN_DIR "${CUDA_TOOLKIT_ROOT_DIR}/bin")
81+
else()
82+
message(STATUS "CUDA not found")
83+
endif()
84+
else()
85+
find_package(CUDAToolkit QUIET)
86+
if(CUDAToolkit_FOUND)
87+
set(CUDA_FOUND ON)
88+
enable_language(CUDA)
89+
else()
90+
message(STATUS "CUDA not found")
91+
endif()
92+
endif()
93+
endif()
94+
95+
if(CUDA_ENABLED AND CUDA_FOUND)
96+
if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
97+
set(CMAKE_CUDA_ARCHITECTURES "native")
98+
endif()
99+
100+
add_definitions("-DGLOMAP_CUDA_ENABLED")
101+
102+
# Do not show warnings if the architectures are deprecated.
103+
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Wno-deprecated-gpu-targets")
104+
# Explicitly set PIC flags for CUDA targets.
105+
if(NOT IS_MSVC)
106+
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --compiler-options -fPIC")
107+
endif()
108+
109+
message(STATUS "Enabling CUDA support (version: ${CUDAToolkit_VERSION}, "
110+
"archs: ${CMAKE_CUDA_ARCHITECTURES})")
111+
else()
112+
set(CUDA_ENABLED OFF)
113+
message(STATUS "Disabling CUDA support")
114+
endif()

glomap/controllers/option_manager.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ void OptionManager::AddGlobalPositionerOptions() {
180180
return;
181181
}
182182
added_global_positioning_options_ = true;
183+
AddAndRegisterDefaultOption("GlobalPositioning.use_gpu",
184+
&mapper->opt_gp.use_gpu);
185+
AddAndRegisterDefaultOption("GlobalPositioning.gpu_index",
186+
&mapper->opt_gp.gpu_index);
183187
AddAndRegisterDefaultOption("GlobalPositioning.optimize_positions",
184188
&mapper->opt_gp.optimize_positions);
185189
AddAndRegisterDefaultOption("GlobalPositioning.optimize_points",
@@ -199,6 +203,10 @@ void OptionManager::AddBundleAdjusterOptions() {
199203
return;
200204
}
201205
added_bundle_adjustment_options_ = true;
206+
AddAndRegisterDefaultOption("BundleAdjustment.use_gpu",
207+
&mapper->opt_ba.use_gpu);
208+
AddAndRegisterDefaultOption("BundleAdjustment.gpu_index",
209+
&mapper->opt_ba.gpu_index);
202210
AddAndRegisterDefaultOption("BundleAdjustment.optimize_rotations",
203211
&mapper->opt_ba.optimize_rotations);
204212
AddAndRegisterDefaultOption("BundleAdjustment.optimize_translation",

glomap/estimators/bundle_adjustment.cc

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <colmap/estimators/cost_functions.h>
44
#include <colmap/estimators/manifold.h>
55
#include <colmap/sensor/models.h>
6+
#include <colmap/util/cuda.h>
7+
#include <colmap/util/misc.h>
68

79
namespace glomap {
810

@@ -36,6 +38,58 @@ bool BundleAdjuster::Solve(const ViewGraph& view_graph,
3638
// Set the solver options.
3739
ceres::Solver::Summary summary;
3840

41+
int num_images = images.size();
42+
#ifdef GLOMAP_CUDA_ENABLED
43+
bool cuda_solver_enabled = false;
44+
45+
#if (CERES_VERSION_MAJOR >= 3 || \
46+
(CERES_VERSION_MAJOR == 2 && CERES_VERSION_MINOR >= 2)) && \
47+
!defined(CERES_NO_CUDA)
48+
if (options_.use_gpu && num_images >= options_.min_num_images_gpu_solver) {
49+
cuda_solver_enabled = true;
50+
options_.solver_options.dense_linear_algebra_library_type = ceres::CUDA;
51+
}
52+
#else
53+
if (options_.use_gpu) {
54+
LOG_FIRST_N(WARNING, 1)
55+
<< "Requested to use GPU for bundle adjustment, but Ceres was "
56+
"compiled without CUDA support. Falling back to CPU-based dense "
57+
"solvers.";
58+
}
59+
#endif
60+
61+
#if (CERES_VERSION_MAJOR >= 3 || \
62+
(CERES_VERSION_MAJOR == 2 && CERES_VERSION_MINOR >= 3)) && \
63+
!defined(CERES_NO_CUDSS)
64+
if (options_.use_gpu && num_images >= options_.min_num_images_gpu_solver) {
65+
cuda_solver_enabled = true;
66+
options_.solver_options.sparse_linear_algebra_library_type =
67+
ceres::CUDA_SPARSE;
68+
}
69+
#else
70+
if (options_.use_gpu) {
71+
LOG_FIRST_N(WARNING, 1)
72+
<< "Requested to use GPU for bundle adjustment, but Ceres was "
73+
"compiled without cuDSS support. Falling back to CPU-based sparse "
74+
"solvers.";
75+
}
76+
#endif
77+
78+
if (cuda_solver_enabled) {
79+
const std::vector<int> gpu_indices =
80+
colmap::CSVToVector<int>(options_.gpu_index);
81+
THROW_CHECK_GT(gpu_indices.size(), 0);
82+
colmap::SetBestCudaDevice(gpu_indices[0]);
83+
}
84+
#else
85+
if (options_.use_gpu) {
86+
LOG_FIRST_N(WARNING, 1)
87+
<< "Requested to use GPU for bundle adjustment, but COLMAP was "
88+
"compiled without CUDA support. Falling back to CPU-based "
89+
"solvers.";
90+
}
91+
#endif // GLOMAP_CUDA_ENABLED
92+
3993
// Do not use the iterative solver, as it does not seem to be helpful
4094
options_.solver_options.linear_solver_type = ceres::SPARSE_SCHUR;
4195
options_.solver_options.preconditioner_type = ceres::CLUSTER_TRIDIAGONAL;

glomap/estimators/bundle_adjustment.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ struct BundleAdjusterOptions : public OptimizationBaseOptions {
1717
bool optimize_principal_point = false;
1818
bool optimize_points = true;
1919

20+
bool use_gpu = true;
21+
std::string gpu_index = "-1";
22+
int min_num_images_gpu_solver = 50;
23+
2024
// Constrain the minimum number of views per track
2125
int min_num_view_per_track = 3;
2226

glomap/estimators/global_positioning.cc

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
#include "glomap/estimators/cost_function.h"
44

5+
#include <colmap/util/cuda.h>
6+
#include <colmap/util/misc.h>
7+
58
namespace glomap {
69
namespace {
710

@@ -361,6 +364,58 @@ void GlobalPositioner::ParameterizeVariables(
361364
}
362365
}
363366

367+
int num_images = images.size();
368+
#ifdef GLOMAP_CUDA_ENABLED
369+
bool cuda_solver_enabled = false;
370+
371+
#if (CERES_VERSION_MAJOR >= 3 || \
372+
(CERES_VERSION_MAJOR == 2 && CERES_VERSION_MINOR >= 2)) && \
373+
!defined(CERES_NO_CUDA)
374+
if (options_.use_gpu && num_images >= options_.min_num_images_gpu_solver) {
375+
cuda_solver_enabled = true;
376+
options_.solver_options.dense_linear_algebra_library_type = ceres::CUDA;
377+
}
378+
#else
379+
if (options_.use_gpu) {
380+
LOG_FIRST_N(WARNING, 1)
381+
<< "Requested to use GPU for bundle adjustment, but Ceres was "
382+
"compiled without CUDA support. Falling back to CPU-based dense "
383+
"solvers.";
384+
}
385+
#endif
386+
387+
#if (CERES_VERSION_MAJOR >= 3 || \
388+
(CERES_VERSION_MAJOR == 2 && CERES_VERSION_MINOR >= 3)) && \
389+
!defined(CERES_NO_CUDSS)
390+
if (options_.use_gpu && num_images >= options_.min_num_images_gpu_solver) {
391+
cuda_solver_enabled = true;
392+
options_.solver_options.sparse_linear_algebra_library_type =
393+
ceres::CUDA_SPARSE;
394+
}
395+
#else
396+
if (options_.use_gpu) {
397+
LOG_FIRST_N(WARNING, 1)
398+
<< "Requested to use GPU for bundle adjustment, but Ceres was "
399+
"compiled without cuDSS support. Falling back to CPU-based sparse "
400+
"solvers.";
401+
}
402+
#endif
403+
404+
if (cuda_solver_enabled) {
405+
const std::vector<int> gpu_indices =
406+
colmap::CSVToVector<int>(options_.gpu_index);
407+
THROW_CHECK_GT(gpu_indices.size(), 0);
408+
colmap::SetBestCudaDevice(gpu_indices[0]);
409+
}
410+
#else
411+
if (options_.use_gpu) {
412+
LOG_FIRST_N(WARNING, 1)
413+
<< "Requested to use GPU for bundle adjustment, but COLMAP was "
414+
"compiled without CUDA support. Falling back to CPU-based "
415+
"solvers.";
416+
}
417+
#endif // GLOMAP_CUDA_ENABLED
418+
364419
// Set up the options for the solver
365420
// Do not use iterative solvers, for its suboptimal performance.
366421
if (tracks.size() > 0) {

glomap/estimators/global_positioning.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ struct GlobalPositionerOptions : public OptimizationBaseOptions {
2929
bool optimize_points = true;
3030
bool optimize_scales = true;
3131

32+
bool use_gpu = true;
33+
std::string gpu_index = "-1";
34+
int min_num_images_gpu_solver = 50;
35+
3236
// Constrain the minimum number of views per track
3337
int min_num_view_per_track = 3;
3438

0 commit comments

Comments
 (0)