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
DM-13854: extend cache in Psf #334
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few small comments; biggest one is to try to get Cache.h
out of the header files.
Another thought: could we modify the hash function and equality comparison used by the cache for computeKernelImage
to round off to the nearest integer pixel, so tiny changes in the point requested don't result in cache misses? If our PSFs are changing much over the scale of a pixel, we've got bigger problems (or we've already flagged that object with INEXACT_PSF for exactly that reason). Of course, we'd probably want to modify computeKernelImage
itself to do that rounding even when not using the cache, so the cache doesn't change the actual behavior, but I think that'd be fine. And obviously we can't do that rounding in computeImage
.
include/lsst/afw/detection/Psf.h
Outdated
mutable geom::Point2D _cachedImagePosition; | ||
mutable geom::Point2D _cachedKernelImagePosition; | ||
mutable utils::Cache<CacheKey, std::shared_ptr<Image>> _imageCache; | ||
mutable utils::Cache<CacheKey, std::shared_ptr<Image>> _kernelImageCache; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe shared_ptr<Image const>
, because it can be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think I can, unless I cast away the same const
in Psf::computeImage
.
include/lsst/afw/detection/Psf.h
Outdated
@@ -29,6 +29,7 @@ | |||
#include <memory> | |||
|
|||
#include "lsst/daf/base.h" | |||
#include "lsst/utils/Cache.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed on the utils
ticket, I'd prefer to forward-declare Cache
, have Psf
hold it by unique_ptr
, and move this include to the .cc file.
include/lsst/afw/detection/Psf.h
Outdated
|
||
/// Set the capacity of the caches | ||
/// | ||
/// Both the image and kernel image caches will be set to this capacity. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use /** */
for multi-line Doxygen comments.
include/lsst/afw/detection/Psf.h
Outdated
return os << key.position; | ||
} | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hopefully this can be moved to the .cc file, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pulled it out of the class, into a preceding namespace detail
. But it does mess up the top of the file a bit, especially since I have to get into namespace std
to provide the std::hash
support (it's more annoying to work with than boost::hash
).
@@ -364,6 +366,8 @@ PyPoint<T, N> declarePoint(py::module &mod, std::string const &suffix) { | |||
cls.def("__ne__", [](Point<T, N> const &self, Point<T, N> const &other) { return self != other; }, | |||
py::is_operator()); | |||
|
|||
cls.def("__hash__", [](Point<T, N> const &self) { return boost::hash<Point<T, N>>()(self); }); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure it's a good idea to add this to Python; Points are not immutable and hence putting them in dicts could definitely confuse the dict.
d85aeb2
to
e4cb086
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you didn't go quite far enough in moving things to the .cc file to reap the benefits (and doing that should greatly reduce the need for changes in other packages). More comments inline.
include/lsst/afw/detection/Psf.h
Outdated
void setCacheCapacity(std::size_t capacity) { | ||
_imageCache->reserve(capacity); | ||
_kernelImageCache->reserve(capacity); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you define setCacheCapacity
and getCacheCapacity
(and ~Psf()
, I think), you should no longer need to include Cache.h
in other source files that use Psf
. I'm not totally sure that's enough, but the goal here is to make sure that anything that uses Cache
as more than an opaque pointer is in Psf.cc
, and that will make it unnecessary to include Cache.h
anywhere but Psf.cc
.
include/lsst/afw/detection/Psf.h
Outdated
friend std::ostream & operator<<(std::ostream &os, PsfCacheKey const &key) { | ||
return os << key.position; | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need a forward declaration of this class in the header for the typedef later, but the rest can also go in Psf.cc
.
include/lsst/afw/detection/Psf.h
Outdated
mutable image::Color _cachedKernelImageColor; | ||
mutable geom::Point2D _cachedImagePosition; | ||
mutable geom::Point2D _cachedKernelImagePosition; | ||
typedef utils::Cache<detail::PsfCacheKey, std::shared_ptr<Image>> PsfCache; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using PsfCache = utils::Cache<detail::PsfCacheKey, std::shared_ptr<Image>>
is preferred in C++11.
include/lsst/afw/detection/Psf.h
Outdated
mutable geom::Point2D _cachedKernelImagePosition; | ||
typedef utils::Cache<detail::PsfCacheKey, std::shared_ptr<Image>> PsfCache; | ||
mutable std::shared_ptr<PsfCache> _imageCache; | ||
mutable std::shared_ptr<PsfCache> _kernelImageCache; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe these no longer need to be mutable
; the extra layer of indirection does that for you. Since Psf
is already noncopyable and immutable, std::unique_ptr
should be used instead of std::shared_ptr
as well.
src/detection/Psf.cc
Outdated
: daf::base::Citizen(typeid(this)), | ||
_isFixed(isFixed), | ||
_imageCache(new PsfCache(capacity)), | ||
_kernelImageCache(new PsfCache(capacity)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Best practice is to use std::make_shared
to initialize smart pointers when you're constructing the pointee at the same time (or, if you switch to std::unique_ptr
, std::make_unique
).
5e9f969
to
028ffca
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
Two tiny inline comments.
include/lsst/afw/detection.h
Outdated
@@ -26,6 +26,8 @@ | |||
#ifndef LSST_AFW_DETECTION_H | |||
#define LSST_AFW_DETECTION_H | |||
|
|||
#include "lsst/utils/Cache.h" // for afw::detection::Psf | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be removable now.
src/geom/Point.cc
Outdated
@@ -21,6 +21,7 @@ | |||
*/ | |||
|
|||
#include <cmath> | |||
#include <boost/functional/hash.hpp> // boost::hash |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use ""
, not <>
.
Allows its use as a key in lsst::utils::Cache. Deliberately NOT defining Point.__hash__ in python, since Point is mutable so we don't want to be able to use it as the key in a dict.
This allows caching many more realisations (they're relatively cheap: 50x50 pixels per realisation @ 8 bytes per pixel); the number of realisations is configurable. This gains about 22% in the runtime of measureCoaddSources.py using the default 100 cache slots for all Psf instances. Allowing CoaddPsf to use 100000 cache slots increases the gain to about 25%.
028ffca
to
9ecf299
Compare
Larger cache makes things go faster.