Reducing Python wrapping memory overhead for a small registration pipeline

Hi!

While migrating ConfUSIus from SimpleITK to ITK, we investigated the Python memory overhead of a small float64 rigid/correlation registration.

We compared ITK 5.4.7 and SimpleITK 2.5.5 on GIL-enabled CPython 3.14.8, using the same small float64 rigid/correlation pipeline, including centered initialization, two pyramid
levels, optimization, and resampling:

Loading approach USS per interpreter Private-dirty library pages
ITK — standard supported API ~498 MiB ~123 MiB
ITK — experimental generated-wrapper imports ~320 MiB ~58 MiB
SimpleITK — standard supported API ~51 MiB ~19 MiB

These are fresh-process measurements after deleting pipeline objects, garbage collection, and malloc trimming. Two independent interpreters loaded each configuration to distinguish
shared library pages from duplicated private memory. Registered arrays, transform parameters, objective values, and all 80 optimizer iteration events matched exactly across
implementations.

The experimental imports select the same underlying ITK C++ classes while bypassing broad Python wrapper-group loading. Importing only the correlation metric narrowly did not help: later public registration-type resolution loaded the broad dependency graph again.

This seems related to #6728’s “first-touch SWIG cost” follow-up. The Metricsv4 → RegistrationCommon dependency chain loads substantially more Python wrappers than this workload appears to need.

Would finer-grained proxy loading/template registration be worthwhile, or is there an existing supported approach I have missed?

During the same migration, we found a GIL-release issue (it seems that ITK is never releasing the GIL although it is supposed to since 5.4.6?). We proposed the GIL-release fix in #7002, but the memory comparison above uses the stock wheel and is independent.

registration_memory_mwe.py (7.5 KB)

1 Like