[Numpy-discussion] next NumPy Optimization Team meeting - July 15th, 2024 at 5 pm UTC
The next NumPy Optimization Team meeting will be held this Monday, July 15th at 5 pm UTC. Join us via Zoom: https://numfocus-org.zoom.us/j/81261288210?pwd=iwV99tGSjR61RTGEERKM4QKxe46g1n.1 . Everyone is welcome and encouraged to attend. To add to the meeting agenda the topics you’d like to discuss, follow the link: https://hackmd.io/dVdSlQ0TThWkOk0OkmGsmw?both. For the notes from the previous meetings, visit: https://github.com/numpy/archive/tree/main/optim_team_meetings. -- Cheers, Inessa Inessa Pawson GitHub: inessapawson ___ NumPy-Discussion mailing list -- numpy-discussion@python.org To unsubscribe send an email to numpy-discussion-le...@python.org https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ Member address: arch...@mail-archive.com
[Numpy-discussion] Re: Enhancement for generalized ufuncs
On Thu, 2024-07-11 at 19:31 -0400, Warren Weckesser wrote: > I have implemented quite a few generalized ufuncs over in ufunclab > (https://github.com/WarrenWeckesser/ufunclab), and in the process I > have accumulated a gufunc "wish list". Two items on that list are: > > (1) the ability to impose constraints on the core dimensions that are > checked when the gufunc is called. By far the most common use-case I > have is requiring that a dimension have length at least 1. To do this > currently, I check the shapes in the ufunc loop function, and if they > are not valid, raise an exception and hope that the gufunc machinery > processes it as expected when the loop function returns. (Sorry, I'm > using lingo--"loop function", "core dimension", etc--that will be > familiar to those who already know the ufunc C API, but not so > familiar to general users of NumPy.) > > (2) the ability to have the output dimension be a function of the > input dimensions, instead of being limited to one of the input > dimensions or an independent dimension. Then one could create, for > example, a 1-d convolution gufunc with shape signature that is > effectively `(m),(n)->(m + n - 1)` (corresponding to `mode='full'` in > `np.convolve`) and the gufunc code would automatically allocate the > output with the correct shape and dtype. > Nice, thanks! I have to look at the implementation in detail, but this seems like a good idea. Have to look at the PR for bike-shedding, but I think we should just add this. (You won't be able to know these relations from reading the signature, but I doubt it's worth worrying about that.) This seems like it should cover all or at least almost all of the things that have come up about ufunc core dimension flexibility (might be nice to check briefly, but even if not I suspect the hook here is the right choice). - Sebastian > I have proposed a change in https://github.com/numpy/numpy/pull/26908 > that makes both these features possible. A field is added to the > PyUFuncObject that is an optional user-defined C function that the > gufunc author implements. When a gufunc is called, this function is > called with an array of the values of the core dimensions of the > input > and output arrays. Some or all of the output core dimensions might be > -1, meaning the arrays are to be allocated by the gufunc/iterator > machinery. The new "hook" allows the user to check the given core > dimensions and raise an exception if some constraint is not > satisfied. > The user-defined function can also replace those -1 values with sizes > that it computes based on the given input core dimensions. > > To define the 1-d convolution gufunc, the actual shape signature that > is passed to `PyUFunc_FromFuncAndDataAndSignature` is `(m),(n)->(p)`. > When a user passes arrays with shapes, say, (20,) and (30,) as the > input and with no output array specified, the user-defined function > will get the array [20, 30, -1]. It would replace -1 with m + n - 1 = > 49 and return. If the caller *does* include an output array in the > call, the core dimension of that array will be the third element of > the array passed to the user-defined function. In that case, the > function verifies that the value equals m + n - 1, and raises an > exception if it doesn't. > > Here's that 1-d convolution, called `conv1d_full` here, in action: > > ``` > In [14]: import numpy as np > > In [15]: from experiment import conv1d_full > > In [16]: type(conv1d_full) > Out[16]: numpy.ufunc > ``` > > `m = 4`, `n = 6`, so the output shape is `p = m + n - 1 = 9`: > > ``` > In [17]: conv1d_full([1, 2, 3, 4], [-1, 1, 2, 1.5, -2, 1]) > Out[17]: array([-1. , -1. , 1. , 4.5, 11. , 9.5, 2. , -5. , 4. ]) > ``` > > Standard broadcasting: > > ``` > In [18]: conv1d_full([[1, 2, 3, 4], [0.5, 0, -1, 1]], [-1, 1, 2, 1.5, > -2, 1]) > Out[18]: > array([[-1. , -1. , 1. , 4.5 , 11. , 9.5 , 2. , -5. , 4. ], > [-0.5 , 0.5 , 2. , -1.25, -2. , 1. , 3.5 , -3. , 1. ]]) > ``` > > Comments here or over in the pull request are welcome. The essential > changes to the source code are just 7 lines in `ufunc_object.c` and 7 > lines in `ufuncobject.h`. The rest of the changes in the PR create a > couple gufuncs that use the new feature, with corresponding unit > tests. > > Warren > ___ > NumPy-Discussion mailing list -- numpy-discussion@python.org > To unsubscribe send an email to numpy-discussion-le...@python.org > https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ > Member address: sebast...@sipsolutions.net > ___ NumPy-Discussion mailing list -- numpy-discussion@python.org To unsubscribe send an email to numpy-discussion-le...@python.org https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ Member address: arch...@mail-archive.com
[Numpy-discussion] Re: Enhancement for generalized ufuncs
On Fri, Jul 12, 2024 at 7:47 AM Sebastian Berg wrote: > > (You won't be able to know these relations from reading the signature, > but I doubt it's worth worrying about that.) After creating the gufunc with `PyUFunc_FromFuncAndDataAndSignature`, the gufunc author could set the `core_signature` field at the same time that `process_core_dims_func` is set. That requires freeing the old signature and allocating memory for the new one. For the 1-d convolution example, the signature would be set to `"(m),(n)->(m + n - 1)"`: ``` In [1]: from experiment import conv1d_full In [2]: conv1d_full.signature Out[2]: '(m),(n)->(m + n - 1)' ``` Warren ___ NumPy-Discussion mailing list -- numpy-discussion@python.org To unsubscribe send an email to numpy-discussion-le...@python.org https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ Member address: arch...@mail-archive.com
[Numpy-discussion] Re: Windows 11 arm64 wheel
We will start looking at the bug and the CI job. Thanks, Slobodan ___ NumPy-Discussion mailing list -- numpy-discussion@python.org To unsubscribe send an email to numpy-discussion-le...@python.org https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ Member address: arch...@mail-archive.com
[Numpy-discussion] Re: Enhancement for generalized ufuncs
On Fri, 2024-07-12 at 09:56 -0400, Warren Weckesser wrote: > On Fri, Jul 12, 2024 at 7:47 AM Sebastian Berg > wrote: > > > > > (You won't be able to know these relations from reading the > > signature, > > but I doubt it's worth worrying about that.) > > After creating the gufunc with `PyUFunc_FromFuncAndDataAndSignature`, > the gufunc author could set the `core_signature` field at the same > time that `process_core_dims_func` is set. That requires freeing the > old signature and allocating memory for the new one. For the 1-d > convolution example, the signature would be set to `"(m),(n)->(m + n > - > 1)"`: > > ``` > In [1]: from experiment import conv1d_full > > In [2]: conv1d_full.signature > Out[2]: '(m),(n)->(m + n - 1)' > ``` I have to look at the PR, but the ufunc parses the signature only once? That solution seems very hacky, but allowing to just replace the signature may make sense. (Downside is, if someone else wants to parse the original signature, but I guess it is unlikely.) In either case, the only other thing to hook into would be the signature parsing itself with the full shapes available. But then you may need to deal with `axes=`, etc. as well, so I think your solution that only adjusts shapes seems better. It's much simpler and should cover most or even all relevant things. - Sebastian > > Warren > ___ > NumPy-Discussion mailing list -- numpy-discussion@python.org > To unsubscribe send an email to numpy-discussion-le...@python.org > https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ > Member address: sebast...@sipsolutions.net ___ NumPy-Discussion mailing list -- numpy-discussion@python.org To unsubscribe send an email to numpy-discussion-le...@python.org https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ Member address: arch...@mail-archive.com
[Numpy-discussion] Re: Enhancement for generalized ufuncs
On Fri, Jul 12, 2024 at 2:35 PM Sebastian Berg wrote: > > On Fri, 2024-07-12 at 09:56 -0400, Warren Weckesser wrote: > > On Fri, Jul 12, 2024 at 7:47 AM Sebastian Berg > > wrote: > > > > > > > > (You won't be able to know these relations from reading the > > > signature, > > > but I doubt it's worth worrying about that.) > > > > After creating the gufunc with `PyUFunc_FromFuncAndDataAndSignature`, > > the gufunc author could set the `core_signature` field at the same > > time that `process_core_dims_func` is set. That requires freeing the > > old signature and allocating memory for the new one. For the 1-d > > convolution example, the signature would be set to `"(m),(n)->(m + n > > - > > 1)"`: > > > > ``` > > In [1]: from experiment import conv1d_full > > > > In [2]: conv1d_full.signature > > Out[2]: '(m),(n)->(m + n - 1)' > > ``` > > > I have to look at the PR, but the ufunc parses the signature only once? Yes. The ufunc doesn't need to save the signature string once it has parsed it. As the comment about it in `ufuncobject.h` says, the `core_signature` field (type `char *`) is "for printing purposes". Updating the `core_signature` is optional. I hadn't thought about it until you mentioned it above, but it doesn't seem like a bad idea. I added this to the `experiment` module at https://github.com/WarrenWeckesser/experiments/blob/main/python/numpy/gufunc-process_core_dims_func/experiment.c, where I now have a helper function `reset_core_signature(PyUFuncObject *gufunc, char *new_signature)` to update the field. This is not part of the pull request. I'm not sure if that is something we would suggest as the recommended practice for this feature. > That solution seems very hacky, but allowing to just replace the > signature may make sense. > (Downside is, if someone else wants to parse the original signature, > but I guess it is unlikely.) > > In either case, the only other thing to hook into would be the > signature parsing itself with the full shapes available. But then you > may need to deal with `axes=`, etc. as well, so I think your solution > that only adjusts shapes seems better. > It's much simpler and should cover most or even all relevant things. Yes, for the use-cases that I can think of, all that matters are the values of the core dimensions of the input and output arrays when the gufunc is called. Warren > > - Sebastian > > > > > > > Warren > > ___ > > NumPy-Discussion mailing list -- numpy-discussion@python.org > > To unsubscribe send an email to numpy-discussion-le...@python.org > > https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ > > Member address: sebast...@sipsolutions.net > > > ___ > NumPy-Discussion mailing list -- numpy-discussion@python.org > To unsubscribe send an email to numpy-discussion-le...@python.org > https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ > Member address: warren.weckes...@gmail.com ___ NumPy-Discussion mailing list -- numpy-discussion@python.org To unsubscribe send an email to numpy-discussion-le...@python.org https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ Member address: arch...@mail-archive.com