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
PERF: MeanImageFilter faster, using BufferedImageNeighborhoodPixelAccessPolicy #1365
PERF: MeanImageFilter faster, using BufferedImageNeighborhoodPixelAccessPolicy #1365
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.
Great!
Does median filter have similar implementation pattern? Can this approach be applied to it? |
The median filter should be exploiting coherence of a sorted neighborhood, so the method should be quite difference. Come to think of it the mean could be exploit a moving average as well to reduce repeated adjacent computation. EDIT: And there are there trade off with exploiting the separability of the mean too. |
As for the PR, are there any asserts of validations of the buffered region assumptions? or will be just get "undefined" behavior when the assumptions are not met? |
Thank you both for your comments!
Yes it does 😄 I just did
An attempt to access a location outside the buffered region, using the proposed new pixel access policy, will produce undefined behavior, indeed. The calculation of the index value into the image buffer does not do bounds checking:
That's really a fundamental property of this new pixel access policy. It should be as fast as possible. Within Some more profiling results from VS2017 Release:
Could you please check if you can observe similar performance improvements from this PR? |
I hate always being the nay sayer. But the checks for these assumptions (at least in debug mode) is very important. I have spent a lot of time debugging filters and pipeline issues. With the removal of these safety checks it will make development and maintenance even more difficult and time consuming than it is. |
I would suggest looking at the ConvolutionImageFilter next. There is easily room for 10x-100x performance improvement there. There are faster implementations of the Mean and Median filters in other implementations in ITK. |
With included test, before: 0.3 sec, with this PR: 0.15 sec. 2x speedup, nice! |
Thanks for your comments @blowekamp
Which faster implementation of the Mean filter do you mean? Is the current (v5.1b01) |
The BoxMeanImageFilter performs better for higher dimension images and larger radius as it uses a moving accumulation. This implementation likely performs better for 2-D and smaller radius.
ITK is not about THE implementation for an algorithm. Many algorithms have multiple implementations which perform better in different situations. Others are frequent exemplar of how to do common operations in a generalized templated way. This filter I consider an exemplar filter for doing neighborhood operations, as well as giving good performance for small radius. It is most certainly worth the effort and is a great contribution. Also do you know if these iterators work well with VectorImages? This filter did not work with them before. |
Just added an
|
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, but CI has qualms with it.
Thanks @dzenanz I see at https://open.cdash.org/viewBuildError.php?type=1&buildid=6181856
Even though I did |
What happens if you use ITK/Modules/Core/Common/include/itkImageSource.hxx Lines 247 to 250 in 4967165
|
Unfortunately, same warnings still there, when using
OK! (But then of course: |
Added `BufferedImageNeighborhoodPixelAccessPolicy`, for faster pixel access during neighborhood iteration. Unlike `ConstantBoundaryImageNeighborhoodPixelAccessPolicy` and `ZeroFluxNeumannImageNeighborhoodPixelAccessPolicy`, this new pixel access policy for `ShapedImageNeighborhoodRange` assumes that the pixel index of the selected neighbor is always within the buffered region of the image.
Improved the performance of `MeanImageFilter::Update` by replacing its local `itk::ConstNeighborhoodIterator` variable by an `Experimental::ShapedImageNeighborhoodRange` variable, using the new `BufferedImageNeighborhoodPixelAccessPolicy`. ~40% reduction of the run-time duration was observed on a `filter->Update()` call, using VS2017, processing a 256x256x256 image. For a 1024x1024x16 image, the performance improvement appeared even higher.
Indeed: I just observed that with the "default" radius value (1), The output of
The iterator ranges from With this PR, I did not want to change that logic, because this PR is intended to just improve the performance of existing use cases. If you want to add |
Succeeded on ITK.Linux, ITK.Windows, and ITK.macOS 🎉 The ITK.Linux.Python failures at the dashboard seem unrelated to this PR:
https://open.cdash.org/testDetails.php?test=811772611&build=6183942 |
for (ImageDimensionType i = 0; i < ImageDimension; ++i) | ||
{ | ||
const auto pixelIndexValue = pixelIndex[i]; | ||
assert((pixelIndexValue >= 0) && (static_cast<SizeValueType>(pixelIndexValue) < imageSize[i])); |
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 assertion gets triggered 😄
https://open.cdash.org/testDetails.php?test=819819335&build=6195188
Improved the performance
MeanImageFilter
, usingShapedImageNeighborhoodRange
with a newly added pixel access policy,BufferedImageNeighborhoodPixelAccessPolicy
. Tested performance by: