Repository navigation
FlexGlue: cache the dense features on the GPU - #4915
Merged
Merged
Conversation
This was referenced Oct 28, 2026
sarlinpe
changed the base branch from
sarlinpe/flexglue-bias-epilogue
to
sarlinpe/flexglue
October 28, 2026 07:45
sarlinpe
force-pushed
the
sarlinpe/flexglue-device-features
branch
from
October 28, 2026 07:45
0b1137b to
a239675
Compare
sarlinpe
force-pushed
the
sarlinpe/flexglue-device-features
branch
from
October 29, 2026 05:43
a239675 to
362913f
Compare
sarlinpe
force-pushed
the
sarlinpe/flexglue-device-features
branch
from
October 29, 2026 05:56
362913f to
d88c10d
Compare
sarlinpe
force-pushed
the
sarlinpe/flexglue-device-features
branch
from
October 29, 2026 07:27
d88c10d to
99e01e1
Compare
sarlinpe
force-pushed
the
sarlinpe/flexglue-device-features
branch
from
October 29, 2026 23:27
99e01e1 to
9b1d4e4
Compare
ahojnnes
pushed a commit
that referenced
this pull request
Oct 30, 2026
) Fixes #4787. Supersedes #4895. ## Problem With `--LomaMatching.use_bf16 1` on CUDA, the bf16 LoMa matcher always fails to initialize and falls back to fp32: ``` Failed to initialize the bf16 LoMa matcher (This session contains graph nodes that are assigned to the default CPU EP, but fallback to CPU EP has been explicitly disabled by the user.); falling 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 CUDA `Shape`/`Size` kernels write their output to host memory, and `GetCpuPreferredNodes` then 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: - The bf16 models are only used with the CUDA execution provider, on GPUs with compute capability 8.0 (Ampere) or newer. Otherwise, the fp32 models are loaded directly, without first downloading and loading the bf16 models. - On older GPUs, creating a bf16 session can succeed while inference fails, which the fallback on initialization failures would not catch. - On the CPU, `use_bf16` is now a no-op instead of trying to load the bf16 models. - The bf16 models are loaded as regular `ONNXModel`s, with a fallback to fp32 if initialization throws an `Ort::Exception`. This removes `ONNXModel`'s `is_capability_probe`, whose only user was LoMa. - New `CudaDeviceSupportsBf16()` queries the device. It returns false if the device cannot be queried, and on HIP builds. - New `SelectONNXCudaDevice()` resolves `gpu_index` to the device that `ONNXModel` runs on, shared with the bf16 check. - Updated the option docs (C++, pycolmap, `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: - the allowlist, which is brittle: which nodes ORT moves to the CPU depends on data flow, not on the operator type. For example, FlexGlue's matchers run `Reshape` on the CPU, which the allowlist rejects. Any rejected node silently falls back to fp32 again. - the `ORT_API_VERSION >= 24` gating; the fix also works with older ORT. - downloading and loading the bf16 models on GPUs without bf16 support before rejecting them. - ~80 lines of hand-encoded ONNX test models. 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`: `CudaDeviceSupportsBf16` returns false for invalid devices and, with a GPU, leaves no CUDA error. - `util/onnx_test`: `SelectONNXCudaDevice`, and an invalid model throws the `Ort::Exception` that the LoMa fallback catches. - `feature/loma_test`, `util/onnx_test`, `util/cuda_test` (also with `CUDA_VISIBLE_DEVICES=""`) pass locally (CUDA + ONNX build). - Not yet run end-to-end with the CUDA EP: ORT 1.30's CUDA EP does not load on my machine (older system CUDA runtime). The bf16 LoMa-B matcher with CPU shape nodes was validated in #4895 (64/64 and 128/128 self-matches on an RTX 3060). **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 to `CudaDeviceSupportsBf16()`. #4915 uses `SelectONNXCudaDevice()` for the GPU feature cache.
ahojnnes
force-pushed
the
sarlinpe/flexglue-device-features
branch
from
October 30, 2026 08:37
9b1d4e4 to
719750d
Compare
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.
ahojnnes
force-pushed
the
sarlinpe/flexglue-device-features
branch
from
October 30, 2026 12:09
719750d to
c3503dc
Compare
sarlinpe
force-pushed
the
sarlinpe/flexglue-device-features
branch
2 times, most recently
from
October 30, 2026 23:42
fd12471 to
801552b
Compare
ahojnnes
approved these changes
Oct 31, 2026
ahojnnes
force-pushed
the
sarlinpe/flexglue-device-features
branch
from
November 1, 2026 18:32
801552b to
bf3ec0e
Compare
Contributor
|
@sarlinpe Rebased to pull appease the macos-15 requirement. |
When the FlexGlue models run on a CUDA GPU, the descriptor writes the dense features directly to GPU memory through an ONNX Runtime I/O binding, and the cache keeps them there, so that the matcher reads them without copying both 4MB feature maps to the GPU for every pair (about 2 ms per pair). The GPU memory is bounded by feature_cache_size (~4MB per image). Adds an ONNXModel::Run overload whose outputs are allocated in a given memory.
sarlinpe
force-pushed
the
sarlinpe/flexglue-device-features
branch
from
November 1, 2026 20:33
bf3ec0e to
01accc4
Compare
sarlinpe
enabled stacked auto-merge (squash)
November 1, 2026 20:34
fringehush-gif
added a commit
to fringehush-gif/colmap
that referenced
this pull request
Nov 3, 2026
Integrate thirteen official upstream commits after the private GPU cleanup checkpoint. Preserve blocking host-sync selection and its CUDA 12.0/12.1 flag boundary while adopting upstream's generalized compute-capability helper and LoMa/FlexGlue callers. Keep both capability and policy tests; remove the duplicate colmap_util_cuda link from automatic composition. Includes upstream rig-frame covisibility, thin bitmap thumbnails, visibility coordinate conversion, row-wise warp dispatch, benchmark fixes, FlexGlue, review guidance, and the Windows non-GUI SIFT-test build fix. Validation at this private checkpoint: merge conflicts resolved in cuda.cc, cuda.h, cuda_test.cc; source search found no remaining old BF16-helper call; git diff --check passed. Native merged-source qualification and independent exact-diff review remain pending. Prior GPU tests qualify their pinned source, not this entire merged product. No reconstruction or performance claim. AI-assisted integration. Existing published history is preserved. ## Upstream commits - `e52aa8ee12ef58eb1cd16ada2be9316fa1c02cd3` Move pycolmap macOS CI from macos-14 to macos-15 runner (colmap#4933) - `8007d1a51ae0c0af87fff3ebd204cf4698df7565` Preserve float weight ordering in maximum spanning trees (colmap#4928) - `dd84102ef5e75fc17e20da281d2fc2fee5aca6a9` Bump pypa/gh-action-pypi-publish from 1.14.2 to 1.14.3 in /.github/workflows (colmap#4942) - `721e185ddb6205b85fddc39ccf0774567f6be6ed` Add FlexGlue feature matcher (colmap#4908) - `d0a411f2a9af139b5ea8118d64e5da5b70c6a890` FlexGlue: cache the dense features on the GPU (colmap#4915) - `105817b6299cf22144fbbf39f95689681352476d` Hoist camera model dispatch per row in image warps (colmap#4935) - `27ffad4388ce5647df3ea9e547bf8e1ea155fbcd` Make benchmark translation-angle errors invariant to reconstruction scale (colmap#4932) - `e8f3522b936882cbceae074a19fca58fe378d323` Resolve benchmark paths before changing subprocess directories (colmap#4931) - `f664d5d219230c1f1ebf9c2c7ecdcafc451b95ce` Clamp visibility coordinates before unsigned conversion (colmap#4943) - `138119b7640d46f1f51fe329694a9ddae3ae0908` Keep thin bitmap thumbnails nonempty (colmap#4927) - `b16ed5f97fa405ff2462745f9509386a9ebe6ece` Count rig frame covisibility once per 3D point (colmap#4893) - `93dbbcb7f3019da30bd4a2c72753421e6cb85b45` Add colmap-review agent skill for code review (colmap#4934) - `2a6f6955ed73a3d15b2a75edede5750e7c7b3304` Fix sift_test build on MSVC without the GUI (colmap#4955)
fringehush-gif
added a commit
to fringehush-gif/colmap
that referenced
this pull request
Nov 4, 2026
Integrate thirteen official upstream commits after the private GPU cleanup checkpoint. Preserve blocking host-sync selection and its CUDA 12.0/12.1 flag boundary while adopting upstream's generalized compute-capability helper and LoMa/FlexGlue callers. Keep both capability and policy tests; remove the duplicate colmap_util_cuda link from automatic composition. Includes upstream rig-frame covisibility, thin bitmap thumbnails, visibility coordinate conversion, row-wise warp dispatch, benchmark fixes, FlexGlue, review guidance, and the Windows non-GUI SIFT-test build fix. Validation at this private checkpoint: merge conflicts resolved in cuda.cc, cuda.h, cuda_test.cc; source search found no remaining old BF16-helper call; git diff --check passed. Native merged-source qualification and independent exact-diff review remain pending. Prior GPU tests qualify their pinned source, not this entire merged product. No reconstruction or performance claim. AI-assisted integration. Existing published history is preserved. ## Upstream commits - `e52aa8ee12ef58eb1cd16ada2be9316fa1c02cd3` Move pycolmap macOS CI from macos-14 to macos-15 runner (colmap#4933) - `8007d1a51ae0c0af87fff3ebd204cf4698df7565` Preserve float weight ordering in maximum spanning trees (colmap#4928) - `dd84102ef5e75fc17e20da281d2fc2fee5aca6a9` Bump pypa/gh-action-pypi-publish from 1.14.2 to 1.14.3 in /.github/workflows (colmap#4942) - `721e185ddb6205b85fddc39ccf0774567f6be6ed` Add FlexGlue feature matcher (colmap#4908) - `d0a411f2a9af139b5ea8118d64e5da5b70c6a890` FlexGlue: cache the dense features on the GPU (colmap#4915) - `105817b6299cf22144fbbf39f95689681352476d` Hoist camera model dispatch per row in image warps (colmap#4935) - `27ffad4388ce5647df3ea9e547bf8e1ea155fbcd` Make benchmark translation-angle errors invariant to reconstruction scale (colmap#4932) - `e8f3522b936882cbceae074a19fca58fe378d323` Resolve benchmark paths before changing subprocess directories (colmap#4931) - `f664d5d219230c1f1ebf9c2c7ecdcafc451b95ce` Clamp visibility coordinates before unsigned conversion (colmap#4943) - `138119b7640d46f1f51fe329694a9ddae3ae0908` Keep thin bitmap thumbnails nonempty (colmap#4927) - `b16ed5f97fa405ff2462745f9509386a9ebe6ece` Count rig frame covisibility once per 3D point (colmap#4893) - `93dbbcb7f3019da30bd4a2c72753421e6cb85b45` Add colmap-review agent skill for code review (colmap#4934) - `2a6f6955ed73a3d15b2a75edede5750e7c7b3304` Fix sift_test build on MSVC without the GUI (colmap#4955)
fringehush-gif
added a commit
to fringehush-gif/colmap
that referenced
this pull request
Nov 7, 2026
Refresh the experimental alternative with fork main while retaining its previous head as a parent. The resulting tree is exactly main plus the isolated shared-current-cost-cache deletion: one CUDA file, +1/-25. ## Change Read the existing cost map directly during the ordered sampled-cost fold. Preserve current plane propagation, source packing, scheduling and fallback mathematics. The cache originates in custom a37c1c3, MVS: Reuse sampled current costs (GPU perf). The earlier alternative is retained through 8481f89; its original experiment was 8b1412f. Historical Fountain11 photo+geometry at 3072 recorded 76.85 -> 78.82 seconds, one observation per arm, on the older revision. Retain this inconclusive/adverse observation with its earlier revision; current performance has not been measured. No performance experiment was reopened. ## Validation - Exact candidate CUDA owner compiled with CUDA 13.2 for compute_86/sm_86. In a bounded retained-support context on RTX 3060, both matched targets passed all 13 selected cases: propagation, ordered source folding, checkpoint-HMM and paired-sweep preservation. - Four complete inputs and four outputs matched across executables: 8,492,128 bytes per arm. Maps were finite with positive depth and checked ordered graph IDs. Complete witnesses use checkpoint_hmm=false; separate checkpoint tests cover both settings without full cross-executable true-mode witnesses. - Direct owners, link maps and actual loaded providers were checked; managed jobs ended and released their bookings. Later host resize/warp changes have separate owner qualification. This is not a whole-branch build, reconstruction-quality, portability or current-performance result. ## Upstream commits carried forward - e52aa8e Move pycolmap macOS CI from macos-14 to macos-15 runner (colmap#4933) - 8007d1a Preserve float weight ordering in maximum spanning trees (colmap#4928) - dd84102 Bump pypa/gh-action-pypi-publish from 1.14.2 to 1.14.3 in /.github/workflows (colmap#4942) - 721e185 Add FlexGlue feature matcher (colmap#4908) - d0a411f FlexGlue: cache the dense features on the GPU (colmap#4915) - 105817b Hoist camera model dispatch per row in image warps (colmap#4935) - 27ffad4 Make benchmark translation-angle errors invariant to reconstruction scale (colmap#4932) - e8f3522 Resolve benchmark paths before changing subprocess directories (colmap#4931) - f664d5d Clamp visibility coordinates before unsigned conversion (colmap#4943) - 138119b Keep thin bitmap thumbnails nonempty (colmap#4927) - b16ed5f Count rig frame covisibility once per 3D point (colmap#4893) - 93dbbcb Add colmap-review agent skill for code review (colmap#4934) - 2a6f695 Fix sift_test build on MSVC without the GUI (colmap#4955) - 78cc729 Fix default prior_position_loss_scale to sqrt(chi2_95_3dof) (colmap#4936) - 8653c6b Estimate two-view relative rotation covariance (colmap#4950) - e1317dd FlexGlue: match keypoints in the resized descriptor input frame (colmap#4949) - 3db6eb0 Extract ConvertPosePriorsToENU and skip pose priors without position (colmap#4937) - 77cbe48 Store and estimate rotation covariances on PoseGraph (colmap#4951) - 30a1a81 Support covariance whitening in CeresRotationAverager (colmap#4952) - e6644e7 Fix -Wunused-result warning in ThreadPool::AddTask (colmap#4958) - 5b6da88 Clear descriptor-index results for empty queries (colmap#4960) - d1d92d9 Add COVARIANCE reweighting for Ceres rotation averaging (colmap#4953) - 761d90d Enable covariance-weighted rotation averaging in global pipelines (colmap#4823) - fdee2e1 Reuse the pose graph of GlobalPipeline in the component mappers (colmap#4912) 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.
Stacked on #4908 (which now includes early stopping, formerly #4916).
Summary
When the FlexGlue models run on a CUDA GPU, this PR keeps the cached dense features on the GPU:
ONNXModel::Run(inputs, output_memory_info)overload.Ort::Values.Previously, both 4 MB float32 feature maps were copied host→device for every pair.
How much do we gain?
Setup:
delivery_area+terrains+office(2132 pairs), with the keypoints of the evaluation, on an idle A100.CudaPinnedoutputs via the same I/O binding) uses no GPU memory, but only gives about a third of the gain (−0.6 / −0.7 ms at 2k / 8k), so it is not included.Is it worth the change, and how do we avoid eating precious GPU memory?
flexglue.ccand anONNXModel::Runoverload.feature_cache_size: 128 images × ~4 MB = 512 MB by default.feature_cache_sizereduces the GPU memory; this is documented. The cache only moves to the GPU when both models run on CUDA, on the device resolved bySelectONNXCudaDevice(Fix LoMa bf16 fallback on CUDA by loading it like any other model #4924), like the sessions. There is no separate on/off option: the GPU cache is strictly faster, and its size is already bounded.Tests:
feature/,controllers/andutil/onnxtests pass.ONNXModelTest.RunWithOutputMemoryInforuns the newRunoverload (I/O binding into host memory) on every CI job, since the GPU path needs a CUDA GPU.