I am currently working on registration of CT images.
Originally, I ran rigid registration in SimpleITK and this was quite fast for each iteration. Overall, the registration process finished after a couple of minutes.
Now I am doing the registration in C++ with ITK. I am using the same registration method, same data, same metric, same optimizer, and same parameters. I am building in release mode and already increased the threads from 12 to 24. However, the overall registration process is now severely slower, which is not at all what I expected.
Does anybody have any ideas here on what could cause it or how I could potentially get more performance out of it? Maybe there are some hidden things that SimpleITK does by default but that I have to manually set in ITK?
You’re right…the C++ should be slightly faster or at least the same. Since the python code is really just specifying a registration framework which is then primarily executed as wrapped C++ functions, the execution shouldn’t be slower for the C++.
Unless someone has addressed this before, it might take some exploration. The cause is likely a configuration / initial condition difference.
Here is my guess at the top two (three?) things to consider (assuming the optimizers, transform, interpolator, metrics, and ITK version are the same):
If the number of iterations used during optimization is about the same, then perhaps the difference is the configuration of the metric. In particular, it may be the portion of the image sampled to compute the metric is different between C++ and Python.
If the number of iterations used during optimization is different, it may be caused by differences in the initial conditions of the transform (e.g., does it begin with an identity transform in both cases, is the center of rotation the same) or the stopping criteria (is the tolerance the same).
It would be interesting to know what you learn. This is likely to be an issue for others as well, in the future.
In SimpleITK, if you set DebugOn it will print the ITK objects before execution of the optimization. This will allow you to inspect their state to compare with the ITK configuration you are using.
In addition to what Stephen suggestion to check, also check the Optimizer’s scales. Are they manually set or do they use an automatic method?
The performance of adding more threads may not be linear and at some point may begin to decrease. I would suggest setting 1 thread in both implementation to better isolate the differences. And initially focus on having both implementation follow the same optimization path through the parameters.
So it turns out that despite me thinking that I set it to release build, this did not happen. I also do not have any release folders in my ITK build. When trying to rebuild it with the Configuration CMAKE_CONFIGURATION_TYPES Debug; Release, only the Debug libraries get built. I can’t find any other options in CMAKE advanced options either. How do I build ITK to include the release mode so that I can build my projects in release mode?
Only one value can be given for the build type. Options include
Release
Debug
RelWithDebInfo
You cannot specify Release and Debug. However, RelWithDebInfo will allow you to get (most of) the speed of release with debugging info embedded. However, there are some warnings with that option. It has been awhile since I used it, but as I recall, the two major considerations are 1) The build size is huge. 2) Line numbers and bug locations might not exactly correspond because compiler optimizations for release speed may cause a bug to involve code optimized from multiple C++ lines or from re-ordered lines.
Thank you for the quick response! This allowed me to build release. But now if I want to switch back to debug, it does not work. Is there a way to have both versions and have them automatically detected? I thought I read about this functionality online.
In the past, it was recommended to have different directories for different ITK build types. I still practice that today (my build directories are called ITK-Release, ITK-Debug, etc.). So, when building a project that uses ITK, I choose which build-version of ITK I want to build against by selecting the appropriate directory during cmake configuration. I find this approach to be very intuitive, explicit, and easy to maintain.
If you don’t want to go that route, we’re going to have to bring in the gurus… @dzenanz ?