From 60a858a372b14b73547baacf4a472eccfade1073 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Tue, 7 Dec 2021 20:17:17 -0600 Subject: ENH: Improve array function overhead by using vectorcall This moves dispatching for `__array_function__` into a C-wrapper. This helps speed for multiple reasons: * Avoids one additional dispatching function call to C * Avoids the use of `*args, **kwargs` which is slower. * For simple NumPy calls we can stay in the faster "vectorcall" world This speeds up things generally a little, but can speed things up a lot when keyword arguments are used on lightweight functions, for example:: np.can_cast(arr, dtype, casting="same_kind") is more than twice as fast with this. There is one alternative in principle to get best speed: We could inline the "relevant argument"/dispatcher extraction. That changes behavior in an acceptable but larger way (passes default arguments). Unless the C-entry point seems unwanted, this should be a decent step in the right direction even if we want to do that eventually, though. Closes gh-20790 Closes gh-18547 (although not quite sure why) --- numpy/core/numeric.py | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) (limited to 'numpy/core/numeric.py') diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index 577f8e7cd..91e35c684 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -130,10 +130,6 @@ def zeros_like(a, dtype=None, order='K', subok=True, shape=None): return res -def _ones_dispatcher(shape, dtype=None, order=None, *, like=None): - return(like,) - - @set_array_function_like_doc @set_module('numpy') def ones(shape, dtype=None, order='C', *, like=None): @@ -187,16 +183,13 @@ def ones(shape, dtype=None, order='C', *, like=None): """ if like is not None: - return _ones_with_like(shape, dtype=dtype, order=order, like=like) + return _ones_with_like(like, shape, dtype=dtype, order=order) a = empty(shape, dtype, order) multiarray.copyto(a, 1, casting='unsafe') return a - -_ones_with_like = array_function_dispatch( - _ones_dispatcher -)(ones) +_ones_with_like = array_function_dispatch()(ones) def _ones_like_dispatcher(a, dtype=None, order=None, subok=None, shape=None): @@ -323,7 +316,7 @@ def full(shape, fill_value, dtype=None, order='C', *, like=None): """ if like is not None: - return _full_with_like(shape, fill_value, dtype=dtype, order=order, like=like) + return _full_with_like(like, shape, fill_value, dtype=dtype, order=order) if dtype is None: fill_value = asarray(fill_value) @@ -333,9 +326,7 @@ def full(shape, fill_value, dtype=None, order='C', *, like=None): return a -_full_with_like = array_function_dispatch( - _full_dispatcher -)(full) +_full_with_like = array_function_dispatch()(full) def _full_like_dispatcher(a, fill_value, dtype=None, order=None, subok=None, shape=None): @@ -1778,10 +1769,6 @@ def indices(dimensions, dtype=int, sparse=False): return res -def _fromfunction_dispatcher(function, shape, *, dtype=None, like=None, **kwargs): - return (like,) - - @set_array_function_like_doc @set_module('numpy') def fromfunction(function, shape, *, dtype=float, like=None, **kwargs): @@ -1847,15 +1834,13 @@ def fromfunction(function, shape, *, dtype=float, like=None, **kwargs): """ if like is not None: - return _fromfunction_with_like(function, shape, dtype=dtype, like=like, **kwargs) + return _fromfunction_with_like(like, function, shape, dtype=dtype, **kwargs) args = indices(shape, dtype=dtype) return function(*args, **kwargs) -_fromfunction_with_like = array_function_dispatch( - _fromfunction_dispatcher -)(fromfunction) +_fromfunction_with_like = array_function_dispatch()(fromfunction) def _frombuffer(buf, dtype, shape, order): @@ -2130,10 +2115,6 @@ def _maketup(descr, val): return tuple(res) -def _identity_dispatcher(n, dtype=None, *, like=None): - return (like,) - - @set_array_function_like_doc @set_module('numpy') def identity(n, dtype=None, *, like=None): @@ -2168,15 +2149,13 @@ def identity(n, dtype=None, *, like=None): """ if like is not None: - return _identity_with_like(n, dtype=dtype, like=like) + return _identity_with_like(like, n, dtype=dtype) from numpy import eye return eye(n, dtype=dtype, like=like) -_identity_with_like = array_function_dispatch( - _identity_dispatcher -)(identity) +_identity_with_like = array_function_dispatch()(identity) def _allclose_dispatcher(a, b, rtol=None, atol=None, equal_nan=None): -- cgit v1.2.1