Search code examples
pythonnumpyin-place

NumPy in-place operations with overlapping slices


Consider this out-of-place operation:

>>> b = numpy.asarray([1, 2, 3])
>>> b[1:] = b[1:] - b[:-1]
>>> b
array([1, 1, 1])

Now consider the in-place operation:

>>> a = numpy.asarray([1, 2, 3])
>>> a[1:] -= a[:-1]
>>> a
array([1, 1, 2])

They give different results, which I did not expect.

Update: It seems this behavior changed; now they give the same result.

I would have assumed NumPy would have done the subtraction in the correct order (backward) so that they would give equivalent results to the out-of-place subtraction.

My question is: is this intended behavior on NumPy's part, or is it a bug, or is the result undefined?


Solution

  • This behavior was previously undefined, but since NumPy 1.13.0, operations with overlapping input and output now behave as if inputs were copied first. Quoting the release notes:

    Operations where ufunc input and output operands have memory overlap produced undefined results in previous NumPy versions, due to data dependency issues. In NumPy 1.13.0, results from such operations are now defined to be the same as for equivalent operations where there is no memory overlap.

    Operations affected now make temporary copies, as needed to eliminate data dependency. As detecting these cases is computationally expensive, a heuristic is used, which may in rare cases result to needless temporary copies. For operations where the data dependency is simple enough for the heuristic to analyze, temporary copies will not be made even if the arrays overlap, if it can be deduced copies are not necessary. As an example,np.add(a, b, out=a) will not involve copies.

    Here is the relevant issue on GitHub.