# Container iterators

**URL:** https://discourse.itk.org/t/container-iterators/2774
**Category:** Algorithms
**Tags:** c17, iterator
**Created:** [March 2, 2020, 12:51am UTC](https://discourse.itk.org/t/container-iterators/2774 "2020-03-02T00:51:05Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![Gordian](https://discourse.itk.org/user_avatar/discourse.itk.org/gordian/32/335_2.png) [@Gordian](https://discourse.itk.org/u/Gordian)
#### Post date: [March 2, 2020, 12:51am UTC](https://discourse.itk.org/t/container-iterators/2774/1 "2020-03-02T00:51:05Z")

</div>

Hello,

i would like to know if there is an container iterator that provide the functionality I need for the C++17 features like std::reduce() with an parallel execution policy. This might improve the performance of some filters.

I have something like this in mind:

```
ImageRegionConstIterator<MovingGradientImageType> iter(m_SubtractionImageFilter->GetOutput(), this->GetFixedImageRegion());
MovingGradientPixelType initialValue; initialValue.Fill(0);

TPixelType sum = std::reduce(std::execution::par, iter.GoToBegin(), iter.GoToBegin()+numberOfPixel, initialValue, binary_op);

```

I would like to use the `std::end()` on the image container. is there a workaround or solution for this problem?

Beside the usual [iterators](https://itk.org/Doxygen50/html/ImageIteratorsPage.html) I did not find anything that could help me.

---

<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: [March 2, 2020, 3:37pm UTC](https://discourse.itk.org/t/container-iterators/2774/2 "2020-03-02T15:37:19Z")

</div>

[ImageRange](https://discourse.itk.org/t/imagerange-a-range-of-iterators-to-the-pixels-of-an-image/1455) introduced by @Niels_Dekker might fit the bill.

---

<div class="post-metadata">

### Author: ![Niels\_Dekker](https://discourse.itk.org/letter_avatar_proxy/v4/letter/n/9d8465/32.png) [@Niels\_Dekker](https://discourse.itk.org/u/Niels_Dekker)
#### Post date: [March 2, 2020, 8:51pm UTC](https://discourse.itk.org/t/container-iterators/2774/3 "2020-03-02T20:51:21Z")

</div>

@Gordian If you need `std::reduce` to iterate over the _entire_ image buffer (all pixels), I would recommend [ImageBufferRange](https://itk.org/Doxygen50/html/classitk_1_1Experimental_1_1ImageBufferRange.html). If you need to iterate over a _subregion_ of the image, you may use [ImageRegionRange](https://itk.org/Doxygen/html/classitk_1_1Experimental_1_1ImageRegionRange.html) instead.

Please let us know if that solves your problem!

---

<div class="post-metadata">

### Author: ![Gordian](https://discourse.itk.org/user_avatar/discourse.itk.org/gordian/32/335_2.png) [@Gordian](https://discourse.itk.org/u/Gordian)
#### Post date: [March 2, 2020, 10:26pm UTC](https://discourse.itk.org/t/container-iterators/2774/4 "2020-03-02T22:26:28Z")

</div>

Thanks to @Niels_Dekker and @dzenanz for pointing to this class. It does a good job for single and double precision. Easy to implement.

Here a small code example for comparison:

```
    #include "itkImage.h"
    #include "HighPrecisionTimer.h"
    #include <execution>
    #include "itkImageBufferRange.h"
   
    int main(int argc, char* argv[])
    {
    	auto img = itk::Image<float, 3>::New();
    	itk::Image<float, 3>::IndexType idx;
    	idx.Fill(0);

    	itk::Image<float, 3>::SizeType sz; //arbitrary numbers here
    	sz.Fill(512);
    	sz[2] = 1;

    	itk::Image<float, 3>::RegionType reg(idx, sz);
    	img->SetRegions(reg);
    	img->Allocate();
    	img->FillBuffer(0.1);

    	for (auto i = 0; i < 4; ++i)
    	{
    		itk::ImageRegionConstIterator<itk::Image<float, 3>> iter(img, img->GetLargestPossibleRegion());
    		iter.GoToBegin();
    		float sum = 0;

    		{
    			auto Timer{ HighPrecisionTimer<TimeUnits::Microseconds>() };
    			while (!iter.IsAtEnd())
    			{
    				sum = sum + iter.Get();
    				++iter;
    			}
    		}
    		if(i = 3) std::cout << sum << std::endl; ->257 microseconds

    		itk::Experimental::ImageBufferRange<itk::Image<float, 3>> range{ *img };
    		sum = 0;
    		{
    			auto Timer{ HighPrecisionTimer<TimeUnits::Microseconds>() };
    			for each (auto&& var in range)
    			{
    				sum = sum + var;
    			}
    		}

    		if (i = 3) std::cout << sum << std::endl; -> 251 microseconds

    		sum = 0;
    		{
    			auto Timer{ HighPrecisionTimer<TimeUnits::Microseconds>() };
    			sum = std::reduce(std::execution::par, range.begin(), range.end(), 0.0);
    		}
    		if (i = 3) std::cout << sum << std::endl; -> 223 microseconds

    		sum = 0;
    		{
    			auto Timer{ HighPrecisionTimer<TimeUnits::Microseconds>() };
    			sum = std::reduce(std::execution::par_unseq, range.begin(), range.end(), 0.0);
    		}
    		if (i = 3) std::cout << sum << std::endl; -> 86 microseconds
    	}
    	return 0;
    }  

```

Returns incorrect results for the first two tests. The run times for the four tests are at given numbers. The Timer is basically a class that uses the chrono library. The number are not relable in any way; they are more an idea of the runtime.

Edit: Tried the same with itk::Covariant\<float, 3\> as pixel type. The times were really inconsistent for the range tests but mostly the std::execution::par\_unseq was the fastest.

---

<div class="post-metadata">

### Author: ![Niels\_Dekker](https://discourse.itk.org/letter_avatar_proxy/v4/letter/n/9d8465/32.png) [@Niels\_Dekker](https://discourse.itk.org/u/Niels_Dekker)
#### Post date: [March 3, 2020, 1:41pm UTC](https://discourse.itk.org/t/container-iterators/2774/5 "2020-03-03T13:41:15Z")

</div>

@Gordian Glad to see you got some promising results from using `ImageBufferRange` with `std::reduce`. Did you build in Release mode (optimized for speed)?

Three more questions on your code example:

- When I tried to compile your code example, I got a suspicious warning (four times) from Visual C++ 2017, on `if (i = 3)`:

> warning C4706: assignment within conditional expression

That looks like a bug! Did you mean to write `if (i == 3)` instead?

- `for each (auto&& var in range)` appears to be a Microsoft specific (.NET/CLR) “for each” loop. Could you maybe also try the standard C++ range-based for-loop, `for (auto&& var : range)`? I’d be interested to hear if one is faster than the other!

- I could not compile `HighPrecisionTimer<TimeUnits::Microseconds>`, where can I find the “HighPrecisionTimer.h” header file? For previous benchmarks, I used `std::chrono`, for example:

Another example, using `std::chrono`: [Estimates duration of increasing the capacity of `std::vector\<itk::NeighborhoodAllocator\<int\>\>` · GitHub](https://gist.github.com/N-Dekker/e629feb4f2ebcbc2f085d355d81f0f26)

Kind regards, Niels

---

<div class="post-metadata">

### Author: ![Gordian](https://discourse.itk.org/user_avatar/discourse.itk.org/gordian/32/335_2.png) [@Gordian](https://discourse.itk.org/u/Gordian)
#### Post date: [March 3, 2020, 7:57pm UTC](https://discourse.itk.org/t/container-iterators/2774/6 "2020-03-03T19:57:01Z")

</div>

@Niels_Dekker

- I build the test application in RelWithDebInfo mode (as far as I have seen this is close to release mode)

- You are correct about the warnings. It was late and the compiler does not throw any errors (and as we all know a code without errors is fine…🙂 )

- There is no significant change in duration between the microsoft `for each` and the standard C++ range-based for-loop (at least on my system).

- The `HighPrecisionTimer<TimeUnits::Microseconds>` is basically like your suggestion for time measurements. It’s wrapped in a class and will destroy itself at the end of the scope after the measurement. It’s a custom convenience class for cleaner code.

As small extra I tested the code using `itk::CovariantVector<float,3>` as pixeltype and added a plus functor for the `std::reduce(...)`:

```
auto binary_op = [](VectorPixel num1, VectorPixel num2) {
		VectorPixel sum;
		for (auto i = 0; i < VectorPixel::Dimension; ++i)
			sum[i] = num1[i] + num2[i];
		return sum; };

```

The times using the custom functor are (about):  
2200 microseconds for itk::iterator  
2200 microseconds for ranged-based for-loop  
650 microseconds for `std::reduce(std::execution::par)` (at least twice if `itk::CovariantVector<float,3>::operator+()` is used)  
600 microseconds for `std::reduce(std::execution::par_unseq)` (at least twice if `itk::CovariantVector<float,3>::operator+()` is used)

---

<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: [March 3, 2020, 9:40pm UTC](https://discourse.itk.org/t/container-iterators/2774/7 "2020-03-03T21:40:49Z")

</div>

Did you do these timing tests on a 4-core computer?

It seems you could also use `MultiThreaderBase::ParallelizeImageRegion` with a little custom summing code. Examples:  
[UseParallelizeImageRegion](https://itk.org/ITKExamples/src/Core/Common/UseParallelizeImageRegion/Documentation.html)  
[FilterAndParallelizeImageRegion](https://itk.org/ITKExamples/src/Core/Common/FilterAndParallelizeImageRegion/Documentation.html)

---

<div class="post-metadata">

### Author: ![Gordian](https://discourse.itk.org/user_avatar/discourse.itk.org/gordian/32/335_2.png) [@Gordian](https://discourse.itk.org/u/Gordian)
#### Post date: [March 4, 2020, 12:35am UTC](https://discourse.itk.org/t/container-iterators/2774/8 "2020-03-04T00:35:45Z")

</div>

I did run the test on a 4-core machine (Intel i5-2500K @ 3,30GHz, Windows 10 Pro, VS2017).

I will look at the examples for ParallizedImageRegion. Thanks.
