diff options
| author | Pieter Eendebak <pieter.eendebak@gmail.com> | 2022-05-11 10:02:54 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-05-11 10:02:54 +0200 |
| commit | 79875572916a5c8805cb7bdd00a5b26df72b0733 (patch) | |
| tree | 75a20e87afb51c35e5a0f26f98590879829d9098 | |
| parent | c360f1ebb09cca42c32f715aa2b730ef9874fde4 (diff) | |
| download | numpy-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.h | 2 | ||||
| -rw-r--r-- | numpy/core/src/common/ufunc_override.c | 6 |
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) |
