Skip to content

Parallelize structure-less registration on different images with ThreadPool#4142

Open
B1ueber2y wants to merge 1 commit intomainfrom
shaohui/parallelize_structureless
Open

Parallelize structure-less registration on different images with ThreadPool#4142
B1ueber2y wants to merge 1 commit intomainfrom
shaohui/parallelize_structureless

Conversation

@B1ueber2y
Copy link
Contributor

Structure-less registration becomes the bottleneck in large-scale datasets. This PR attempts to speed it up with multi-threading.

@gemini-code-assist
Copy link

Summary of Changes

Hello @B1ueber2y, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a performance bottleneck in structure-less registration by implementing parallel processing. It introduces a thread pool to handle multiple image registrations concurrently, improving efficiency for large datasets. The changes include refactoring the registration process into estimation and commit phases, with the estimation phase being thread-safe.

Highlights

  • Parallelization: This PR introduces multi-threading to speed up structure-less registration, which is identified as a bottleneck in large-scale datasets.
  • Thread Pool Implementation: Utilizes a thread pool to concurrently run Phase 1 (read-only RANSAC) of structure-less estimation for multiple candidate images.
  • New Data Structure: Introduces a StructureLessEstimationResult struct to encapsulate the results of the structure-less estimation process, facilitating thread-safe data handling.
Changelog
  • src/colmap/controllers/incremental_pipeline.cc
    • Implemented parallel structure-less registration using a thread pool for multiple candidate images.
    • Modified the registration loop to accommodate concurrent execution and result handling.
    • Added logic to stop the thread pool upon successful registration.
    • Refactored the structure-less registration to use the new EstimateStructureLessPose and CommitStructureLessRegistration functions.
  • src/colmap/sfm/incremental_mapper.cc
    • Refactored RegisterNextStructureLessImage into EstimateStructureLessPose and CommitStructureLessRegistration functions.
    • The EstimateStructureLessPose function now performs read-only estimation and is thread-safe.
    • The CommitStructureLessRegistration function commits the successful estimation to the reconstruction and is not thread-safe.
    • Added a StructureLessEstimationResult struct to store the results of the estimation phase.
    • Modified the return logic of EstimateStructureLessPose to return the StructureLessEstimationResult instead of a boolean.
  • src/colmap/sfm/incremental_mapper.h
    • Added forward declaration of CorrespondenceGraph.
    • Added declaration of StructureLessEstimationResult struct.
    • Added declarations for EstimateStructureLessPose and CommitStructureLessRegistration functions.
Activity
  • The PR introduces threading to the structure-less registration process.
  • The code was refactored to separate estimation and commit phases for thread safety.
  • A new data structure StructureLessEstimationResult was introduced to manage the results of the estimation phase.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces parallelization for structure-less image registration using a thread pool, which is a significant performance enhancement for large datasets. The refactoring of IncrementalMapper to separate the estimation and commit phases is well-executed to enable this parallelism. However, I've identified a potential correctness issue with the early-stopping mechanism (stop flag) that could cause the parallel implementation to behave differently from the sequential one, possibly leading to registration failures where it should have succeeded. I've provided a high-severity comment with a suggested fix. Additionally, I have a medium-severity suggestion to restore some useful logging that was removed during the refactoring.

Comment on lines +534 to +544
[&mapper, &mapper_options, &stop, cid]()
-> IncrementalMapper::StructureLessEstimationResult {
if (stop.load()) {
return {};
}
auto result =
mapper.EstimateStructureLessPose(mapper_options, cid);
if (result.success) {
stop.store(true);
}
return result;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

There is a potential correctness issue with the stop flag logic. A successful estimation (result.success == true) does not guarantee a successful commit (mapper.CommitStructureLessRegistration returns true), as the commit phase involves further checks and bundle adjustment which can fail.

By setting stop.store(true) upon a successful estimation, you might be prematurely stopping other estimation tasks that could have led to a successful commit. If the commit for the first successful estimation fails, subsequent estimations might have already been cancelled due to the stop flag, leading to a failure to register any image in this batch. This would be a deviation from the sequential behavior and could lead to a less robust reconstruction.

To ensure correctness and maintain the same behavior as the sequential version, I recommend removing the stop flag optimization from the worker thread. The worker threads should perform the estimation, and the main thread will iterate through the results and stop the thread pool only after a successful commit.

You should remove std::atomic_bool stop = false; on line 530 and modify the lambda to not use stop.

                [&mapper, &mapper_options, cid]()
                    -> IncrementalMapper::StructureLessEstimationResult {
                  return mapper.EstimateStructureLessPose(mapper_options, cid);
                }

Comment on lines +557 to +558
LOG(INFO) << StringPrintf(
"Registering image with structure-less fallback");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This change removed the log message that shows the number of correspondences for the image being registered in the structure-less case. This information is useful for debugging and understanding the registration process. Consider adding it back to improve observability.

              LOG(INFO) << StringPrintf(
                  "Registering image with structure-less fallback");
              LOG(INFO) << StringPrintf(
                  "=> Image sees %d / %d correspondences",
                  mapper.ObservationManager().NumVisibleCorrespondences(
                      next_image_id),
                  mapper.ObservationManager().NumCorrespondences(next_image_id));

@ahojnnes
Copy link
Contributor

My gut reaction is that this is a bit complicated and I'd rather have us have a parallelized implementation of RANSAC.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants