-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
Deferred execution NEP #8889
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deferred execution NEP #8889
Conversation
This is indeed one of the goals of adding |
I'd love to see someone develop a library like this, building up an abstract graph to represent NumPy arrays, but I don't think it needs to live in NumPy. This also bears some similarity to Dask and Blaze. CC @mrocklin |
I'll give my case for having it part of numpy:
Also I don't think arguing over a NEP is a downside. Instead I see it as a strength. |
note that there already is a nep for this: |
Even if all of those points are true, it doesn't follow that this functionality should live in NumPy from the start. It may be a good approach to work out a NEP, then implement it as a separate project, add enough tests to NumPy for the NumPy interfaces that enable the functionality in the separate project, and only after everything has proven itself for a while consider moving things into NumPy. This is complex enough that an implementation won't be first time right (see |
Agreed that, if at all possible, best is to develop something separate first and then try to include. But a NEP is definitely good to start thinking about this! So, one general comment on it: I think we need to be very careful to define what we mean by "deferred execution" and in particular what its purpose is. All cases I can think can (I think) be summarized with the following example:
this would normally be executed as
it would be lovely (in increasing steps of complexity) if it was realised that:
My own goal for 2 aims simply to allow one to define a chained ufunc (for which Well, now that I've written this, I'm not so sure any more whether my stuff is relevant to your goal (item 3)... I probably should write my own NEP. But better first get |
@mhvk its not so much chaining ufuncs as operating on cache sized blocks to reduce memory bandwidth. For large arrays, many operations are memory IO bound and the CPU spends most of its time waiting to read or write data to main memory. A much more efficient way to execute them would be to process a cache sized chunk through multiple operations. A crudely optimized example is below, note that many other optimizations could be done and it would be significantly faster in C than python:
@rgommers I agree that might be a good path. We definitely don't want to release/enable it before its mature enough. At this point I am much more concerned about whether this functionality should ever be included in numpy and whether the proposed API is any good. The development strategy can be hammered out once the first two are cleared. Also I am somewhat hopeful that experience from the previous NEP and projects such as numexpr, theano, dask, numba, and blaze will improve our chances at getting it right sooner. |
I would be interested in this for NumPy if:
More concretely, I think the interface should be closer to: # array_like can be any object with a shape and dtype
deferred = DeferredExecutionArray(array_like)
...
result = some_engine.run(sum_square) where |
@mattharrigan - yes, the speed-up you mention is the goal of my step (2): let |
@shoyer For 1, agreed. I also like the API change, the array shouldn't be responsible for building up the operation graph and executing it. For 2, my initial thought was that the DeferredExecutionArray would not have public methods exposing the operation graph. It would be used as a proxy through the code and then used by the NumPy engine. The API for a typical user writing a script would be consistent/unified across execution libraries, but each execution library would write its own class for building the operation graph exactly how they want it. IIUC you are proposing that the new array would have public methods for exposing the operation graph and would be used directly by library writers for execution. I definitely see value in that approach. My concern is that the API would be much larger and more complex. Also I'm not entirely sure multiple execution engines would like the same thing. A very quick scan of dask and numexpr indicate that there are many differences in how they build graphs. However perhaps we could collect a superset of data so that either of those forms would be producible from our graph. |
I think you have this backwards :-). It's always tricky to give good feedback on this kind of thing, because we don't want to discourage people and do want the leave the door open to new ideas, but... I would say there's basically zero chance of something like this being included in numpy proper unless it's (a) demonstrated some compelling success as a standalone library first, and (b) there's some reason why putting it in numpy will have compelling advantages over it living on as a standalone library. This isn't because we want to be mean; it's exactly the opposite :-). Putting your code into numpy is really a bad idea if it can be at all avoided, both for you and for your code. You have to integrate with a complicated and rickety code base, you end up having to maintain unreasonable levels of backwards compatibility that hobble your ability to make improvements, and if your code is ever replaced by something better than you're still stuck maintaining it forever – or someone will be. (Numpy has many examples of code that's stuck in this kind of grim afterlife, starting with Really the question should be "is there any way we can avoid putting this into numpy?" And this is a major motivation behind I'd encourage you to start with a prototype. That'll teach you more about the API quality than any amount of review here. And if you run into limitations where you need changes to numpy's core, then we'd be very interested to hear about them. |
Yes, exactly.
This is certainly true: every execution engine is going to want to build their own representation of the data. There are lots of ways to represent graphs, but fundamentally everything computation graph is a tree, and converting back and forth is usually relatively straightforward. For The advantage of |
@njsmith Thank you very much for your candor. I think that is good advice and I don't find anything you said mean at all. Candidly I probably lack both the skill and time required to create a large complex library on my own. |
What should be done with the PR? My guess is to close it. @mhvk You were indeed going after some of the same goals as this PR, sorry for my confusion. I think your approach is far simpler and more achievable. I would be interested in seeing exactly what you want to do and helping if you would like. Thanks all |
@mattharrigan - OK, I'll keep you in the loop! But first order will be to get As for what to do with this PR: my own feeling would be to add a note to the existing NEP about using |
We don't have an explicit one. I'd say let's do this similar to PEPs: if @mattharrigan feels it makes sense to merge the two NEPs then he can just edit the existing one (Mark won't be coming back to it I think), and otherwise two competing NEPs is not a problem. |
Yeah, that's always a challenge – but if it helps (...it probably doesn't help 😄) then this is a problem you'd have to solve either way. It's entirely possible you might be able to convince some of the people in this thread to help you with a third-party library, or vice-versa if you don't have the time to write the code and you can't find volunteers to help, then targeting numpy won't make helpers magically appear. (If only...) |
This PR is for a NEP with a possible mechanism/API for deferred execution of various numpy operations to allow for various optimizations. I thought I would post here for initial feedback before considering starting a discussion topic. I think this might be a nice use case for the new
__array_ufunc__
. In fact recent discussions in PR #8247 sparked this concept, particularly some comments by @mhvk