Skip to content

Commit 64ee06a

Browse files
authored
Merge pull request numpy#26607 from ngoldbaum/global-state-refactor
MNT: Reorganize non-constant global statics into structs
2 parents ccff7fb + 3ae66b1 commit 64ee06a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+989
-902
lines changed

numpy/_core/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,7 @@ src_multiarray = multiarray_gen_headers + [
11011101
'src/multiarray/nditer_constr.c',
11021102
'src/multiarray/nditer_pywrap.c',
11031103
src_file.process('src/multiarray/nditer_templ.c.src'),
1104+
'src/multiarray/npy_static_data.c',
11041105
'src/multiarray/number.c',
11051106
'src/multiarray/refcount.c',
11061107
src_file.process('src/multiarray/scalartypes.c.src'),

numpy/_core/src/common/binop_override.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "numpy/arrayobject.h"
77

88
#include "get_attr_string.h"
9+
#include "npy_static_data.h"
910

1011
/*
1112
* Logic for deciding when binops should return NotImplemented versus when
@@ -128,7 +129,7 @@ binop_should_defer(PyObject *self, PyObject *other, int inplace)
128129
* Classes with __array_ufunc__ are living in the future, and only need to
129130
* check whether __array_ufunc__ equals None.
130131
*/
131-
attr = PyArray_LookupSpecial(other, npy_um_str_array_ufunc);
132+
attr = PyArray_LookupSpecial(other, npy_interned_str.array_ufunc);
132133
if (attr != NULL) {
133134
defer = !inplace && (attr == Py_None);
134135
Py_DECREF(attr);

numpy/_core/src/common/npy_cpu_dispatch.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
#include "npy_cpu_dispatch.h"
1+
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
2+
#define _MULTIARRAYMODULE
23

3-
static PyObject *npy__cpu_dispatch_registery = NULL;
4+
#include "npy_cpu_dispatch.h"
5+
#include "numpy/ndarraytypes.h"
6+
#include "npy_static_data.h"
47

58
NPY_VISIBILITY_HIDDEN int
69
npy_cpu_dispatch_tracer_init(PyObject *mod)
710
{
8-
if (npy__cpu_dispatch_registery != NULL) {
11+
if (npy_static_pydata.cpu_dispatch_registry != NULL) {
912
PyErr_Format(PyExc_RuntimeError, "CPU dispatcher tracer already initlized");
1013
return -1;
1114
}
@@ -22,21 +25,21 @@ npy_cpu_dispatch_tracer_init(PyObject *mod)
2225
if (err != 0) {
2326
return -1;
2427
}
25-
npy__cpu_dispatch_registery = reg_dict;
28+
npy_static_pydata.cpu_dispatch_registry = reg_dict;
2629
return 0;
2730
}
2831

2932
NPY_VISIBILITY_HIDDEN void
3033
npy_cpu_dispatch_trace(const char *fname, const char *signature,
3134
const char **dispatch_info)
3235
{
33-
PyObject *func_dict = PyDict_GetItemString(npy__cpu_dispatch_registery, fname);
36+
PyObject *func_dict = PyDict_GetItemString(npy_static_pydata.cpu_dispatch_registry, fname);
3437
if (func_dict == NULL) {
3538
func_dict = PyDict_New();
3639
if (func_dict == NULL) {
3740
return;
3841
}
39-
int err = PyDict_SetItemString(npy__cpu_dispatch_registery, fname, func_dict);
42+
int err = PyDict_SetItemString(npy_static_pydata.cpu_dispatch_registry, fname, func_dict);
4043
Py_DECREF(func_dict);
4144
if (err != 0) {
4245
return;

numpy/_core/src/common/npy_cpu_features.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55

66
/******************** Private Definitions *********************/
77

8+
// This is initialized during module initialization and thereafter immutable.
9+
// We don't include it in the global data struct because the definitions in
10+
// this file are shared by the _simd, _umath_tests, and
11+
// _multiarray_umath modules
12+
813
// Hold all CPU features boolean values
914
static unsigned char npy__cpu_have[NPY_CPU_FEATURE_MAX];
1015

numpy/_core/src/common/npy_ctypes.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <Python.h>
55

66
#include "npy_import.h"
7+
#include "multiarraymodule.h"
78

89
/*
910
* Check if a python type is a ctypes class.
@@ -17,16 +18,17 @@
1718
static inline int
1819
npy_ctypes_check(PyTypeObject *obj)
1920
{
20-
static PyObject *py_func = NULL;
2121
PyObject *ret_obj;
2222
int ret;
2323

24-
npy_cache_import("numpy._core._internal", "npy_ctypes_check", &py_func);
25-
if (py_func == NULL) {
24+
npy_cache_import("numpy._core._internal", "npy_ctypes_check",
25+
&npy_thread_unsafe_state.npy_ctypes_check);
26+
if (npy_thread_unsafe_state.npy_ctypes_check == NULL) {
2627
goto fail;
2728
}
2829

29-
ret_obj = PyObject_CallFunctionObjArgs(py_func, (PyObject *)obj, NULL);
30+
ret_obj = PyObject_CallFunctionObjArgs(npy_thread_unsafe_state.npy_ctypes_check,
31+
(PyObject *)obj, NULL);
3032
if (ret_obj == NULL) {
3133
goto fail;
3234
}

numpy/_core/src/common/ufunc_override.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "npy_import.h"
88
#include "ufunc_override.h"
99
#include "scalartypes.h"
10+
#include "npy_static_data.h"
1011

1112
/*
1213
* Check whether an object has __array_ufunc__ defined on its class and it
@@ -19,15 +20,8 @@
1920
NPY_NO_EXPORT PyObject *
2021
PyUFuncOverride_GetNonDefaultArrayUfunc(PyObject *obj)
2122
{
22-
static PyObject *ndarray_array_ufunc = NULL;
2323
PyObject *cls_array_ufunc;
2424

25-
/* On first entry, cache ndarray's __array_ufunc__ */
26-
if (ndarray_array_ufunc == NULL) {
27-
ndarray_array_ufunc = PyObject_GetAttrString((PyObject *)&PyArray_Type,
28-
"__array_ufunc__");
29-
}
30-
3125
/* Fast return for ndarray */
3226
if (PyArray_CheckExact(obj)) {
3327
return NULL;
@@ -41,15 +35,15 @@ PyUFuncOverride_GetNonDefaultArrayUfunc(PyObject *obj)
4135
* Does the class define __array_ufunc__? (Note that LookupSpecial has fast
4236
* return for basic python types, so no need to worry about those here)
4337
*/
44-
cls_array_ufunc = PyArray_LookupSpecial(obj, npy_um_str_array_ufunc);
38+
cls_array_ufunc = PyArray_LookupSpecial(obj, npy_interned_str.array_ufunc);
4539
if (cls_array_ufunc == NULL) {
4640
if (PyErr_Occurred()) {
4741
PyErr_Clear(); /* TODO[gh-14801]: propagate crashes during attribute access? */
4842
}
4943
return NULL;
5044
}
5145
/* Ignore if the same as ndarray.__array_ufunc__ */
52-
if (cls_array_ufunc == ndarray_array_ufunc) {
46+
if (cls_array_ufunc == npy_static_pydata.ndarray_array_ufunc) {
5347
Py_DECREF(cls_array_ufunc);
5448
return NULL;
5549
}

numpy/_core/src/multiarray/alloc.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include "numpy/npy_common.h"
1212
#include "npy_config.h"
1313
#include "alloc.h"
14+
#include "npy_static_data.h"
15+
#include "multiarraymodule.h"
1416

1517
#include <assert.h>
1618
#ifdef NPY_OS_LINUX
@@ -35,21 +37,19 @@ typedef struct {
3537
static cache_bucket datacache[NBUCKETS];
3638
static cache_bucket dimcache[NBUCKETS_DIM];
3739

38-
static int _madvise_hugepage = 1;
39-
4040

4141
/*
4242
* This function tells whether NumPy attempts to call `madvise` with
4343
* `MADV_HUGEPAGE`. `madvise` is only ever used on linux, so the value
44-
* of `_madvise_hugepage` may be ignored.
44+
* of `madvise_hugepage` may be ignored.
4545
*
4646
* It is exposed to Python as `np._core.multiarray._get_madvise_hugepage`.
4747
*/
4848
NPY_NO_EXPORT PyObject *
4949
_get_madvise_hugepage(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args))
5050
{
5151
#ifdef NPY_OS_LINUX
52-
if (_madvise_hugepage) {
52+
if (npy_thread_unsafe_state.madvise_hugepage) {
5353
Py_RETURN_TRUE;
5454
}
5555
#endif
@@ -59,20 +59,20 @@ _get_madvise_hugepage(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args))
5959

6060
/*
6161
* This function enables or disables the use of `MADV_HUGEPAGE` on Linux
62-
* by modifying the global static `_madvise_hugepage`.
63-
* It returns the previous value of `_madvise_hugepage`.
62+
* by modifying the global static `madvise_hugepage`.
63+
* It returns the previous value of `madvise_hugepage`.
6464
*
6565
* It is exposed to Python as `np._core.multiarray._set_madvise_hugepage`.
6666
*/
6767
NPY_NO_EXPORT PyObject *
6868
_set_madvise_hugepage(PyObject *NPY_UNUSED(self), PyObject *enabled_obj)
6969
{
70-
int was_enabled = _madvise_hugepage;
70+
int was_enabled = npy_thread_unsafe_state.madvise_hugepage;
7171
int enabled = PyObject_IsTrue(enabled_obj);
7272
if (enabled < 0) {
7373
return NULL;
7474
}
75-
_madvise_hugepage = enabled;
75+
npy_thread_unsafe_state.madvise_hugepage = enabled;
7676
if (was_enabled) {
7777
Py_RETURN_TRUE;
7878
}
@@ -110,7 +110,8 @@ _npy_alloc_cache(npy_uintp nelem, npy_uintp esz, npy_uint msz,
110110
#endif
111111
#ifdef NPY_OS_LINUX
112112
/* allow kernel allocating huge pages for large arrays */
113-
if (NPY_UNLIKELY(nelem * esz >= ((1u<<22u))) && _madvise_hugepage) {
113+
if (NPY_UNLIKELY(nelem * esz >= ((1u<<22u))) &&
114+
npy_thread_unsafe_state.madvise_hugepage) {
114115
npy_uintp offset = 4096u - (npy_uintp)p % (4096u);
115116
npy_uintp length = nelem * esz - offset;
116117
/**

numpy/_core/src/multiarray/array_converter.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#include "abstractdtypes.h"
2222
#include "convert_datatype.h"
2323
#include "descriptor.h"
24-
#include "multiarraymodule.h"
24+
#include "npy_static_data.h"
2525
#include "ctors.h"
2626

2727
#include "npy_config.h"
@@ -186,8 +186,8 @@ static int
186186
pyscalar_mode_conv(PyObject *obj, scalar_policy *policy)
187187
{
188188
PyObject *strings[3] = {
189-
npy_ma_str_convert, npy_ma_str_preserve,
190-
npy_ma_str_convert_if_no_array};
189+
npy_interned_str.convert, npy_interned_str.preserve,
190+
npy_interned_str.convert_if_no_array};
191191

192192
/* First quick pass using the identity (should practically always match) */
193193
for (int i = 0; i < 3; i++) {

numpy/_core/src/multiarray/arrayfunction_override.c

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,41 +7,25 @@
77
#include "numpy/ndarraytypes.h"
88
#include "get_attr_string.h"
99
#include "npy_import.h"
10+
#include "npy_static_data.h"
1011
#include "multiarraymodule.h"
1112

1213
#include "arrayfunction_override.h"
1314

14-
/* Return the ndarray.__array_function__ method. */
15-
static PyObject *
16-
get_ndarray_array_function(void)
17-
{
18-
PyObject* method = PyObject_GetAttrString((PyObject *)&PyArray_Type,
19-
"__array_function__");
20-
assert(method != NULL);
21-
return method;
22-
}
23-
24-
2515
/*
2616
* Get an object's __array_function__ method in the fastest way possible.
2717
* Never raises an exception. Returns NULL if the method doesn't exist.
2818
*/
2919
static PyObject *
3020
get_array_function(PyObject *obj)
3121
{
32-
static PyObject *ndarray_array_function = NULL;
33-
34-
if (ndarray_array_function == NULL) {
35-
ndarray_array_function = get_ndarray_array_function();
36-
}
37-
3822
/* Fast return for ndarray */
3923
if (PyArray_CheckExact(obj)) {
40-
Py_INCREF(ndarray_array_function);
41-
return ndarray_array_function;
24+
Py_INCREF(npy_static_pydata.ndarray_array_function);
25+
return npy_static_pydata.ndarray_array_function;
4226
}
4327

44-
PyObject *array_function = PyArray_LookupSpecial(obj, npy_ma_str_array_function);
28+
PyObject *array_function = PyArray_LookupSpecial(obj, npy_interned_str.array_function);
4529
if (array_function == NULL && PyErr_Occurred()) {
4630
PyErr_Clear(); /* TODO[gh-14801]: propagate crashes during attribute access? */
4731
}
@@ -142,12 +126,7 @@ get_implementing_args_and_methods(PyObject *relevant_args,
142126
static int
143127
is_default_array_function(PyObject *obj)
144128
{
145-
static PyObject *ndarray_array_function = NULL;
146-
147-
if (ndarray_array_function == NULL) {
148-
ndarray_array_function = get_ndarray_array_function();
149-
}
150-
return obj == ndarray_array_function;
129+
return obj == npy_static_pydata.ndarray_array_function;
151130
}
152131

153132

@@ -175,7 +154,7 @@ array_function_method_impl(PyObject *func, PyObject *types, PyObject *args,
175154
}
176155
}
177156

178-
PyObject *implementation = PyObject_GetAttr(func, npy_ma_str_implementation);
157+
PyObject *implementation = PyObject_GetAttr(func, npy_interned_str.implementation);
179158
if (implementation == NULL) {
180159
return NULL;
181160
}
@@ -252,14 +231,14 @@ get_args_and_kwargs(
252231
static void
253232
set_no_matching_types_error(PyObject *public_api, PyObject *types)
254233
{
255-
static PyObject *errmsg_formatter = NULL;
256234
/* No acceptable override found, raise TypeError. */
257235
npy_cache_import("numpy._core._internal",
258236
"array_function_errmsg_formatter",
259-
&errmsg_formatter);
260-
if (errmsg_formatter != NULL) {
237+
&npy_thread_unsafe_state.array_function_errmsg_formatter);
238+
if (npy_thread_unsafe_state.array_function_errmsg_formatter != NULL) {
261239
PyObject *errmsg = PyObject_CallFunctionObjArgs(
262-
errmsg_formatter, public_api, types, NULL);
240+
npy_thread_unsafe_state.array_function_errmsg_formatter,
241+
public_api, types, NULL);
263242
if (errmsg != NULL) {
264243
PyErr_SetObject(PyExc_TypeError, errmsg);
265244
Py_DECREF(errmsg);
@@ -321,12 +300,12 @@ array_implement_c_array_function_creation(
321300
}
322301

323302
/* The like argument must be present in the keyword arguments, remove it */
324-
if (PyDict_DelItem(kwargs, npy_ma_str_like) < 0) {
303+
if (PyDict_DelItem(kwargs, npy_interned_str.like) < 0) {
325304
goto finish;
326305
}
327306

328307
/* Fetch the actual symbol (the long way right now) */
329-
numpy_module = PyImport_Import(npy_ma_str_numpy);
308+
numpy_module = PyImport_Import(npy_interned_str.numpy);
330309
if (numpy_module == NULL) {
331310
goto finish;
332311
}

numpy/_core/src/multiarray/arrayobject.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,7 @@ maintainer email: [email protected]
6262

6363
#include "binop_override.h"
6464
#include "array_coercion.h"
65-
66-
67-
NPY_NO_EXPORT npy_bool numpy_warn_if_no_mem_policy = 0;
65+
#include "multiarraymodule.h"
6866

6967
/*NUMPY_API
7068
Compute the size of an array (in number of items)
@@ -429,7 +427,7 @@ array_dealloc(PyArrayObject *self)
429427
}
430428
}
431429
if (fa->mem_handler == NULL) {
432-
if (numpy_warn_if_no_mem_policy) {
430+
if (npy_thread_unsafe_state.warn_if_no_mem_policy) {
433431
char const *msg = "Trying to dealloc data, but a memory policy "
434432
"is not set. If you take ownership of the data, you must "
435433
"set a base owning the data (e.g. a PyCapsule).";
@@ -927,7 +925,8 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
927925
*/
928926
if (result == NULL
929927
&& (cmp_op == Py_EQ || cmp_op == Py_NE)
930-
&& PyErr_ExceptionMatches(npy_UFuncNoLoopError)) {
928+
&& PyErr_ExceptionMatches(
929+
npy_static_pydata._UFuncNoLoopError)) {
931930
PyErr_Clear();
932931

933932
PyArrayObject *array_other = (PyArrayObject *)PyArray_FROM_O(other);

0 commit comments

Comments
 (0)