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

Reduce memory usage of MapEvaluator #4989

Merged
merged 5 commits into from Jan 18, 2024
Merged

Conversation

QRemy
Copy link
Contributor

@QRemy QRemy commented Dec 14, 2023

Avoid caching exposure cutout on MapEvaluator. The cutout creates a new array in memory for each source so this does not scale well if the cutout region and the number of sources is large, while the cutout is very fast to compute.

@QRemy QRemy added the performance Performance improvement label Dec 14, 2023
@QRemy
Copy link
Contributor Author

QRemy commented Dec 14, 2023

reference
newplot (6)
this PR
newplot (5)

Copy link

codecov bot commented Dec 14, 2023

Codecov Report

Attention: 1 lines in your changes are missing coverage. Please review.

Comparison is base (ca22055) 75.69% compared to head (8f708ed) 75.69%.

Files Patch % Lines
gammapy/datasets/evaluator.py 95.65% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4989   +/-   ##
=======================================
  Coverage   75.69%   75.69%           
=======================================
  Files         228      228           
  Lines       33841    33851   +10     
=======================================
+ Hits        25616    25624    +8     
- Misses       8225     8227    +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@adonath
Copy link
Member

adonath commented Dec 14, 2023

Are you sure the difference comes from the exposure? The cutout should only return a view and not copy any values. However the cutout geom re-computes the array of coordinates. I would presume the memory usage comes from this.

@QRemy
Copy link
Contributor Author

QRemy commented Dec 14, 2023

Are you sure the difference comes from the exposure? The cutout should only return a view and not copy any values. However the cutout geom re-computes the array of coordinates. I would presume the memory usage comes from this.

from what I understand the cutout creates a new map with a new data array :

data = np.zeros(shape=geom_cutout.data_shape, dtype=self.data.dtype)
data[cutout_slices] = self.data[parent_slices]
return self._init_copy(geom=geom_cutout, data=data)

and the coordinates are not re-computed as they are cached only one time with the lru_cache of the original geom

@QRemy
Copy link
Contributor Author

QRemy commented Dec 15, 2023

I updated the reference plot from my previous comment (it was wrong because I forgot to cherry pick one of the other memory patches in my reference branch).

@adonath
Copy link
Member

adonath commented Dec 15, 2023

I updated the reference plot from my previous #4989 (comment) (it was wrong because I forgot to cherry pick one of the other memory patches in my reference branch).

Thanks, that's even worse. There is a memory leak...

@adonath
Copy link
Member

adonath commented Dec 15, 2023

and the coordinates are not re-computed as they are cached only one time with the lru_cache of the original geom

Yes, but no...

As we create a cutout geom for each source, it is a new object. The first time we access the coordinates on the cutout geom, they are re-computed and cached. Worst case, when there are a lot of source and large support, we duplicate all the coordination information. In this case it might be better to create a cutout from the original larger coordinate arrays. But this highly depends on the analysis scenario, for few sources computing the coordinates on the cutouts is probably much better.

from what I understand the cutout creates a new map with a new data array :

Yes, you are right. I might be worth to only work with view and give up on the not fully contained cutouts, but trim instead.

@QRemy
Copy link
Contributor Author

QRemy commented Dec 15, 2023

Thanks, that's even worse. There is a memory leak...

For this test I have 32 sources, and each new peak corresponds to the npred computation of a source

@QRemy
Copy link
Contributor Author

QRemy commented Dec 15, 2023

As we create a cutout geom for each source, it is a new object. The first time we access the coordinates on the cutout geom, they are re-computed and cached. Worst case, when there are a lot of source and large support, we duplicate all the coordination information. In this case it might be better to create a cutout from the original larger coordinate arrays. But this highly depends on the analysis scenario, for few sources computing the coordinates on the cutouts is probably much better.

Right, at least we could save memory on coordinates caching by returning a 2D meshgrid for lon, lat if the geom is regular and a 1d array for the axes instead of a ND meshgrid for each axis. I will try that in another PR.

@adonath
Copy link
Member

adonath commented Dec 15, 2023

For this test I have 32 sources, and each new peak corresponds to the npred computation of a source

Ok ,thanks for clarifying. It thought it was multiple npred evaluations. But it is only one with 32 sources.

Signed-off-by: Quentin Remy <quentin.remy@mpi-hd.mpg.de>
Signed-off-by: Quentin Remy <quentin.remy@mpi-hd.mpg.de>
Signed-off-by: Quentin Remy <quentin.remy@mpi-hd.mpg.de>
@QRemy QRemy force-pushed the memory_opti branch 2 times, most recently from 1758c23 to 945542f Compare January 1, 2024 15:18
Signed-off-by: Quentin Remy <quentin.remy@mpi-hd.mpg.de>
Signed-off-by: Quentin Remy <quentin.remy@mpi-hd.mpg.de>
@QRemy QRemy added this to the 1.2 milestone Jan 1, 2024
Copy link
Contributor

@registerrier registerrier left a comment

Choose a reason for hiding this comment

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

Thanks @QRemy . This looks good. No comment from my side.

@registerrier registerrier added the trigger-benchmarks run profiler in gammapy-benchmarks label Jan 18, 2024
@registerrier registerrier merged commit 9faaff3 into gammapy:main Jan 18, 2024
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Performance improvement trigger-benchmarks run profiler in gammapy-benchmarks
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants