DIPlib / diplib

Quantitative Image Analysis in C++, MATLAB and Python
https://diplib.org
Apache License 2.0
222 stars 49 forks source link

Memory leak in EigenDecomposition #131

Closed JannikIrmai closed 1 year ago

JannikIrmai commented 1 year ago

PyDIP (diblib 3.4.0)

Describe the bug When using the EigenDecomposition method to compute Eigen values and vectors simultaneously there seems to be a memory leak.

To Reproduce

To reproduce this I generate a random 3D image, compute the Hessian of that image and then compute the Eigen decomposition of the hessian. I do this three times in a row and delete the results after each iteration. However, the memory is not freed.

import diplib as dip
import matplotlib.pyplot as plt
import numpy as np
import psutil

shape = (100, 500, 500)
n = 3

img = np.random.random(shape)
cpu_percentages = []

for i in range(n):
    cpu_percentages.append(psutil.virtual_memory().percent)
    hessian = dip.Hessian(img, sigmas=1)
    cpu_percentages.append(psutil.virtual_memory().percent)
    eigen_val, eigen_vec = dip.EigenDecomposition(hessian)
    cpu_percentages.append(psutil.virtual_memory().percent)
    del hessian, eigen_val, eigen_vec

fig, ax = plt.subplots()
ax.plot(cpu_percentages)
ax.set_xticks(range(len(cpu_percentages)))
ax.set_xticklabels(["Start", "Hessian", "Eigen"]*n)
ax.set_ylabel("RAM (%)")
plt.show()

image

In each iteration the memory usage increases when the hessian and Eigen decomposition are computed. However, after the iteration the memory usage is only reduced by the amount of the hessian and not the Eigen decomposition.

If, instead of using EigenDecomposition I use the Eigenvalues and, for example, SmallestEigenvector functions then the memory is freed:

image

System information:

crisluengo commented 1 year ago

Thank you for reporting this! And thank you for including the code to reproduce, that makes things a lot easier.

I added the DIPlib tag because my first instinct was that this is a memory leak in the library, but I don’t see any significant difference in the code between EigenDecomposition and SmallestEigenvector. So maybe this is an issue with the bindings after all.

I will try to reproduce the problem and run under valgrind to see where the memory is lost.

crisluengo commented 1 year ago

Indeed, this was a bug in the Python bindings. A reference counting issue.