summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Eendebak <pieter.eendebak@gmail.com>2022-05-11 10:02:54 +0200
committerGitHub <noreply@github.com>2022-05-11 10:02:54 +0200
commit79875572916a5c8805cb7bdd00a5b26df72b0733 (patch)
tree75a20e87afb51c35e5a0f26f98590879829d9098
parentc360f1ebb09cca42c32f715aa2b730ef9874fde4 (diff)
downloadnumpy-79875572916a5c8805cb7bdd00a5b26df72b0733.tar.gz
PERF: Skip probing `__array_ufunc__` for NumPy builtin scalars (#21470)
The method `PyUFuncOverride_GetNonDefaultArrayUfunc` is expensive on numpy scalars because these objects do not have a `__array_ufunc__` set and for a missing attribute lookup cpython generates an exception that is later cleared by numpy. This is a performance bottleneck, see #21455. An issue has been submitted to cpython (https://github.com/python/cpython/issues/92216). But even if this is addressed in cpython, it will take untill python 3.12+ before this will be useable by numpy. As an alternative solution, this PR adds a fast path to `PyUFuncOverride_GetNonDefaultArrayUfunc` to determine whether an object is a numpy scalar.
-rw-r--r--numpy/core/src/common/get_attr_string.h2
-rw-r--r--numpy/core/src/common/ufunc_override.c6
2 files changed, 7 insertions, 1 deletions
diff --git a/numpy/core/src/common/get_attr_string.h b/numpy/core/src/common/get_attr_string.h
index a3e5d5ec8..90eca5ee6 100644
--- a/numpy/core/src/common/get_attr_string.h
+++ b/numpy/core/src/common/get_attr_string.h
@@ -42,7 +42,7 @@ _is_basic_python_type(PyTypeObject *tp)
* on the type object, rather than on the instance itself.
*
* Assumes that the special method is a numpy-specific one, so does not look
- * at builtin types, nor does it look at a base ndarray.
+ * at builtin types. It does check base ndarray and numpy scalar types.
*
* In future, could be made more like _Py_LookupSpecial
*/
diff --git a/numpy/core/src/common/ufunc_override.c b/numpy/core/src/common/ufunc_override.c
index 2c3dc5cb3..4fb4d4b3e 100644
--- a/numpy/core/src/common/ufunc_override.c
+++ b/numpy/core/src/common/ufunc_override.c
@@ -5,6 +5,7 @@
#include "get_attr_string.h"
#include "npy_import.h"
#include "ufunc_override.h"
+#include "scalartypes.h"
/*
* Check whether an object has __array_ufunc__ defined on its class and it
@@ -30,6 +31,11 @@ PyUFuncOverride_GetNonDefaultArrayUfunc(PyObject *obj)
if (PyArray_CheckExact(obj)) {
return NULL;
}
+ /* Fast return for numpy scalar types */
+ if (is_anyscalar_exact(obj)) {
+ return NULL;
+ }
+
/*
* Does the class define __array_ufunc__? (Note that LookupSpecial has fast
* return for basic python types, so no need to worry about those here)