Skip to content

Instantly share code, notes, and snippets.

@MarcCote
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MarcCote/9053599 to your computer and use it in GitHub Desktop.
Save MarcCote/9053599 to your computer and use it in GitHub Desktop.
Gist showing a potential memory leak when using the 'out' parameter of PyArray_CumSum of the numpy's C-api.
import resource
import numpy as np
from scipy import weave
x = np.ones(1e6, dtype=np.float32)
# There is no memory leak, when we let PyArray_CumSum creates the output array, i.e. when out=NULL.
code_good = r"""
npy_intp shape[1] = { PyArray_SIZE(x_array) };
int dtype = PyArray_DTYPE(x_array)->type_num;
PyArrayObject* res = (PyArrayObject*)PyArray_CumSum(x_array, NPY_MAXDIMS, dtype, NULL);
return_val = (PyObject*)res;
Py_XDECREF(res);
"""
print "RAM: {0:.2}Gb".format(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024.**2)
for i in xrange(100):
weave.inline(code_good, ['x'])
print "RAM: {0:.2}Gb".format(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024.**2)
res = weave.inline(code_good, ['x'])
print np.all(res == np.cumsum(x))
# There is memory leak, when we first create an array let with PyArray_SimpleNew and let
# PyArray_CumSum fills it, i.e. when out=res.
code_leak = r"""
npy_intp shape[1] = { PyArray_SIZE(x_array) };
int dtype = PyArray_DTYPE(x_array)->type_num;
PyArrayObject* res = (PyArrayObject*) PyArray_SimpleNew(1, shape, dtype);
PyArray_CumSum(x_array, NPY_MAXDIMS, dtype, res);
return_val = (PyObject*)res;
Py_XDECREF(res);
"""
print "RAM: {0:.2}Gb".format(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024.**2)
for i in xrange(100):
weave.inline(code_leak, ['x'])
print "RAM: {0:.2}Gb".format(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024.**2)
res = weave.inline(code_leak, ['x'])
print np.all(res == np.cumsum(x))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment