Skip to content

Avoid calling ImageConstIterator::GetIndex() iteratively, in transforms and metrics#1410

Merged
N-Dekker merged 5 commits intomainfrom
Use-iterator-WithIndex-when-calling-GetIndex
Feb 24, 2026
Merged

Avoid calling ImageConstIterator::GetIndex() iteratively, in transforms and metrics#1410
N-Dekker merged 5 commits intomainfrom
Use-iterator-WithIndex-when-calling-GetIndex

Conversation

@N-Dekker
Copy link
Copy Markdown
Member

@N-Dekker N-Dekker commented Feb 13, 2026

ImageConstIterator::GetIndex() is relatively expensive, as it computes the index with each call, by doing m_Image->ComputeIndex(m_Offset) internally.

This pull request avoids calling ImageConstIterator::GetIndex(), either by using an iterator "with index" (for example ImageRegionIteratorWithIndex), or by using an iterator "with only index" (ImageRegionConstIteratorWithOnlyIndex), instead.

Doing so should improve the performance of initialization of metrics. Moreover, it specifically improves the performance of the "DistancePreservingRigidityPenalty" and the "TransformRigidityPenalty" metric. It also improves the performance of the "BSplineTransformWithDiffusion" and the "MultiBSplineTransformWithNormal" transform.


See also:

When calling `it.GetIndex()` on each iteration, ITK's `ImageRegionIteratorWithIndex` is much faster than `ImageRegionIterator`.

This commit will improve the performance of the "TransformRigidityPenalty" metric.

Removed the unnecessary public `RigidityImageIteratorType = ImageRegionIterator` type alias.
When calling `it.GetIndex()` on each iteration, `ImageRegionIteratorWithIndex` is much faster than `ImageRegionIterator`.

This yields a performance improvement when using a mask. ComputeImageExtremaFilter is being used during the initialization of metrics.
When calling `it.GetIndex()` on each iteration, ITK's `ImageRegionIteratorWithIndex` is much faster than `ImageRegionIterator`.

This commit will improve the performance of the "MultiBSplineTransformWithNormal" transform.
@N-Dekker
Copy link
Copy Markdown
Member Author

Regarding the use of an iterator "With Index" (versus using an iterator without index), proposed for TransformRigidityPenaltyTerm, ComputeImageExtremaFilter, and MultiBSplineDeformableTransformWithNormal, I observed that ImageRegionConstIteratorWithIndex is much faster than ImageRegionConstIterator (without index), when both the index and the pixel value are retrieved iteratively. I tried the following for a large 2D image:

for (IteratorType it{ image, region }; !it.IsAtEnd(); ++it)
{
    const auto& index = it.GetIndex();
    result += it.Get() + (index[0] + index[1]) % 8;
}

Using VS2026, Release build and ITK v6.0b02, I observed that ImageRegionConstIterator (without index) can take twice as much time as ImageRegionConstIteratorWithIndex.

@N-Dekker
Copy link
Copy Markdown
Member Author

N-Dekker commented Feb 15, 2026

To my surprise, when only the index is retrieved, both ImageRegionConstIteratorWithIndex and ImageRegionConstIterator appear faster than ImageRegionIndexRange, on a large 2D image. (ImageRegionConstIteratorWithIndex is then almost 3x as fast as ImageRegionConstIterator, and almost 4x as fast as ImageRegionIndexRange.) 🤔


@N-Dekker N-Dekker force-pushed the Use-iterator-WithIndex-when-calling-GetIndex branch from 7e6a612 to fa75a2b Compare February 22, 2026 13:56
Iterative retrieval of n-dimensional index values is much faster when using `ImageRegionIteratorWithOnlyIndex` than when using a regular `ImageRegionIterator` (which "computes" the index with each iteration).

This commit will improve the performance of the "DistancePreservingRigidityPenalty" metric.
Iterative retrieval of n-dimensional index values is much faster when using `ImageRegionConstIteratorWithOnlyIndex` than when using a regular `ImageRegionConstIterator` (which "computes" the index with each iteration).

This commit will improve the performance of the "BSplineTransformWithDiffusion" transform.

Removed the nested `DummyIteratorType` typedef, that is no longer used by now.
@N-Dekker N-Dekker force-pushed the Use-iterator-WithIndex-when-calling-GetIndex branch from fa75a2b to fec8631 Compare February 22, 2026 14:01
@N-Dekker N-Dekker merged commit ce4bfc1 into main Feb 24, 2026
8 checks passed
@N-Dekker N-Dekker deleted the Use-iterator-WithIndex-when-calling-GetIndex branch February 24, 2026 09:37
N-Dekker added a commit to N-Dekker/ITKElastix that referenced this pull request Mar 13, 2026
Upgraded to SuperElastix/elastix@d6affa8

Including:

* ENH: use utf-8 via manifest on Windows by codeling in SuperElastix/elastix#1401
* ENH: Add relative path to lib directory to RPATH on Linux and MacOS in SuperElastix/elastix#1404
* COMP: Replace MersenneTwister Initialize calls in tests with SetSeed in SuperElastix/elastix#1406
* COMP: Use GTest::gtest and GTest::gtest_main targets for ITK > v5.4.5 in SuperElastix/elastix#1408
* Upgrade to Doxygen v1.16.1 in SuperElastix/elastix#1409
* Avoid calling `ImageConstIterator::GetIndex()` iteratively, in transforms and metrics in SuperElastix/elastix#1410
* DOC: Exclude GTesting from Doxygen in SuperElastix/elastix#1411
* ENH: Lazy loading for optional components (IMPACT) by vboussot in SuperElastix/elastix#1396
* Small MainBase style improvements regarding lazy component loading in SuperElastix/elastix#1412
* Reduce `#if` blocks in `MainBase::TryLoadComponentPlugin` in SuperElastix/elastix#1414
* STYLE: Remove deprecated member functions from `elx::ParameterObject` in SuperElastix/elastix#1417
* Remove VERSION and SOVERSION target properties, replace "elx" prefix with "elx-", for library files  in SuperElastix/elastix#1416
N-Dekker added a commit to N-Dekker/ITKElastix that referenced this pull request Mar 16, 2026
Upgraded to SuperElastix/elastix@d6affa8

Including:

* ENH: use utf-8 via manifest on Windows by codeling in SuperElastix/elastix#1401
* ENH: Add relative path to lib directory to RPATH on Linux and MacOS in SuperElastix/elastix#1404
* COMP: Replace MersenneTwister Initialize calls in tests with SetSeed in SuperElastix/elastix#1406
* COMP: Use GTest::gtest and GTest::gtest_main targets for ITK > v5.4.5 in SuperElastix/elastix#1408
* Upgrade to Doxygen v1.16.1 in SuperElastix/elastix#1409
* Avoid calling `ImageConstIterator::GetIndex()` iteratively, in transforms and metrics in SuperElastix/elastix#1410
* DOC: Exclude GTesting from Doxygen in SuperElastix/elastix#1411
* ENH: Lazy loading for optional components (IMPACT) by vboussot in SuperElastix/elastix#1396
* Small MainBase style improvements regarding lazy component loading in SuperElastix/elastix#1412
* Reduce `#if` blocks in `MainBase::TryLoadComponentPlugin` in SuperElastix/elastix#1414
* STYLE: Remove deprecated member functions from `elx::ParameterObject` in SuperElastix/elastix#1417
* Remove VERSION and SOVERSION target properties, replace "elx" prefix with "elx-", for library files  in SuperElastix/elastix#1416
N-Dekker added a commit to N-Dekker/ITKElastix that referenced this pull request Mar 17, 2026
Upgraded to SuperElastix/elastix@ef34ca9

Including:

* ENH: use utf-8 via manifest on Windows by codeling in SuperElastix/elastix#1401
* ENH: Add relative path to lib directory to RPATH on Linux and MacOS in SuperElastix/elastix#1404
* COMP: Replace MersenneTwister Initialize calls in tests with SetSeed in SuperElastix/elastix#1406
* COMP: Use GTest::gtest and GTest::gtest_main targets for ITK > v5.4.5 in SuperElastix/elastix#1408
* Upgrade to Doxygen v1.16.1 in SuperElastix/elastix#1409
* Avoid calling `ImageConstIterator::GetIndex()` iteratively, in transforms and metrics in SuperElastix/elastix#1410
* DOC: Exclude GTesting from Doxygen in SuperElastix/elastix#1411
* ENH: Lazy loading for optional components (IMPACT) by vboussot in SuperElastix/elastix#1396
* Small MainBase style improvements regarding lazy component loading in SuperElastix/elastix#1412
* Reduce `#if` blocks in `MainBase::TryLoadComponentPlugin` in SuperElastix/elastix#1414
* STYLE: Remove deprecated member functions from `elx::ParameterObject` in SuperElastix/elastix#1417
* Remove VERSION and SOVERSION target properties, replace "elx" prefix with "elx-", for library files  in SuperElastix/elastix#1416
* STYLE: Remove redundant `file(MAKE_DIRECTORY ...)` calls from CMakeLists in SuperElastix/elastix#1418
* ENH: Use the full date and time (RFC 2822) in Doxygen generated HTML in SuperElastix/elastix#1419
* ENH: Let ParameterObject throw an exception when index is out of range in SuperElastix/elastix#1420
* ENH: ParameterObject.GetParameter throw when parameter name is not there in SuperElastix/elastix#1422
* ENH: Add Chinese chars to path names Testing/Data and output directory in SuperElastix/elastix#1421
* Add patch version number to library file names,  bump elastix version to 5.3.1 in SuperElastix/elastix#1423
N-Dekker added a commit to N-Dekker/ITKElastix that referenced this pull request Mar 20, 2026
Upgraded to https://github.com/SuperElastix/elastix/releases/tag/5.3.1

Including:

* ENH: use utf-8 via manifest on Windows by codeling in SuperElastix/elastix#1401
* ENH: Add relative path to lib directory to RPATH on Linux and MacOS in SuperElastix/elastix#1404
* Avoid calling `ImageConstIterator::GetIndex()` iteratively, in transforms and metrics in SuperElastix/elastix#1410
* ENH: Lazy loading for optional components (IMPACT) by vboussot in SuperElastix/elastix#1396
* STYLE: Remove deprecated member functions from `elx::ParameterObject` in SuperElastix/elastix#1417
* Remove VERSION and SOVERSION target properties, replace "elx" prefix with "elx-", for library files  in SuperElastix/elastix#1416
* ENH: Let ParameterObject throw an exception when index is out of range in SuperElastix/elastix#1420
* ENH: ParameterObject.GetParameter throw when parameter name is not there in SuperElastix/elastix#1422
* ENH: Add Chinese chars to path names Testing/Data and output directory in SuperElastix/elastix#1421
* Add patch version number to library file names,  bump elastix version to 5.3.1 in SuperElastix/elastix#1423
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant