Conversation
numpy/core/src/umath/ufunc_object.c
Outdated
There was a problem hiding this comment.
// is C++ comment, should be /* ... */
There was a problem hiding this comment.
Thanks. Suggestions for a better name?
|
As for performance, it's hard to get consistent results, but this adds about 5μs to 10μs, or 4% to 5% decrease in speed (tested with %timeit and multiply and add.) |
numpy/core/src/umath/ufunc_object.c
Outdated
There was a problem hiding this comment.
This needs to be inside an else { } branch.
|
Note that we want similar logic also for In the ufunc code, you might want to run the override check/parsing code only if get_ufunc_arguments sees an object with an The question whether the dict should be keyed by ufunc objects rather than ufunc names should also be addressed. I think one cannot assume ufunc names are unique. |
|
Considering this, should I change the name to something other than Also, do tests for this go in |
|
It think |
|
I'd perhaps not expose that function in the public API, as it's not really something a user of Numpy C-API wants to see. It would be better put in a |
|
I'm having a problem with checking for the numpy.dot key in |
|
@cowlicks: You can either grab the Python function object via PyImport_ImportModule + PyObject_GetAttrString and store the result in a static variable inside the functions that need it (i.e., |
|
This is really cool. I think the API's still not 100% there, though. Some thoughts:
Python's standard approach to multimethods seems like a good fit here -- I'm thinking of things like Of course, ufuncs can have arbitrarily many arguments, so we don't want to mess about with "rufunc" or whatever. Here's my suggestion:
For example, in our example above, if If this returns
Note 1: This scheme doesn't allow dispatch on Note 2: If a class defines Note 3: I think this system is strictly more powerful than the existing (This leaves out |
|
Oh right, I was going to also say: Note 4: For a generic implementation (like the one np.ma might want), where you might need to know whether the current operation was e.g. a An alternative would be to have a different override method for each ufunc method. |
|
Regarding |
|
@njsmith: Doesn't the weird way Regarding the points:
|
|
I thought 'dot' used the same rule as gufuncs -- iterate over the first n Do you have any use case for dispatching on the output argument? It seems On Wed, Jul 17, 2013 at 3:43 PM, Pauli Virtanen notifications@github.comwrote:
|
|
@njsmith: For gufunc, this would be I don't really have an use case for broadcasting on output, apart from probably misremembering how |
|
I agree that standardizing the input argument format is good. But why standardize on dict? I think this could slow thing down. Why not use a tuple like (inputs..., outputs...)? Or 2 tuples, one for inputs and one for outputs? I don't know about the other arguments you talked about. |
|
Ufuncs can take tons of kwargs, can't avoid that. For call the current On Wed, Jul 17, 2013 at 4:21 PM, Frédéric Bastien
|
|
Okay, I'm rewriting the NEP to describe the implementation y'all are suggesting. I think |
|
@pv @njsmith It looks like ufunc methods (reduce, etc.) except for outer, take a different code path than the standard ufunc_generic_call. So I think this API can be told what the ufunc method being used is. Since I don't think there is a way to tell just being given the ufunc, args, and kwargs. ...Except handling outer might be a little different. So the new function to check for an override can be like: |
|
Multi-methods are definitely the way to go here and should replace the I recently wrote a blog-post where I linked to several common multi-method implementations that are worth looking at before going down this route of adding yet another special method to the objects. Here is the blog-post: http://technicaldiscovery.blogspot.com/2013/07/thoughts-after-scipy-2013-and-specific.html I think looking into doing an actual multi-method implementation would be extremely beneficial for NumPy and would strongly encourage that whatever is done is at least done with awareness of the mulit-method literature such as this paper: http://dl.acm.org/citation.cfm?id=203096&dl=ACM&coll= Traditional multi-methods are basically a simple look-up table (i.e. dictionary) whose keys are the types of the arguments (here actual Python types would work well). Obviously, if there is an exact match, you know what to do --- call the function and propagate errors. If the function called returns One nice thing about the suggested It is really great to see activity and progress towards building better multi-methods in NumPy. |
|
@teoliphant: I think the (1) They preserve Python's overall dispatch model. The classic multimethod literature all assumes that you're using a strongly-typed language with type-based dispatch. Python doesn't do that at all -- Python uses "duck typing", in which dispatch always goes directly through attributes of the object, without caring about the actual value of (2) They preserve locality: if I see an expression (3) They play better with having a fallback "other type" handler: For a numpy ufunc, there are lots of objects that we don't want to handle via any kind of multimethod dispatch, but instead want to fall back on using (4) They're familiar: While I love playing with cool designs for sexy programming language technology, I don't really think numpy should be in the business of trying to define a new dispatch system from scratch. But that's what we're doing as soon as we reach the hand-wavy bit of your design where we have to start walking multiple MRO hierarchies in parallel. (What happens when you have |
There was a problem hiding this comment.
BTW, this should be using the new PyArray_GetAttrString_SuppressException, which includes the fast-paths for skipping checking basic types that we know don't have special attributes. (Though perhaps it should have a few more special cases added, like for PyArray_CheckExact, PyInt_CheckExact, etc.)
There was a problem hiding this comment.
This function actually being removed, it implemented my previous dict look-up approach. But, I do check for PyArray_CheckExact, line 74, is that what you mean?
There was a problem hiding this comment.
I mean that in whatever code you end up writing, instead of writing code to
do the attribute lookup in some cases and not others, you should use our
existing function for doing fast attribute lookup. (And maybe make it
faster.)
On 18 Jul 2013 17:20, "Blake Griffith" notifications@github.com wrote:
In numpy/core/src/private/ufunc_override.h:
+NPY_NO_EXPORT PyObject *
+PyUFunc_GetOverride(PyObject *ufunc, PyObject *args, PyObject *kwds)
+{
- int i;
- int nargs = PyTuple_GET_SIZE(args);
- int noa = 0;
- PyObject *obj;
- PyObject *with_override[NPY_MAXARGS], *overrides[NPY_MAXARGS];
- PyObject *override = NULL, *override_dict = NULL;
- for (i = 0; i < nargs; i++) {
obj = PyTuple_GET_ITEM(args, i);if (PyArray_CheckExact(obj) || PyArray_IsAnyScalar(obj)) {continue;}override_dict = PyObject_GetAttrString(obj, "**ufunc_override**");This function actually being removed, it implemented my previous dict
look-up approach. But, I do check for PyArray_CheckExact, line 74, is
that what you mean?—
Reply to this email directly or view it on GitHubhttps://github.com//pull/3524/files#r5270580
.
|
@njsmith A complication, what it an object defines I think it should probably return |
|
@teoliphant I think @njsmith's arguments are persuasive. However I'd like to hear what you think. |
|
@cowlicks: if you want default ufunc behavior, you can cast your data to an ndarray and call the ufunc again. If you are a subclass and |
|
@cowlicks: yeah, I had that kind of fallback behaviour in my initial sketch but then took it out before posting, because of what @pv says. With |
There was a problem hiding this comment.
Again, the keeping of state worries me.
|
I'm concerned about the use of static variables in some of the functions. They are like globals and best avoided if possible. |
|
Ping travisbot. Looks like pip is failing. |
|
@cowlicks universal failure of build on account of pip. |
numpy/core/blasdot/_dotblas.c
Outdated
|
Looks good modulo a few nitpicks. |
sudo apt-get install -qq libatlas-dev libatlas-base-dev
|
Merged, thanks. |
This PR adds a mechanism to override ufuncs.
It undoubtedly needs a lot of review. I have written an explanation of the implementation and given a demo in a NEP, which is also included in this PR.
This also needs new tests and documentation but I thought reviewing what I have so far would be best.