Repository navigation
Fix LoMa bf16 fallback on CUDA by loading it like any other model - #4924
Merged
Merged
Conversation
The bf16 LoMa models were loaded as capability probes that disabled ONNX Runtime's CPU fallback. ORT deliberately runs small shape computations of the matchers on the CPU, so the bf16 matcher always failed to initialize and fell back to fp32 (#4787). - Only use the bf16 models with the CUDA execution provider on GPUs with compute capability 8.0 or newer, checked before loading any model. - Drop the disabled CPU fallback of capability probes. They still propagate initialization failures without logging an error. - Add CudaDeviceSupportsBf16().
- Remove ONNXModel's is_capability_probe. LoMa now loads the bf16 models as plain sessions with an Ort::Exception fallback, like the FlexGlue fp16 matcher. - Add SelectONNXCudaDevice(), shared by ONNXModel and the LoMa bf16 check, so both resolve gpu_index to the same device. - Skip the CUDA error state check of cuda_test without a GPU, where the initialization error is sticky. - Return false from CudaDeviceSupportsBf16() on HIP. - Remove the Bf16MatcherCpuFallback test, which no longer reaches the fallback.
This was referenced Oct 29, 2026
ahojnnes
approved these changes
Oct 30, 2026
ahojnnes
pushed a commit
that referenced
this pull request
Oct 30, 2026
…4907) ## Summary Adds a `max_num_features` option to `automatic_reconstructor` and to the reconstruction benchmark, to evaluate a feature type with a different number of keypoints than its default. The first use is evaluating learned matchers at 2k/4k/8k keypoints. ### Changes - **`AutomaticReconstructionController::Options::max_num_features`** (default `-1`, off). - When positive, it overrides `max_num_features` of the SIFT, ALIKED and LoMa extraction options. - It is applied after the quality preset, which otherwise sets the number of SIFT features. - **`colmap automatic_reconstructor --max_num_features N`.** - **Benchmark:** `benchmark/reconstruction/evaluate.py --max_num_features N` forwards the option to every `automatic_reconstructor` call (`evaluation/utils.py`). ### Validation - With `--feature loma --max_num_features {2048, 4096, 8192}`, all 898 images of ETH3D DSLR have exactly 2048 / 4096 / 8192 keypoints. - With the option unset, behaviour is unchanged. - `controllers/` tests pass. Part of the FlexGlue stack: #4924, then this PR, #4921, #4908 and #4915. #4908 uses it for its evaluation.
fringehush-gif
added a commit
to fringehush-gif/colmap
that referenced
this pull request
Oct 30, 2026
## Summary Adopt the device check and ordinary ONNX Runtime sessions from upstream COLMAP PR colmap#4924. Check BF16 support before loading the model and fall back to FP32 when initialization fails. Remove the graph-assignment probe and its operator allowlist while retaining the fork's unrelated CUDA synchronization work and focused fallback tests. ## Validation - A fresh Linux CUDA build with ONNX Runtime 1.31.1 passed 11 ONNX and five CUDA tests with no skips. - On one real image pair, the BF16 matcher produced 1,848 matches with byte-identical match indices to the pristine upstream output. Separate 128-feature screens produced 68 matches for both CPU selection and GPU initialization-error fallback to FP32. - Native Windows component checks with ONNX Runtime 1.30 passed for the fork and integrated candidate in FP32 and BF16. All four 128-feature self-match outputs were byte-identical to the pristine BF16 result. Unchanged objects were reused; system-header contents were not sealed before their original compilation. - On the GTX 1080 with ONNX Runtime 1.31.1, the integrated component selected FP32 without loading BF16 and produced byte-identical 64- and 128-feature self-matches compared with the pristine and original-fork controls. These are focused functional checks, not full reconstruction comparisons or performance measurements. AI disclosure: totally vibe coded.
Contributor
|
I can confirm this work as intended whatever I threw at it. ORT 1.30 and 1.31.1 produced matching results on RTX 3060 and 3080 Ti under WSL and Windows. Both version selected FP32 before loading BF16 on GTX 1080 on Windows. Turns out I have quite a lot of stuff lying around so I tried a semi-random matrix of things, including a few different LoMa models not reflected below, both BF16 and FP32, across hardware. This was more of a curiosity and was not tested equally across all scenarios like the ones below. An unhealthy mix of compilers, CUDA libraries, operating systems and hardware. I couldn't get it to fail. :)
|
Member
Author
|
Great, thank you for confirming with such an extensive combination of setups! :) |
fringehush-gif
added a commit
to fringehush-gif/colmap
that referenced
this pull request
Nov 3, 2026
## Summary Adopt the device check and ordinary ONNX Runtime sessions from upstream COLMAP PR colmap#4924. Check BF16 support before loading the model and fall back to FP32 when initialization fails. Remove the graph-assignment probe and its operator allowlist while retaining the fork's unrelated CUDA synchronization work and focused fallback tests. ## Validation - A fresh Linux CUDA build with ONNX Runtime 1.31.1 passed 11 ONNX and five CUDA tests with no skips. - On one real image pair, the BF16 matcher produced 1,848 matches with byte-identical match indices to the pristine upstream output. Separate 128-feature screens produced 68 matches for both CPU selection and GPU initialization-error fallback to FP32. - Native Windows component checks with ONNX Runtime 1.30 passed for the fork and integrated candidate in FP32 and BF16. All four 128-feature self-match outputs were byte-identical to the pristine BF16 result. Unchanged objects were reused; system-header contents were not sealed before their original compilation. - On the GTX 1080 with ONNX Runtime 1.31.1, the integrated component selected FP32 without loading BF16 and produced byte-identical 64- and 128-feature self-matches compared with the pristine and original-fork controls. These are focused functional checks, not full reconstruction comparisons or performance measurements. AI disclosure: totally vibe coded.
fringehush-gif
added a commit
to fringehush-gif/colmap
that referenced
this pull request
Nov 3, 2026
## Summary - Integrate all 12 upstream commits after the shared base 9371f7b, including LoMa BF16 loading, matching-worker error propagation, keypoint shape scaling, and project-file CLI overrides. - Preserve the fork's CUDA blocking-sync helper alongside upstream's BF16 device check and register the shared CUDA test once. ## Validation - Resolved all merge conflicts; no conflict markers or unmerged paths remain; git diff --check passes. - Incremental Linux CUDA build linked six focused test executables. The prepared custom Ceres closure required its existing Abseil/CUDA library directories on the linker's search path. - CTest passed controllers/base_option_manager_test, feature_matching_utils_test, incremental_pipeline_test, option_manager_test, feature/loma_test, and util/cuda_test (six programs, one run each). - No full suite, Python binding, end-to-end, or performance claim. ## Upstream commits - `ea470c0c4f4a40a3bdfa33d01eb38375c5df64de` Run Windows and remaining pycolmap CI only with the full-ci label (colmap#4904) - `c0339e95482c404b51f38ff9b86866de495984f0` Fix MSVC warnings C4805, C4996, and C4756 (colmap#4910) - `f00d6063bb0b120cf10ee190f7f06f4a34edf432` Expose Ceres solver thresholds in incremental mapping (colmap#4892) - `978a4467f36bbfc9ae18780f2dca253000b0d008` Keep division-camera derivatives finite on the optical axis (colmap#4888) - `98f31541f483788ab550f5c4a4e0804e8674b9e0` Fix leak and check covariance in CovarianceWeightedCostFunction (colmap#4911) - `a467519441171054c7aaa17dffe86fe06431f05c` Avoid stack overflow when compressing union-find chains (colmap#4906) - `404b83db2c2cc04892e14a578ddfa73e0ac9bfb1` Fix LoMa bf16 fallback on CUDA by loading it like any other model (colmap#4924) - `d02e6701dede22eaeee89f73784a8c79f6f289ac` Add max_num_features option to automatic_reconstructor and benchmark (colmap#4907) - `82c3b5db78d96a7e93ca7b8b2af0634e28aa33f4` Propagate errors of feature matching workers instead of terminating (colmap#4921) - `4afe8d1156a71a2ff33974895f221c8eb3740cb1` Rescale keypoint shapes in image coordinates (colmap#4926) - `ce2b5ab9df3801c2b75edbba338c04ad3c8cc6af` Fix vocabulary tree builder descriptor dimensions (colmap#4923) - `f956ce629c21a88d75a7f7b3107298d1faf3dcf3` Fix command-line overrides for project files (colmap#4902)
fringehush-gif
added a commit
to fringehush-gif/colmap
that referenced
this pull request
Nov 4, 2026
## Summary Adopt the device check and ordinary ONNX Runtime sessions from upstream COLMAP PR colmap#4924. Check BF16 support before loading the model and fall back to FP32 when initialization fails. Remove the graph-assignment probe and its operator allowlist while retaining the fork's unrelated CUDA synchronization work and focused fallback tests. ## Validation - A fresh Linux CUDA build with ONNX Runtime 1.31.1 passed 11 ONNX and five CUDA tests with no skips. - On one real image pair, the BF16 matcher produced 1,848 matches with byte-identical match indices to the pristine upstream output. Separate 128-feature screens produced 68 matches for both CPU selection and GPU initialization-error fallback to FP32. - Native Windows component checks with ONNX Runtime 1.30 passed for the fork and integrated candidate in FP32 and BF16. All four 128-feature self-match outputs were byte-identical to the pristine BF16 result. Unchanged objects were reused; system-header contents were not sealed before their original compilation. - On the GTX 1080 with ONNX Runtime 1.31.1, the integrated component selected FP32 without loading BF16 and produced byte-identical 64- and 128-feature self-matches compared with the pristine and original-fork controls. These are focused functional checks, not full reconstruction comparisons or performance measurements. AI disclosure: totally vibe coded.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4787. Supersedes #4895.
Problem
With
--LomaMatching.use_bf16 1on CUDA, the bf16 LoMa matcher always fails to initialize and falls back to fp32:The bf16 models are loaded as capability probes, which set
session.disable_cpu_ep_fallback. But ONNX Runtime deliberately runs small shape computations on the CPU, whatever the precision of the model: its CUDAShape/Sizekernels write their output to host memory, andGetCpuPreferredNodesthen moves their int64 consumers (Gather,Unsqueeze,Concat,Cast,Reshape, ...) to the CPU EP. Tensors in bf16 or fp16 are never moved. The dynamic-shape matcher graphs contain such nodes, so the probe always rejects them. The fp32 models are not loaded as probes, so they run with the same CPU nodes.Fix
Load the bf16 models like any other model, and decide up front whether to use them:
use_bf16is now a no-op instead of trying to load the bf16 models.ONNXModels, with a fallback to fp32 if initialization throws anOrt::Exception. This removesONNXModel'sis_capability_probe, whose only user was LoMa.CudaDeviceSupportsBf16()queries the device. It returns false if the device cannot be queried, and on HIP builds.SelectONNXCudaDevice()resolvesgpu_indexto the device thatONNXModelruns on, shared with the bf16 check.doc/features.rst).This is the same pattern as the fp16 FlexGlue matcher in #4908: reduced precision only on CUDA, a regular session, and a fallback to fp32 on initialization failures.
Comparison with #4895
#4895 keeps the strict probe and instead inspects the EP graph assignment (ORT >= 1.24) against an allowlist of CPU operators. This PR avoids:
Reshapeon the CPU, which the allowlist rejects. Any rejected node silently falls back to fp32 again.ORT_API_VERSION >= 24gating; the fix also works with older ORT.Removing the strict probe barely weakens the check: the bf16 tensors themselves are never moved to the CPU, and the CPU EP has almost no bf16 compute kernels, so a bf16 op without a CUDA kernel still fails at initialization and falls back to fp32.
Tests
util/cuda_test:CudaDeviceSupportsBf16returns false for invalid devices and, with a GPU, leaves no CUDA error.util/onnx_test:SelectONNXCudaDevice, and an invalid model throws theOrt::Exceptionthat the LoMa fallback catches.feature/loma_test,util/onnx_test,util/cuda_test(also withCUDA_VISIBLE_DEVICES="") pass locally (CUDA + ONNX build).Stack: the FlexGlue stack builds on this PR: #4907, #4921, #4908, #4915. #4908 selects its fp16 matcher the same way, with a new
CudaDeviceHasTensorCores()(compute capability ≥ 7.0) next toCudaDeviceSupportsBf16(). #4915 usesSelectONNXCudaDevice()for the GPU feature cache.