# Why ResampleImageFilter is slow?

**URL:** https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217
**Category:** Uncategorized
**Created:** [August 21, 2018, 1:23pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217 "2018-08-21T13:23:34Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![denis.p.shamonin](https://discourse.itk.org/user_avatar/discourse.itk.org/denis.p.shamonin/32/112_2.png) [@denis.p.shamonin](https://discourse.itk.org/u/denis.p.shamonin)
#### Post date: [August 21, 2018, 1:23pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/1 "2018-08-21T13:23:34Z")

</div>

Dear developers,

I’ve notices strange performance drop in ResampleImageFilter.  
Here is my logs from ITK 4.12.2, 25 Oct 2017 on the same machine same compiler etc.

ITK 4.12.2  
ResampleImageFilter ; 3 ; 512x512x256 ; 79.6922 sec

ITK 5.0.0  
ResampleImageFilter ; 3 ; 512x512x256 ; 131.241 sec

Interpolator : BSplineInterpolateImageFunction, Transform : CompositeTransform [TranslationTransform, TranslationTransform, BSplineTransform, BSplineTransform, BSplineTransform]

Almost twice performance drop for for all other interpolation and transform combination as well.

More detailed log could be found in CPUGPULog-10-25-17-GPU-GeForce-GTX-980-Ti.txt of the  
[http://www.insight-journal.org/browse/publication/884](http://www.insight-journal.org/browse/publication/884)

Regards, Denis P. Shamonin

---

<div class="post-metadata">

### Author: ![denis.p.shamonin](https://discourse.itk.org/user_avatar/discourse.itk.org/denis.p.shamonin/32/112_2.png) [@denis.p.shamonin](https://discourse.itk.org/u/denis.p.shamonin)
#### Post date: [August 21, 2018, 1:28pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/2 "2018-08-21T13:28:43Z")

</div>

Here is performance logs to compare  
[CPUGPULog-08-21-18-GPU-GeForce-GTX-980-Ti.txt](https://discourse.itk.org/uploads/default/original/1X/c80635b8903449569f22d277b0e062333718cfb0.txt) (38.8 KB)  
[CPUGPULog-10-25-17-GPU-GeForce-GTX-980-Ti.txt](https://discourse.itk.org/uploads/default/original/1X/c230c0a013b4ad2499f14f51d3bc3f70100f26c7.txt) (39.1 KB)

---

<div class="post-metadata">

### Author: ![denis.p.shamonin](https://discourse.itk.org/user_avatar/discourse.itk.org/denis.p.shamonin/32/112_2.png) [@denis.p.shamonin](https://discourse.itk.org/u/denis.p.shamonin)
#### Post date: [August 21, 2018, 1:39pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/3 "2018-08-21T13:39:14Z")

</div>

Why is it slow in general?

The OpenCL implementation on Intel OpenCL SDK on CPU (not GPU) is faster by the factor of 3.  
Here is my log from OpenCL execution on ITK CPU vs Intel OpenCL CPU:

[CPUGPULog-10-25-17-CPU-Intel®-Xeon®-CPU-E5-1620-v3-@-3.50GHz.txt](https://discourse.itk.org/uploads/default/original/1X/13e07e2bc24a7953e7d69e52af8941e983254cec.txt) (38.8 KB)

You could get image 512x512x256 to be re-sampled on CPU with BSpline interpolation and number of BSpline transforms plus extra in 18 sec, but now you have to wait 131 sec.

---

<div class="post-metadata">

### Author: ![denis.p.shamonin](https://discourse.itk.org/user_avatar/discourse.itk.org/denis.p.shamonin/32/112_2.png) [@denis.p.shamonin](https://discourse.itk.org/u/denis.p.shamonin)
#### Post date: [August 23, 2018, 9:20am UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/4 "2018-08-23T09:20:29Z")

</div>

After cooling down. I’ve probably found somebody to blame for this performance drop.  
It most likely the Microsoft compiler 2015. I did performance tests for  
ITK.4.12.2 with VS-2013 and VS-2015 (all updates installed)  
[CPUGPULog-08-23-18-GPU-GeForce-GTX-980-Ti-ITK.4.12.2.VS-2013.txt](https://discourse.itk.org/uploads/default/original/1X/936f1cc093af4abf14f93f8505b10ba8997686fa.txt) (29.6 KB)  
[CPUGPULog-08-23-18-GPU-GeForce-GTX-980-Ti-ITK.4.12.2.VS-2015.txt](https://discourse.itk.org/uploads/default/original/1X/695e7b755646ea04f33d32e60d7ae0f8d13e8852.txt) (29.4 KB)

You could see like 40% performance drop in ResampleImageFilter.

I’ve build everything without any extra setting for CMake, compiler or anything else, just ITK out of the box.  
I can not test VS-2013 compiler with ITK 5.0.0 because it was dropped. Currently VS-2015 is our production compiler of choice for Windows. I did not pay attention when we made a compiler switch.

If anyone knows what could be adjusted to get it at least to VS-2013 speed, let me know.  
Sorry for too many edits on the posts. Was a bit unhappy with such performance drop after years of battles for milliseconds optimization on GPU.

Anyway, let me know if you have some ideas.

---

<div class="post-metadata">

### Author: ![dzenanz](https://discourse.itk.org/user_avatar/discourse.itk.org/dzenanz/32/1093_2.png) [@dzenanz](https://discourse.itk.org/u/dzenanz)
#### Post date: [August 23, 2018, 2:25pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/5 "2018-08-23T14:25:54Z")

</div>

I just had a discussion with @matt.mccormick. He thinks it would be good to add a [benchmark](https://github.com/InsightSoftwareConsortium/ITKPerformanceBenchmarking/tree/master/examples/Filtering) for resampling. That way we will be able to track performance of resampling as we develop and maintain ITK. If you are willing to create that benchmark, that would be great. Otherwise, he will probably find some time to do it over the next few weeks.

Also, I plan to refactor domain threaders which are heavily used in the registration. Once I get started, general feedback and code reviews will be welcome.

---

<div class="post-metadata">

### Author: ![blowekamp](https://discourse.itk.org/user_avatar/discourse.itk.org/blowekamp/32/79_2.png) [@blowekamp](https://discourse.itk.org/u/blowekamp)
#### Post date: [August 23, 2018, 2:51pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/6 "2018-08-23T14:51:32Z")

</div>

I did a quick profiling of Resampling with the BSplineIterpolator.

It appears the current ITK implementation is optimized for resampling an entire image. During the BSplineIterpolator::SetImage method, which is called during initialization the[BSplineDecompositionImageFilter](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=2ahUKEwjwl_ORtYPdAhUFYawKHX_3DhIQFjAAegQIARAB&url=https%3A%2F%2Fitk.org%2FDoxygen%2Fhtml%2Fclassitk_1_1BSplineDecompositionImageFilter.html&usg=AOvVaw1JoLtEUwZ9FapnxGLOZzCF) is called on the entire input image to create coefficient images. This filter is still single threaded! That appears to be the most obvious bottleneck.

Aside from that, I recommend you profile and time the results of compilers with different flags, architectures, and optimization flags. Constructively sharing comparisons of different compilers performance and the effect flags have would be quite welcomed, perhaps even with little easy to digest figures 🙂

---

<div class="post-metadata">

### Author: ![denis.p.shamonin](https://discourse.itk.org/user_avatar/discourse.itk.org/denis.p.shamonin/32/112_2.png) [@denis.p.shamonin](https://discourse.itk.org/u/denis.p.shamonin)
#### Post date: [August 27, 2018, 10:01am UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/7 "2018-08-27T10:01:20Z")

</div>

I will try to make it, have a bit of time somewhere around this weeks. Will modify my test forwards **ITKPerformanceBenchmarking** style. That test already contains most of the checks requred like 1/2/3D, interpolations (Nearest, Linear, BSpline) and transforms (BSpline, Euler2D/3D, Similarity2D/3D, Translation).

---

<div class="post-metadata">

### Author: ![grothausmann.roman](https://discourse.itk.org/user_avatar/discourse.itk.org/grothausmann.roman/32/582_2.png) [@grothausmann.roman](https://discourse.itk.org/u/grothausmann.roman)
#### Post date: [August 28, 2018, 7:06am UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/8 "2018-08-28T07:06:10Z")

</div>

I’d love to see the itkResampleImageFilter to be multi threaded (at least for simple resampling with an identity transform), but when I had a look at the source to see if I could get that implemented I had to agree to the comment there that this is far from trivial in case of an arbitrary transform. Perhaps it could be split for unit transforms (i.e. no transform) or given a new filter (like itkResampleWithUnitTransformImageFilter) for the cases where just up/down sampling is needed.

---

<div class="post-metadata">

### Author: ![dzenanz](https://discourse.itk.org/user_avatar/discourse.itk.org/dzenanz/32/1093_2.png) [@dzenanz](https://discourse.itk.org/u/dzenanz)
#### Post date: [August 28, 2018, 1:39pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/9 "2018-08-28T13:39:19Z")

</div>

ResampleImageFilter is [multi-threaded](https://github.com/InsightSoftwareConsortium/ITK/blob/81640193a45a465f6ab546c146df0f7db9d44440/Modules/Filtering/ImageGrid/include/itkResampleImageFilter.hxx#L178).

---

<div class="post-metadata">

### Author: ![grothausmann.roman](https://discourse.itk.org/user_avatar/discourse.itk.org/grothausmann.roman/32/582_2.png) [@grothausmann.roman](https://discourse.itk.org/u/grothausmann.roman)
#### Post date: [August 28, 2018, 2:57pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/10 "2018-08-28T14:57:02Z")

</div>

Sorry, mixed up multi-threading and [streaming](https://github.com/InsightSoftwareConsortium/ITK/blob/81640193a45a465f6ab546c146df0f7db9d44440/Modules/Filtering/ImageGrid/include/itkResampleImageFilter.hxx#L465-L469) which is (if I’m not mistaken) still not possible?

---

<div class="post-metadata">

### Author: ![dzenanz](https://discourse.itk.org/user_avatar/discourse.itk.org/dzenanz/32/1093_2.png) [@dzenanz](https://discourse.itk.org/u/dzenanz)
#### Post date: [August 28, 2018, 4:10pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/11 "2018-08-28T16:10:05Z")

</div>

The streaming should be possible downstream from resample filter. But upstream will be processed whole, as resample requests the entire input. And resample filter itself can process the image in chunks.

It is not easy, and it is probably infeasible to determine the correct input region for arbitrary transform. But for MatrixWithOffset and its descendants it is possible. If you would like to go ahead and handle those special cases, it would be welcome.

---

<div class="post-metadata">

### Author: ![grothausmann.roman](https://discourse.itk.org/user_avatar/discourse.itk.org/grothausmann.roman/32/582_2.png) [@grothausmann.roman](https://discourse.itk.org/u/grothausmann.roman)
#### Post date: [August 29, 2018, 8:01am UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/12 "2018-08-29T08:01:37Z")

</div>

> And resample filter itself can process the image in chunks.

Can it? If so, it is unclear to me why those chunks cannot be used for streaming?

---

<div class="post-metadata">

### Author: ![dzenanz](https://discourse.itk.org/user_avatar/discourse.itk.org/dzenanz/32/1093_2.png) [@dzenanz](https://discourse.itk.org/u/dzenanz)
#### Post date: [August 29, 2018, 1:57pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/13 "2018-08-29T13:57:30Z")

</div>

That’s what I am saying. The streaming can work for this filter, and the ones after. But since it request the entire input even for partial output, the streaming before this filter is broken. Unless you manually insert [streaming filter](https://itk.org/Doxygen/html/classitk_1_1StreamingImageFilter.html).

---

<div class="post-metadata">

### Author: ![matt.mccormick](https://discourse.itk.org/user_avatar/discourse.itk.org/matt.mccormick/32/7_2.png) [@matt.mccormick](https://discourse.itk.org/u/matt.mccormick)
#### Post date: [August 29, 2018, 2:28pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/14 "2018-08-29T14:28:02Z")

</div>

We could add streaming to `ResampleImageFilter` for linear transforms, i.e. MatrixWithOffset or transforms whose `IsLinear()` method returns `true`, by transforming the bounding box defined by the output `RequestedRegion` and setting the input `RequestedRegion` to the bounds area in voxel space in `ResampleImageFilter::GenerateInputRequestedRegion`.

---

<div class="post-metadata">

### Author: ![grothausmann.roman](https://discourse.itk.org/user_avatar/discourse.itk.org/grothausmann.roman/32/582_2.png) [@grothausmann.roman](https://discourse.itk.org/u/grothausmann.roman)
#### Post date: [August 30, 2018, 11:16am UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/15 "2018-08-30T11:16:58Z")

</div>

Gave it a try but I feel unfamiliar with some of the ITK internals here. What do you think of:

> <https://github.com/romangrothausmann/ITK/commit/99cd8dd7b4e408705b457605c0b7298d414c44bb>

---

<div class="post-metadata">

### Author: ![dzenanz](https://discourse.itk.org/user_avatar/discourse.itk.org/dzenanz/32/1093_2.png) [@dzenanz](https://discourse.itk.org/u/dzenanz)
#### Post date: [August 30, 2018, 12:46pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/16 "2018-08-30T12:46:59Z")

</div>

Looks reasonable to me. Have you tested it, and does it work? What happens with composite transforms?

---

<div class="post-metadata">

### Author: ![grothausmann.roman](https://discourse.itk.org/user_avatar/discourse.itk.org/grothausmann.roman/32/582_2.png) [@grothausmann.roman](https://discourse.itk.org/u/grothausmann.roman)
#### Post date: [August 30, 2018, 1:27pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/17 "2018-08-30T13:27:01Z")

</div>

Thanks @dzenanz for your feedback. It compiles and works with streaming in the frame of my simple [resample\_SDI CLI](https://github.com/romangrothausmann/ITK-CLIs/blob/master/resample_SDI.cxx). The output is nearly the same as without streaming ([resample CLI](https://github.com/romangrothausmann/ITK-CLIs/blob/master/resample.cxx)) except that the SDI output is larger in extent (in my case one more z-slice at the end). Disregarding this slice leads to a difference image that is const. zero.  
Are there any test in the ITK test suite that would be appropriate for testing this?

---

<div class="post-metadata">

### Author: ![dzenanz](https://discourse.itk.org/user_avatar/discourse.itk.org/dzenanz/32/1093_2.png) [@dzenanz](https://discourse.itk.org/u/dzenanz)
#### Post date: [August 30, 2018, 1:44pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/18 "2018-08-30T13:44:56Z")

</div>

There are [several tests](https://github.com/InsightSoftwareConsortium/ITK/tree/master/Modules/Filtering/ImageGrid/test) for resample filter. For example, before [this line](https://github.com/InsightSoftwareConsortium/ITK/blob/76d21ce1a7aef664377b90a5814698472099944f/Modules/Filtering/ImageGrid/test/itkResampleImageTest2.cxx#L156) add `writer1->SetNumberOfStreamDivisions(8); //split into 8 pieces for streaming`. And you can similarly enable streaming in other tests too, but please not all of them.

---

<div class="post-metadata">

### Author: ![blowekamp](https://discourse.itk.org/user_avatar/discourse.itk.org/blowekamp/32/79_2.png) [@blowekamp](https://discourse.itk.org/u/blowekamp)
#### Post date: [August 30, 2018, 2:03pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/19 "2018-08-30T14:03:34Z")

</div>

Depending on the interpolation, you will need to pad the requested region to account for the input area of interpolator selected. What is the padding for nearest? Linear? Bspline? Previously in this thread I noted that the bspline interpolator operated on the entire input, that will need some special consideration.

---

<div class="post-metadata">

### Author: ![grothausmann.roman](https://discourse.itk.org/user_avatar/discourse.itk.org/grothausmann.roman/32/582_2.png) [@grothausmann.roman](https://discourse.itk.org/u/grothausmann.roman)
#### Post date: [August 30, 2018, 2:16pm UTC](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217/20 "2018-08-30T14:16:55Z")

</div>

Hm, sure the padding should be considered, I’m a bit lost on this and wondering how it was done for the itkWarpImageFilter. Some of my code is based on the ideas of [this contribution](https://github.com/InsightSoftwareConsortium/ITK/commit/8510db2df6606837126486c47aba58f0c278b801) but it is not clear to me how the padding for the chosen interpolator entered there.

[Next page](https://discourse.itk.org/t/why-resampleimagefilter-is-slow/1217.md?page=2)
