Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimplement managed raster class in C++ #1597

Merged

Conversation

emlys
Copy link
Member

@emlys emlys commented Jul 17, 2024

Description

This PR reimplements the ManagedRaster class in C++ for better performance. Tested with sdr.calculate_sediment_deposition and the SDR sample data, it's now just slightly faster than the original implementation on main (0.59 vs 0.61 seconds), whereas the python implementation on feature/routing-refactor takes nearly twice as long.

I'm a beginner at C++ so I'm sure I'm not always using the right conventions or design patterns, but this seems like an okay starting point. I took some guidance from the Google C++ style guide. Ignoring some guidelines that don't seem to make sense in this context. For instance, I have all the code in a header file because splitting it out into ManagedRaster.h and ManagedRaster.cpp significantly slowed it down.

Happy to discuss and walk through this PR on a zoom call as well.

Checklist

  • Updated HISTORY.rst and link to any relevant issue (if these changes are user-facing)
  • Updated the user's guide (if needed)
  • Tested the Workbench UI (if relevant)

@emlys emlys changed the base branch from main to feature/routing-refactor July 17, 2024 18:00
@emlys
Copy link
Member Author

emlys commented Nov 5, 2024

@phargogh this is finally ready for re-review! The biggest change is I figured out how to implement the iterators properly, so they can be iterated with the usual syntax, solving the issues with tracking/incrementing values properly.

@emlys emlys requested a review from phargogh November 5, 2024 19:46
Copy link
Member

@phargogh phargogh left a comment

Choose a reason for hiding this comment

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

Thanks @emlys , this looks good to me! I had a couple of minor comments, and then I also wanted to confirm: what we have here in this PR looks to be intended for MFD routing, specifically, so is D8 routing to be added in a future PR?

setup.py Outdated
Comment on lines 23 to 34
include_dirs = [numpy.get_include(), 'src/natcap/invest/managed_raster']
if platform.system() == 'Windows':
compiler_args = ['/std:c++20']
library_dirs = [f'{os.environ["CONDA_PREFIX"]}/Library/lib']
include_dirs.append(f'{os.environ["CONDA_PREFIX"]}/Library/include')
else:
library_dirs = []
compiler_args = []
compiler_and_linker_args = ['-stdlib=libc++', '-std=c++20']
library_dirs = [subprocess.run(
['gdal-config', '--libs'], capture_output=True, text=True
).stdout.split()[0][2:]] # get the first argument which is the library path
Copy link
Member

Choose a reason for hiding this comment

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

Since we are now building directly against gdal, should we add the new build dependency to pyproject.toml?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmmm... the libraries are a dependency of the build, but the gdal python bindings themselves aren't necessary. I'm not sure there's any standardized way to document that kind of dependency?

setup.py Outdated
else:
library_dirs = []
compiler_args = []
compiler_and_linker_args = ['-stdlib=libc++', '-std=c++20']
Copy link
Member

Choose a reason for hiding this comment

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

Is C++20 truly the minimum language version required? I don't think this should be a huge deal since compilers seem to pretty rapidly adopt the new standards, so I think this is mostly a question of curiosity.

Copy link
Member Author

@emlys emlys Dec 9, 2024

Choose a reason for hiding this comment

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

Good question, I think I used some C++20 features during development, but now only need C++17. (It still compiles with 11, but I get warnings that the inline variables are a C++17 feature.) Updated in d50a2c9 C++20 is needed on the Windows build only, for some reason, otherwise there are a lot of syntax errors, e.g. https://github.com/natcap/invest/actions/runs/12245867222/job/34160661279

Copy link
Member

Choose a reason for hiding this comment

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

Sounds good! Thanks for looking into it.

If I had to guess, maybe the lack of an --ffp-contract=off flag (needed for addressing a compilation bug in viewshed) is causing the rest of the errors? If (big if) that's the only thing standing in the way, then the viewshed tests would fail, which isn't worth it if all we need is a recent enough version of the C++ standard.

Comment on lines 346 to 350
ManagedFlowDirRaster(char* raster_path, int band_id, bool write_mode)
: ManagedRaster(raster_path, band_id, write_mode) // Call the superclass constructor in the subclass' initialization list.
{
// do something with bar
}
Copy link
Member

Choose a reason for hiding this comment

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

Is the plan to still do something in this constructor?

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed in 25c954a

@emlys emlys force-pushed the feature/routing-refactor-compare branch from c01339a to 9b95796 Compare December 10, 2024 03:21
@emlys
Copy link
Member Author

emlys commented Dec 10, 2024

@phargogh yes, the D8 feature is over in #1633. I also got the RTD build working here, and added an env variable to configure with GDAL lib path for windows builds.

@emlys emlys requested a review from phargogh December 10, 2024 21:12
Copy link
Member

@phargogh phargogh left a comment

Choose a reason for hiding this comment

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

Thanks so much @emlys it's looking good!

@@ -119,7 +119,7 @@ jobs:
run: |
# uninstall InVEST if it was already in the restored cache
python -m pip uninstall -y natcap.invest
python -m build --wheel
NATCAP_INVEST_GDAL_LIB_PATH="$CONDA_PREFIX/Library" python -m build --wheel
Copy link
Member

Choose a reason for hiding this comment

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

I see we're repeating this new environment variable in a couple places, so would it interfere with anything to move it to the env block so we only need to define it once? I'm pretty sure we can to a top-level env: mapping to allow the env var to propagate across all of the different sections.

Copy link
Member

Choose a reason for hiding this comment

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

Nope, I see now that we won't know what $CONDA_PREFIX is going to be until after we're in the activated environment, so this seems like the most direct way to define it. 👍

setup.py Outdated
else:
library_dirs = []
compiler_args = []
compiler_and_linker_args = ['-stdlib=libc++', '-std=c++20']
Copy link
Member

Choose a reason for hiding this comment

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

Sounds good! Thanks for looking into it.

If I had to guess, maybe the lack of an --ffp-contract=off flag (needed for addressing a compilation bug in viewshed) is causing the rest of the errors? If (big if) that's the only thing standing in the way, then the viewshed tests would fail, which isn't worth it if all we need is a recent enough version of the C++ standard.

@phargogh phargogh merged commit df352de into natcap:feature/routing-refactor Dec 12, 2024
29 checks passed
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