[Numpy-discussion] Incrementing with advanced indexing: why don't repeated indexes repeatedly increment?
Wed Jun 6 10:34:45 CDT 2012
On Wed, Jun 6, 2012 at 4:30 PM, Robert Cimrman <email@example.com> wrote:
> On 06/06/2012 05:06 PM, Nathaniel Smith wrote:
>> On Wed, Jun 6, 2012 at 9:48 AM, John Salvatier
>> <firstname.lastname@example.org> wrote:
>>> I've noticed that If you try to increment elements of an array with advanced
>>> indexing, repeated indexes don't get repeatedly incremented. For example:
>>> In : x = zeros(5)
>>> In : idx = array([1,1,1,3,4])
>>> In : x[idx] += [2,4,8,10,30]
>>> In : x
>>> Out: array([ 0., 8., 0., 10., 30.])
>>> I would intuitively expect the output to be array([0,14, 0,10,30]) since
>>> index 1 is incremented by 2+4+8=14, but instead it seems to only increment
>>> by 8. What is numpy actually doing here?
>>> The authors of Theano noticed this behavior a while ago so they python loop
>>> through the values in idx (this kind of calculation is necessary for
>>> calculating gradients), but this is a bit slow for my purposes, so I'd like
>>> to figure out how to get the behavior I expected, but faster.
>>> I'm also not sure how to navigate the numpy codebase, where would I look for
>>> the code responsible for this behavior?
>> Strictly speaking, it isn't actually in the numpy codebase at all --
>> what's happening is that the Python interpreter sees this code:
>> x[idx] += vals
>> and then it translates it into this code before running it:
>> tmp = x.__getitem__(idx)
>> tmp = tmp.__iadd__(vals)
>> x.__setitem__(idx, tmp)
>> So you can find the implementations of the ndarray methods
>> __getitem__, __iadd__, __setitem__ (they're called
>> array_subscript_nice, array_inplace_add, and array_ass_sub in the C
>> code), but there's no way to fix them so that this works the way you
>> want it to, because there's no way for __iadd__ to know that the
>> temporary values that it's working with are really duplicate copies of
>> "the same" value in the original array.
>> It would be nice if numpy had some sort of standard API for doing what
>> you want, but not sure what a good API would look like, and someone
>> would have to implement it.
> This operation is also heavily used for the finite element assembling, and a
> similar question has been raised already several times (e.g.
> So why not adding a function np.assemble()?
I read that message, but I don't see what it has to do with this
discussion? It seemed to be about fast ways to assign dense matrices
into sparse matrices, not fast ways of applying in-place arithmetic to
specific spots in a dense matrix.
More information about the NumPy-Discussion