-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Swapping getitem and elementwise operations via graph opimization, redux? #2431
Comments
We're certainly in a better place now that we can swap in and out optimizations. We can build optimizations that are not always-on. |
I understand the first case of |
My first inclination on swapping elementwise operations is to do this in two steps:
Although I should look more closely at @jcrist 's past work to see what troubles arose. |
Case two would be the optimization Case three is related, basically |
Given a ufunc and a subsequent getitem call my hope would be that rules to apply the index to the arguments would be straightforward. For example given the following: x = np.ones((10, 1))
y = np.ones((1, 10))
z = (x + y)[a, b] We know that we can rewrite this as z = (x[a] + y[b]) Correct? I imagine that we can probably do the slicing prior to broadcasting if we are clever about it. |
My understand of why @jcrist's past work broke down is that there wasn't a good way to do this optimization when the shapes of the arguments differed, and doing broadcasting in every case added too much overhead (~10% to every dask array operation, whether it needed this optimization or not). Hence my later two suggestions, to make this optional. |
Yes, absolutely. But I'm not sure this is actually worth the trouble, as I haven't seen this specific sort of access pattern come up for geo-data. Often indexing can't be factorized over elementwise arguments -- either there's only one non-array or all arrays have the same shape. The "broadcast first" solution could solve this nearly as well, with only some constant run-time overhead: x2, y2 = broadcast_arrays(x, y)
z = (x2[a, b] + y2[a, b]) ...though it would certainly help to defer automatic rechunking until after the optimization pass (which of course isn't really possible with the current dask.array design). |
Yeah, sorry, to be clear the arrays I'm thinking about here are numpy arrays. I assume that this optimization would kick in only after generic task fusion and slicing-fusion had occurred so that we had large complex tasks that we then wanted to reorder. Rechunking after expression-creation would require taking on something like Blaze (or other). Lets leave that as off-topic for now. |
What costs does |
It's all done with metadata, effectively just inserting new dimensions with a stride of |
@jcrist did some work back in #755 on swapping getitem and elementwise operations. We didn't end up merging this work, because we were unable to come up with a solution that worked across the board without slowing down every dask array operations (by forcing broadcasting).
However, this is still a vital optimization for climate/weather data analysis use cases (where arrays are often currently loaded with one chunk/file, as described in pydata/xarray#1440), and would be extremely valuable for xarray (allowing us to remove our legacy system for deferred array computation). It would be great to pursue it in some more limited form.
Any of the following would solve xarray's use cases:
x + 1
.da.swappable_elementwise()
.The optimization pass itself could also be optional, but we would always want to use it on dask.array objects wrapped with xarray.
The text was updated successfully, but these errors were encountered: