3

I have a function which has to replace every element x of numpy array X with f(x).

def modify_inplace(X):
    X = 2. / (8. + numpy.exp(-X))

But this doesn't work:

>>> X = numpy.random.random( size=(2,3) )
>>> X
array([[ 0.97476386,  0.76411101,  0.37690288],
       [ 0.05462798,  0.44722799,  0.23570353]])
>>>> modify_inplace(X)
>>> X
array([[ 0.97476386,  0.76411101,  0.37690288],
       [ 0.05462798,  0.44722799,  0.23570353]])

I know, I can simply return new array, but I wonder if it's possible to modify numpy arrays inplace so that no additional memory will be allocated?

Ashwini Chaudhary has provided a solution below, but this is not exactly what I am looking for, because I need to modify array inplace without any additional malloc.

2 Answers 2

7

A true in-place approach for this case could be:

def modify_inplace(X):
    np.exp(X, out=X)
    X += 8.
    np.power(X, -1, out=X)
    X *= 2

Two main advantages over @Ashwini Chaudhary's approach (which is also good):

  • a new array does not need to be allocated
  • no data has to be copied after the operations

EDIT:

Note that for more complicated expressions where X appears more than once the copy is hardly avoided, example:

(X + 2.)/(8. + np.exp(X))

here when you change X in-place to calculate np.exp(X) it will no longer be valid to calculate the rest of the expression...

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. In your second example with two X, what can be another solution to avoid memory allocation?
@psihodelia in this case I only see looping over the array calculating the answer of the expression in a temp variable and replacing the old value... Which could be done in Cython for example
3

Currently you're simply creating a new local variable X and assigning a new value to it, to update the object pointed by X inside the function use slice assignment [:] :

>>> def modify_inplace(X):
        X[:] = 2. / (8. + numpy.exp(-X))
...     
>>> X = numpy.random.random( size=(2,3))
>>> X
array([[ 0.21210661,  0.03573271,  0.07002263],
       [ 0.77282535,  0.13973994,  0.82784145]])
>>> modify_inplace(X)
>>> X
array([[ 0.22704366,  0.22309233,  0.22390467],
       [ 0.23635894,  0.22548971,  0.23705132]])

4 Comments

Thank you. So, in this case Numpy will not allocate any additional storage?
@psihodelia For your case a new array is going to be created in memory first and then the contents of original array are replaced with that array. After that the new array is garbage collected as there are no more references to it.
But this means this array is not modified inplace. While my question is how to avoid memory allocation and modify array inplace - just like you will do it in C. Thanks anyway.
@psihodelia If you want to do this is O(1) extra memory then you'll have to replace the expression on RHS with a simple loop, and then during the loop update the current item in X by the value generated in that iteration.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.