Skip to content

Allow mixing dask and numpy arrays in @guvectorize#6863

Merged
jsignell merged 11 commits intodask:mainfrom
jsignell:meta-nonempty
Jun 29, 2021
Merged

Allow mixing dask and numpy arrays in @guvectorize#6863
jsignell merged 11 commits intodask:mainfrom
jsignell:meta-nonempty

Conversation

@jsignell
Copy link
Member

I am not sure that this is the right time for adding a meta_nonempty for dask.array but I thought it might be? Also I suspect that this'll have repercussions for cupy @quasiben.

@martindurant
Copy link
Member

ping @quasiben or maybe suggest someone else to review

"""
if not is_arraylike(x):
return x
return np.ones((1,) * x.ndim, dtype=x.dtype)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this should use [np.ones_like[(https://numpy.org/doc/stable/reference/generated/numpy.ones_like.html) instead. cc @pentschev

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is indeed necessary, we would probably want

dask/dask/array/utils.py

Lines 340 to 349 in 8f9fc16

def ones_like_safe(a, shape, **kwargs):
"""
Return np.ones_like(a, shape=shape, **kwargs) if the shape argument
is supported (requires NumPy >= 1.17), otherwise falls back to
using the old behavior, returning np.ones(shape, **kwargs).
"""
try:
return np.ones_like(a, shape=shape, **kwargs)
except TypeError:
return np.ones(shape, **kwargs)
here, but I'm wondering why can't we just use meta_from_array instead.

np.ones((1,) * x.ndim, dtype=x.dtype) if isinstance(x, Array) else x
for x in args
]
args = [meta_nonempty(x) for x in args]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't using meta_from_array suffice here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is it needs to be a nonempty array for gufuncs to work. If I switch this to meta_from_array I get:

           ValueError: `dtype` inference failed in `apply_gufunc`.
           
           Please specify the dtype explicitly using the `output_dtypes` kwarg.
           
           Original error is below:
           ------------------------
           ValueError('cannot call `vectorize` on size 0 inputs unless `otypes` is set')
           
           Traceback:
           ---------
             File "/home/julia/dask/dask/array/core.py", line 377, in apply_infer_dtype
               o = func(*args, **kwargs)
             File "/home/julia/conda/envs/dask-dev/lib/python3.8/site-packages/numpy/lib/function_base.py", line 2091, in __call__
               return self._vectorize_call(func=func, args=vargs)
             File "/home/julia/conda/envs/dask-dev/lib/python3.8/site-packages/numpy/lib/function_base.py", line 2157, in _vectorize_call
               res = self._vectorize_call_with_signature(func, args)
             File "/home/julia/conda/envs/dask-dev/lib/python3.8/site-packages/numpy/lib/function_base.py", line 2226, in _vectorize_call_with_signature
               raise ValueError('cannot call `vectorize` on size 0 inputs '

Copy link
Member

@pentschev pentschev Feb 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, couldn't you just replace np.ones by ones_like_safe in the old code? That way you wouldn't even need the new meta_from_array function, unless I'm missing something.

"""
if not is_arraylike(x):
return x
return np.ones((1,) * x.ndim, dtype=x.dtype)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is indeed necessary, we would probably want

dask/dask/array/utils.py

Lines 340 to 349 in 8f9fc16

def ones_like_safe(a, shape, **kwargs):
"""
Return np.ones_like(a, shape=shape, **kwargs) if the shape argument
is supported (requires NumPy >= 1.17), otherwise falls back to
using the old behavior, returning np.ones(shape, **kwargs).
"""
try:
return np.ones_like(a, shape=shape, **kwargs)
except TypeError:
return np.ones(shape, **kwargs)
here, but I'm wondering why can't we just use meta_from_array instead.

@jsignell
Copy link
Member Author

jsignell commented Feb 5, 2021

Thanks for the feedback @pentschev. I think I had made it overly complicated for no reason.

Copy link
Member

@pentschev pentschev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jsignell , this reads much better, and looks good to me now! 😄

Base automatically changed from master to main March 8, 2021 20:19
@jsignell
Copy link
Member Author

I am going to merge this if it passes.

@github-actions github-actions bot added the array label May 26, 2021
@jsignell jsignell changed the title Make new meta_nonempty function and use it for gufunc Allow mixing dask and numpy arrays in @guvectorize Jun 18, 2021

try:
return np.ones_like(a, shape=shape, **kwargs)
return _array_like_safe(np.ones_like, ones_like, a, shape=shape, **kwargs)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a neccessary improvement on this function, but @pentschev please correct me if this is wrong.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this isn't necessary. ones_like already existed before we added like= to creation functions like np.asarray, in fact, the like= argument name comes from the *_like functions. We have added like= to all creation functions, including np.ones, but using np.ones_like is equivalent to np.ones(..., like=...). Therefore, ones_like_safe already works without the change proposed here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok thank you. I will think more about what I am doing wrong then. I was getting a segfault without this change which made me think that maybe I was hitting a wierd loop or somthing. I

@jsignell
Copy link
Member Author

Ok I made ones_like_safe operate on the _meta if available so that the result is always an evaluated array

@jsignell
Copy link
Member Author

@jrbourbeau I plan to merge this tomorrow unless you have any comments.

Copy link
Member

@pentschev pentschev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @jsignell for the late reply, overall changes look good, I suggested only using meta_from_array to get the correct _meta, hopefully that's a simpler way and will work as well.

jsignell and others added 3 commits June 28, 2021 14:15
Copy link
Member

@pentschev pentschev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks @jsignell !

@jsignell jsignell merged commit 626cc72 into dask:main Jun 29, 2021
@jsignell
Copy link
Member Author

Thanks for all the reviews! 😅

@jsignell jsignell deleted the meta-nonempty branch June 29, 2021 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mixing of dask.array and numpy.ndarray in Numba @guvectorize

4 participants