8000 PERF: Skip probing `__array_ufunc__` for NumPy builtin scalars (#21470) · numpy/numpy@7987557 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7987557

Browse files
authored
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 (python/cpython#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.
1 parent c360f1e commit 7987557

File tree

2 files changed

+7
-1
lines changed

2 files changed

+7
-1
lines changed

numpy/core/src/common/get_attr_string.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ _is_basic_python_type(PyTypeObject *tp)
4242
* on the type object, rather than on the instance itself.
4343
*
4444
* Assumes that the special method is a numpy-specific one, so does not look
45-
* at builtin types, nor does it look at a base ndarray.
45+
* at builtin types. It does check base ndarray and numpy scalar types.
4646
*
4747
* In future, could be made more like _Py_LookupSpecial
4848
*/

numpy/core/src/common/ufunc_override.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "get_attr_string.h"
66
#include "npy_import.h"
77
#include "ufunc_override.h"
8+
#include "scalartypes.h"
89

910
/*
1011
* Check whether an object has __array_ufunc__ defined on its class and it
@@ -30,6 +31,11 @@ PyUFuncOverride_GetNonDefaultArrayUfunc(PyObject *obj)
3031
if (PyArray_CheckExact(obj)) {
3132
return NULL;
3233
}
34+
/* Fast return for numpy scalar types */
35+
if (is_anyscalar_exact(obj)) {
36+
return NULL;
37+
}
38+
3339
/*
3440
* Does the class define __array_ufunc__? (Note that LookupSpecial has fast
3541
* return for basic python types, so no need to worry about those here)

0 commit comments

Comments
 (0)
0