Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
os: ubuntu-22.04,
cmakeBuildType: Release,
asanEnabled: true,
cudaEnabled: false,
cudaEnabled: true,
checkCodeFormat: false,
},
{
Expand Down Expand Up @@ -163,6 +163,7 @@ jobs:
-DCMAKE_BUILD_TYPE=${{ matrix.config.cmakeBuildType }} \
-DCMAKE_INSTALL_PREFIX=./install \
-DCMAKE_CUDA_ARCHITECTURES=50 \
-DCUDA_ENABLED=${{ matrix.config.cudaEnabled }} \
-DTESTS_ENABLED=ON \
-DASAN_ENABLED=${{ matrix.config.asanEnabled }}
ninja -k 10000
Expand Down
35 changes: 32 additions & 3 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ jobs:
testsEnabled: true,
exportPackage: false,
},
{
os: windows-2022,
cmakeBuildType: Release,
cudaEnabled: true,
testsEnabled: true,
exportPackage: true,
},
{
os: windows-2022,
cmakeBuildType: Release,
Expand Down Expand Up @@ -70,6 +77,15 @@ jobs:

.github/workflows/install-ccache.ps1 -Destination "${{ env.COMPILER_CACHE_DIR }}/bin"

- name: Install CUDA
uses: Jimver/[email protected]
if: matrix.config.cudaEnabled
id: cuda-toolkit
with:
cuda: '12.6.2'
sub-packages: '["nvcc", "nvtx", "cudart", "curand", "curand_dev", "nvrtc_dev"]'
method: 'network'

- name: Install CMake and Ninja
uses: lukka/get-cmake@latest

Expand All @@ -96,10 +112,11 @@ jobs:
-DCMAKE_MAKE_PROGRAM=ninja `
-DCMAKE_BUILD_TYPE=Release `
-DTESTS_ENABLED=ON `
-DCUDA_ENABLED=OFF `
-DCUDA_ENABLED=${{ matrix.config.cudaEnabled }} `
-DGUI_ENABLED=OFF `
-DCGAL_ENABLED=OFF `
-DCMAKE_CUDA_ARCHITECTURES=all-major `
-DCUDAToolkit_ROOT="${{ steps.cuda-toolkit.outputs.CUDA_PATH }}" `
-DCMAKE_TOOLCHAIN_FILE="${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake" `
-DVCPKG_TARGET_TRIPLET=x64-windows-release `
-DCMAKE_INSTALL_PREFIX=install
Expand All @@ -123,15 +140,27 @@ jobs:

../vcpkg/vcpkg.exe install `
--triplet=x64-windows-release
$(if ($${{ matrix.config.cudaEnabled }}) { echo "--x-feature=cuda" })
../vcpkg/vcpkg.exe export --raw --output-dir vcpkg_export --output glomap
cp vcpkg_export/glomap/installed/x64-windows/bin/*.dll install/bin
cp vcpkg_export/glomap/installed/x64-windows-release/bin/*.dll install/bin
if ($${{ matrix.config.cudaEnabled }}) {
cp "${{ steps.cuda-toolkit.outputs.CUDA_PATH }}/bin/cudart64_*.dll" install/bin
cp "${{ steps.cuda-toolkit.outputs.CUDA_PATH }}/bin/curand64_*.dll" install/bin
}

- name: Upload package
uses: actions/upload-artifact@v4
if: ${{ matrix.config.exportPackage && matrix.config.cudaEnabled }}
with:
name: glomap-x64-windows-cuda
path: build/install

- name: Upload package
uses: actions/upload-artifact@v4
if: ${{ matrix.config.exportPackage }}
if: ${{ matrix.config.exportPackage && !matrix.config.cudaEnabled }}
with:
name: glomap-x64-windows
name: glomap-x64-windows-nocuda
path: build/install

- name: Cleanup compiler cache
Expand Down
23 changes: 15 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
cmake_minimum_required(VERSION 3.28)

project(glomap VERSION 1.0.0)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set_property(GLOBAL PROPERTY GLOBAL_DEPENDS_NO_CYCLES ON)

option(CUDA_ENABLED "Whether to enable CUDA, if available" ON)
option(TESTS_ENABLED "Whether to build test binaries" OFF)
option(ASAN_ENABLED "Whether to enable AddressSanitizer flags" OFF)
option(CCACHE_ENABLED "Whether to enable compiler caching, if available" ON)
option(FETCH_COLMAP "Whether to use COLMAP with FetchContent or with self-installed software" ON)
option(FETCH_POSELIB "Whether to use PoseLib with FetchContent or with self-installed software" ON)

# Propagate options to vcpkg manifest.
if(CUDA_ENABLED)
list(APPEND VCPKG_MANIFEST_FEATURES "cuda")
endif()

# Initialize the project.
project(glomap VERSION 1.1.0)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set_property(GLOBAL PROPERTY GLOBAL_DEPENDS_NO_CYCLES ON)

include(cmake/FindDependencies.cmake)

# Propagate options to vcpkg manifest.
if (TESTS_ENABLED)
enable_testing()
endif()
Expand All @@ -39,6 +45,7 @@ else()
message(STATUS "Disabling ccache support")
endif()


if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# Some fixes for the Glog library.
add_definitions("-DGLOG_USE_GLOG_EXPORT")
Expand Down
68 changes: 66 additions & 2 deletions cmake/FindDependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ FetchContent_Declare(PoseLib
SYSTEM
)
message(STATUS "Configuring PoseLib...")
if (FETCH_POSELIB)
if (FETCH_POSELIB)
FetchContent_MakeAvailable(PoseLib)
else()
find_package(PoseLib REQUIRED)
Expand All @@ -42,9 +42,73 @@ FetchContent_Declare(COLMAP
)
message(STATUS "Configuring COLMAP...")
set(UNINSTALL_ENABLED OFF CACHE INTERNAL "")
if (FETCH_COLMAP)
if (FETCH_COLMAP)
FetchContent_MakeAvailable(COLMAP)
else()
find_package(COLMAP REQUIRED)
endif()
message(STATUS "Configuring COLMAP... done")

set(CUDA_MIN_VERSION "7.0")
if(CUDA_ENABLED)
if(CMAKE_VERSION VERSION_LESS 3.17)
find_package(CUDA QUIET)
if(CUDA_FOUND)
message(STATUS "Found CUDA version ${CUDA_VERSION} installed in "
"${CUDA_TOOLKIT_ROOT_DIR} via legacy CMake (<3.17) module. "
"Using the legacy CMake module means that any installation of "
"COLMAP will require that the CUDA libraries are "
"available under LD_LIBRARY_PATH.")
message(STATUS "Found CUDA ")
message(STATUS " Includes : ${CUDA_INCLUDE_DIRS}")
message(STATUS " Libraries : ${CUDA_LIBRARIES}")

enable_language(CUDA)

macro(declare_imported_cuda_target module)
add_library(CUDA::${module} INTERFACE IMPORTED)
target_include_directories(
CUDA::${module} INTERFACE ${CUDA_INCLUDE_DIRS})
target_link_libraries(
CUDA::${module} INTERFACE ${CUDA_${module}_LIBRARY} ${ARGN})
endmacro()

declare_imported_cuda_target(cudart ${CUDA_LIBRARIES})
declare_imported_cuda_target(curand ${CUDA_LIBRARIES})

set(CUDAToolkit_VERSION "${CUDA_VERSION_STRING}")
set(CUDAToolkit_BIN_DIR "${CUDA_TOOLKIT_ROOT_DIR}/bin")
else()
message(STATUS "CUDA not found")
endif()
else()
find_package(CUDAToolkit QUIET)
if(CUDAToolkit_FOUND)
set(CUDA_FOUND ON)
enable_language(CUDA)
else()
message(STATUS "CUDA not found")
endif()
endif()
endif()

if(CUDA_ENABLED AND CUDA_FOUND)
if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
set(CMAKE_CUDA_ARCHITECTURES "native")
endif()

add_definitions("-DGLOMAP_CUDA_ENABLED")

# Do not show warnings if the architectures are deprecated.
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Wno-deprecated-gpu-targets")
# Explicitly set PIC flags for CUDA targets.
if(NOT IS_MSVC)
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --compiler-options -fPIC")
endif()

message(STATUS "Enabling CUDA support (version: ${CUDAToolkit_VERSION}, "
"archs: ${CMAKE_CUDA_ARCHITECTURES})")
else()
set(CUDA_ENABLED OFF)
message(STATUS "Disabling CUDA support")
endif()
8 changes: 8 additions & 0 deletions glomap/controllers/option_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ void OptionManager::AddGlobalPositionerOptions() {
return;
}
added_global_positioning_options_ = true;
AddAndRegisterDefaultOption("GlobalPositioning.use_gpu",
&mapper->opt_gp.use_gpu);
AddAndRegisterDefaultOption("GlobalPositioning.gpu_index",
&mapper->opt_gp.gpu_index);
AddAndRegisterDefaultOption("GlobalPositioning.optimize_positions",
&mapper->opt_gp.optimize_positions);
AddAndRegisterDefaultOption("GlobalPositioning.optimize_points",
Expand All @@ -199,6 +203,10 @@ void OptionManager::AddBundleAdjusterOptions() {
return;
}
added_bundle_adjustment_options_ = true;
AddAndRegisterDefaultOption("BundleAdjustment.use_gpu",
&mapper->opt_ba.use_gpu);
AddAndRegisterDefaultOption("BundleAdjustment.gpu_index",
&mapper->opt_ba.gpu_index);
AddAndRegisterDefaultOption("BundleAdjustment.optimize_rotations",
&mapper->opt_ba.optimize_rotations);
AddAndRegisterDefaultOption("BundleAdjustment.optimize_translation",
Expand Down
54 changes: 54 additions & 0 deletions glomap/estimators/bundle_adjustment.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <colmap/estimators/cost_functions.h>
#include <colmap/estimators/manifold.h>
#include <colmap/sensor/models.h>
#include <colmap/util/cuda.h>
#include <colmap/util/misc.h>

namespace glomap {

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

int num_images = images.size();
#ifdef GLOMAP_CUDA_ENABLED
bool cuda_solver_enabled = false;

#if (CERES_VERSION_MAJOR >= 3 || \
(CERES_VERSION_MAJOR == 2 && CERES_VERSION_MINOR >= 2)) && \
!defined(CERES_NO_CUDA)
if (options_.use_gpu && num_images >= options_.min_num_images_gpu_solver) {
cuda_solver_enabled = true;
options_.solver_options.dense_linear_algebra_library_type = ceres::CUDA;
}
#else
if (options_.use_gpu) {
LOG_FIRST_N(WARNING, 1)
<< "Requested to use GPU for bundle adjustment, but Ceres was "
"compiled without CUDA support. Falling back to CPU-based dense "
"solvers.";
}
#endif

#if (CERES_VERSION_MAJOR >= 3 || \
(CERES_VERSION_MAJOR == 2 && CERES_VERSION_MINOR >= 3)) && \
!defined(CERES_NO_CUDSS)
if (options_.use_gpu && num_images >= options_.min_num_images_gpu_solver) {
cuda_solver_enabled = true;
options_.solver_options.sparse_linear_algebra_library_type =
ceres::CUDA_SPARSE;
}
#else
if (options_.use_gpu) {
LOG_FIRST_N(WARNING, 1)
<< "Requested to use GPU for bundle adjustment, but Ceres was "
"compiled without cuDSS support. Falling back to CPU-based sparse "
"solvers.";
}
#endif

if (cuda_solver_enabled) {
const std::vector<int> gpu_indices =
colmap::CSVToVector<int>(options_.gpu_index);
THROW_CHECK_GT(gpu_indices.size(), 0);
colmap::SetBestCudaDevice(gpu_indices[0]);
}
#else
if (options_.use_gpu) {
LOG_FIRST_N(WARNING, 1)
<< "Requested to use GPU for bundle adjustment, but COLMAP was "
"compiled without CUDA support. Falling back to CPU-based "
"solvers.";
}
#endif // GLOMAP_CUDA_ENABLED

// Do not use the iterative solver, as it does not seem to be helpful
options_.solver_options.linear_solver_type = ceres::SPARSE_SCHUR;
options_.solver_options.preconditioner_type = ceres::CLUSTER_TRIDIAGONAL;
Expand Down
4 changes: 4 additions & 0 deletions glomap/estimators/bundle_adjustment.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ struct BundleAdjusterOptions : public OptimizationBaseOptions {
bool optimize_principal_point = false;
bool optimize_points = true;

bool use_gpu = true;
std::string gpu_index = "-1";
int min_num_images_gpu_solver = 50;

// Constrain the minimum number of views per track
int min_num_view_per_track = 3;

Expand Down
55 changes: 55 additions & 0 deletions glomap/estimators/global_positioning.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

#include "glomap/estimators/cost_function.h"

#include <colmap/util/cuda.h>
#include <colmap/util/misc.h>

namespace glomap {
namespace {

Expand Down Expand Up @@ -361,6 +364,58 @@ void GlobalPositioner::ParameterizeVariables(
}
}

int num_images = images.size();
#ifdef GLOMAP_CUDA_ENABLED
bool cuda_solver_enabled = false;

#if (CERES_VERSION_MAJOR >= 3 || \
(CERES_VERSION_MAJOR == 2 && CERES_VERSION_MINOR >= 2)) && \
!defined(CERES_NO_CUDA)
if (options_.use_gpu && num_images >= options_.min_num_images_gpu_solver) {
cuda_solver_enabled = true;
options_.solver_options.dense_linear_algebra_library_type = ceres::CUDA;
}
#else
if (options_.use_gpu) {
LOG_FIRST_N(WARNING, 1)
<< "Requested to use GPU for bundle adjustment, but Ceres was "
"compiled without CUDA support. Falling back to CPU-based dense "
"solvers.";
}
#endif

#if (CERES_VERSION_MAJOR >= 3 || \
(CERES_VERSION_MAJOR == 2 && CERES_VERSION_MINOR >= 3)) && \
!defined(CERES_NO_CUDSS)
if (options_.use_gpu && num_images >= options_.min_num_images_gpu_solver) {
cuda_solver_enabled = true;
options_.solver_options.sparse_linear_algebra_library_type =
ceres::CUDA_SPARSE;
}
#else
if (options_.use_gpu) {
LOG_FIRST_N(WARNING, 1)
<< "Requested to use GPU for bundle adjustment, but Ceres was "
"compiled without cuDSS support. Falling back to CPU-based sparse "
"solvers.";
}
#endif

if (cuda_solver_enabled) {
const std::vector<int> gpu_indices =
colmap::CSVToVector<int>(options_.gpu_index);
THROW_CHECK_GT(gpu_indices.size(), 0);
colmap::SetBestCudaDevice(gpu_indices[0]);
}
#else
if (options_.use_gpu) {
LOG_FIRST_N(WARNING, 1)
<< "Requested to use GPU for bundle adjustment, but COLMAP was "
"compiled without CUDA support. Falling back to CPU-based "
"solvers.";
}
#endif // GLOMAP_CUDA_ENABLED

// Set up the options for the solver
// Do not use iterative solvers, for its suboptimal performance.
if (tracks.size() > 0) {
Expand Down
4 changes: 4 additions & 0 deletions glomap/estimators/global_positioning.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ struct GlobalPositionerOptions : public OptimizationBaseOptions {
bool optimize_points = true;
bool optimize_scales = true;

bool use_gpu = true;
std::string gpu_index = "-1";
int min_num_images_gpu_solver = 50;

// Constrain the minimum number of views per track
int min_num_view_per_track = 3;

Expand Down
Loading
Loading