[Numpy-discussion] Changes to generalized ufunc core dimension checking
njs at pobox.com
Wed Mar 16 13:55:26 EDT 2016
On Mar 16, 2016 9:52 AM, "Travis Oliphant" <travis at continuum.io> wrote:
> Hi everyone,
> Can you help me understand why the stricter changes to generalized ufunc
argument checking no now longer allows scalars to be interpreted as 1-d
arrays in the core-dimensions?
> Is there a way to specify in the core-signature that scalars should be
allowed and interpreted in those cases as an array with all the elements
the same? This seems like an important feature.
Can you share some example of when this is useful?
The reasoning for the change was that broadcasting is really about aligning
a set of core elements for parallel looping, and in the gufunc case with
arbitrary core kernels that might or might not have any simple loop
structure inside them, it's not at all obvious that it makes sense. (Of
course we still use broadcasting to line up different instances of the core
elements themselves, just not to manufacture the internal shape of the core
elements.) In fact there are examples where it clearly doesn't make sense,
I don't think we were able to come up with any compelling examples where it
did make sense (which is one reason why I'm interested to hear what yours
is :-)), and there's not a single obvious way to reconcile broadcasting
rules and gufunc's named axis matching, so, when in doubt refuse the
temptation to guess.
(Example of when it doesn't make sense: matrix_multiply with
(n,k),(k,m)->(n,m) used to produce all kinds of different counterintuitive
behaviors if one or both of the inputs were scalar or 1d. In this case
making it an error is a clear improvement IMHO. And for something like inv
that takes a single input with signature (n,n), if you get (1,n) do you
broadcast that to (n,n)? If not, why not? For regular broadcasting the
question makes no sense but once you have named axis matching then suddenly
it's not obvious.)
> Here's an example:
> myfunc with core-signature (t),(k),(k) -> (t)
> called with myfunc(arr1, arr2, scalar2).
> This used to work in 1.9 and before and scalar2 was interpreted as a 1-d
array the same size as arr2. It no longer works with 1.10.0 but I don't
see why that is an improvement.
> Thoughts? Is there a work-around that doesn't involve creating a 1-d
array the same size as arr2 and filling it with scalar2?
A better workaround would be to use one of the np.broadcast* functions to
request exactly the broadcasting you want and make an arr2-sized view of
the scalar. In this case where you presumably (?) want to allow the last
two arguments to be broadcast against each other arbitrarily:
arr2, arr3 = np.broadcast_arrays(arr2, scalar)
myufunc(arr1, arr2, arr3)
A little wordier than implicit broadcasting, but not as bad as manually
creating an array, and like implicit broadcasting the memory overhead is
O(1) instead of O(size).
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the NumPy-Discussion