8000 MNT: Reorganize non-constant global statics into structs by ngoldbaum · Pull Request #26607 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

MNT: Reorganize non-constant global statics into structs #26607

New issue < 8000 /summary>

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
baee891
MNT: move interned strings into a single global struct
ngoldbaum May 30, 2024
69075c1
MNT: move cached imports into a global struct
ngoldbaum May 21, 2024
e5c1bd6
MNT: move cpu dispatch registry into global data struct
ngoldbaum May 30, 2024
7719cf2
MNT: move ndarray.__array_*__ references to global data struct
ngoldbaum May 30, 2024
3cbb68d
MNT: move sys.flags.optimize cache to global data struct
ngoldbaum May 30, 2024
2ffcc71
MNT: set up tuple for truediv in global data struct
ngoldbaum May 30, 2024
d2ca21b
MNT: move unpack_bits LUT into global static struct
ngoldbaum May 30, 2024
a1f7200
MNT: move references to int(1) and int(0) to global static struct
ngoldbaum May 30, 2024
26c243d
MNT: move initialization of global ArrayMethods to module initialization
ngoldbaum May 30, 2024
536e5fb
MNT: move initialization of global tuples to global data struct
ngoldbaum May 30, 2024
0c22126
MNT: move default extobj contextvar to global data dict
ngoldbaum May 30, 2024
90b1f38
MNT: move PyArray_SetStringFunction internals into global data struct
ngoldbaum May 30, 2024
6a296c4
BUG: remove questionable static initialization of an array object
ngoldbaum May 30, 2024
398f095
MNT: split global data struct into two structs
ngoldbaum Jun 3, 2024
8f84875
MNT: add PyArrayMethodObject caches to static data struct
ngoldbaum Jun 5, 2024
402a83c
MNT: move some thread-unsafe state in thread-unsafe state struct
ngoldbaum Jun 5, 2024
e43275a
MNT: make data structs static instead of heap-allocated
ngoldbaum Jun 5, 2024
b706536
MNT: apply sebastian's refactoring suggestions
ngoldbaum Jun 6, 2024
c237038
MNT: move static data structs into their own file
ngoldbaum Jun 7, 2024
8000
98ae65d
MNT: Add more global state I missed to the thread_unsafe_state struct
ngoldbaum Jun 7, 2024
a334ddc
MNT: verify all entries in npy_interned_str and npy_static_pydata are…
ngoldbaum Jun 11, 2024
9ed317f
Apply suggestions from code review
ngoldbaum Jun 13, 2024
3ae66b1
MAINT: apply more of Sebastian's suggestions
ngoldbaum Jun 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions numpy/_core/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,7 @@ src_multiarray = multiarray_gen_headers + [
'src/multiarray/nditer_constr.c',
'src/multiarray/nditer_pywrap.c',
src_file.process('src/multiarray/nditer_templ.c.src'),
'src/multiarray/npy_static_data.c',
'src/multiarray/number.c',
'src/multiarray/refcount.c',
src_file.process('src/multiarray/scalartypes.c.src'),
Expand Down
3 changes: 2 additions & 1 deletion numpy/_core/src/common/binop_override.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "numpy/arrayobject.h"

#include "get_attr_string.h"
#include "npy_static_data.h"

/*
* Logic for deciding when binops should return NotImplemented versus when
Expand Down Expand Up @@ -128,7 +129,7 @@ binop_should_defer(PyObject *self, PyObject *other, int inplace)
* Classes with __array_ufunc__ are living in the future, and only need to
* check whether __array_ufunc__ equals None.
*/
attr = PyArray_LookupSpecial(other, npy_um_str_array_ufunc);
attr = PyArray_LookupSpecial(other, npy_interned_str.array_ufunc);
if (attr != NULL) {
defer = !inplace && (attr == Py_None);
Py_DECREF(attr);
Expand Down
15 changes: 9 additions & 6 deletions numpy/_core/src/common/npy_cpu_dispatch.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#include "npy_cpu_dispatch.h"
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
#define _MULTIARRAYMODULE

static PyObject *npy__cpu_dispatch_registery = NULL;
#include "npy_cpu_dispatch.h"
#include "numpy/ndarraytypes.h"
#include "npy_static_data.h"

NPY_VISIBILITY_HIDDEN int
npy_cpu_dispatch_tracer_init(PyObject *mod)
{
if (npy__cpu_dispatch_registery != NULL) {
if (npy_static_pydata.cpu_dispatch_registry != NULL) {
PyErr_Format(PyExc_RuntimeError, "CPU dispatcher tracer already initlized");
return -1;
}
Expand All @@ -22,21 +25,21 @@ npy_cpu_dispatch_tracer_init(PyObject *mod)
if (err != 0) {
return -1;
}
npy__cpu_dispatch_registery = reg_dict;
npy_static_pydata.cpu_dispatch_registry = reg_dict;
return 0;
}

NPY_VISIBILITY_HIDDEN void
npy_cpu_dispatch_trace(const char *fname, const char *signature,
const char **dispatch_info)
{
PyObject *func_dict = PyDict_GetItemString(npy__cpu_dispatch_registery, fname);
PyObject *func_dict = PyDict_GetItemString(npy_static_pydata.cpu_dispatch_registry, fname);
if (func_dict == NULL) {
func_dict = PyDict_New();
if (func_dict == NULL) {
return;
}
int err = PyDict_SetItemString(npy__cpu_dispatch_registery, fname, func_dict);
int err = PyDict_SetItemString(npy_static_pydata.cpu_dispatch_registry, fname, func_dict);
Py_DECREF(func_dict);
if (err != 0) {
return;
Expand Down
5 changes: 5 additions & 0 deletions numpy/_core/src/common/npy_cpu_features.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@

/******************** Private Definitions *********************/

// This is initialized during module initialization and thereafter immutable.
// We don't include it in the global data struct because the definitions in
// this file are shared by the _simd, _umath_tests, and
// _multiarray_umath modules

// Hold all CPU features boolean values
static unsigned char npy__cpu_have[NPY_CPU_FEATURE_MAX];

Expand Down
10 changes: 6 additions & 4 deletions numpy/_core/src/common/npy_ctypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <Python.h>

#include "npy_import.h"
#include "multiarraymodule.h"

/*
* Check if a python type is a ctypes class.
Expand All @@ -17,16 +18,17 @@
static inline int
npy_ctypes_check(PyTypeObject *obj)
{
static PyObject *py_func = NULL;
PyObject *ret_obj;
int ret;

npy_cache_import("numpy._core._internal", "npy_ctypes_check", &py_func);
if (py_func == NULL) {
npy_cache_import("numpy._core._internal", "npy_ctypes_check",
&npy_thread_unsafe_state.npy_ctypes_check);
if (npy_thread_unsafe_state.npy_ctypes_check == NULL) {
goto fail;
}

ret_obj = PyObject_CallFunctionObjArgs(py_func, (PyObject *)obj, NULL);
ret_obj = PyObject_CallFunctionObjArgs(npy_thread_unsafe_state.npy_ctypes_check,
(PyObject *)obj, NULL);
if (ret_obj == NULL) {
goto fail;
}
Expand Down
12 changes: 3 additions & 9 deletions numpy/_core/src/common/ufunc_override.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "npy_import.h"
#include "ufunc_override.h"
#include "scalartypes.h"
#include "npy_static_data.h"

/*
* Check whether an object has __array_ufunc__ defined on its class and it
Expand All @@ -19,15 +20,8 @@
NPY_NO_EXPORT PyObject *
PyUFuncOverride_GetNonDefaultArrayUfunc(PyObject *obj)
{
static PyObject *ndarray_array_ufunc = NULL;
PyObject *cls_array_ufunc;

/* On first entry, cache ndarray's __array_ufunc__ */
if (ndarray_array_ufunc == NULL) {
ndarray_array_ufunc = PyObject_GetAttrString((PyObject *)&PyArray_Type,
"__array_ufunc__");
}

/* Fast return for ndarray */
if (PyArray_CheckExact(obj)) {
return NULL;
Expand All @@ -41,15 +35,15 @@ PyUFuncOverride_GetNonDefaultArrayUfunc(PyObject *obj)
* Does the class define __array_ufunc__? (Note that LookupSpecial has fast
* return for basic python types, so no need to worry about those here)
*/
cls_array_ufunc = PyArray_LookupSpecial(obj, npy_um_str_array_ufunc);
cls_array_ufunc = PyArray_LookupSpecial(obj, npy_interned_str.array_ufunc);
if (cls_array_ufunc == NULL) {
if (PyErr_Occurred()) {
PyErr_Clear(); /* TODO[gh-14801]: propagate crashes during attribute access? */
}
return NULL;
}
/* Ignore if the same as ndarray.__array_ufunc__ */
if (cls_array_ufunc == ndarray_array_ufunc) {
if (cls_array_ufunc == npy_static_pydata.ndarray_array_ufunc) {
Py_DECREF(cls_array_ufunc);
return NULL;
}
Expand Down
19 changes: 10 additions & 9 deletions numpy/_core/src/multiarray/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "numpy/npy_common.h"
#include "npy_config.h"
#include "alloc.h"
#include "npy_static_data.h"
#include "multiarraymodule.h"

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

static int _madvise_hugepage = 1;


/*
* This function tells whether NumPy attempts to call `madvise` with
* `MADV_HUGEPAGE`. `madvise` is only ever used on linux, so the value
* of `_madvise_hugepage` may be ignored.
* of `madvise_hugepage` may be ignored.
*
* It is exposed to Python as `np._core.multiarray._get_madvise_hugepage`.
*/
NPY_NO_EXPORT PyObject *
_get_madvise_hugepage(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args))
{
#ifdef NPY_OS_LINUX
if (_madvise_hugepage) {
if (npy_thread_unsafe_state.madvise_hugepage) {
Py_RETURN_TRUE;
}
#endif
Expand All @@ -59,20 +59,20 @@ _get_madvise_hugepage(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args))

/*
* This function enables or disables the use of `MADV_HUGEPAGE` on Linux
* by modifying the global static `_madvise_hugepage`.
* It returns the previous value of `_madvise_hugepage`.
* by modifying the global static `madvise_hugepage`.
* It returns the previous value of `madvise_hugepage`.
*
* It is exposed to Python as `np._core.multiarray._set_madvise_hugepage`.
*/
NPY_NO_EXPORT PyObject *
_set_madvise_hugepage(PyObject *NPY_UNUSED(self), PyObject *enabled_obj)
{
int was_enabled = _madvise_hugepage;
int was_enabled = npy_thread_unsafe_state.madvise_hugepage;
int enabled = PyObject_IsTrue(enabled_obj);
if (enabled < 0) {
return NULL;
}
_madvise_hugepage = enabled;
npy_thread_unsafe_state.madvise_hugepage = enabled;
if (was_enabled) {
Py_RETURN_TRUE;
}
Expand Down Expand Up @@ -110,7 +110,8 @@ _npy_alloc_cache(npy_uintp nelem, npy_uintp esz, npy_uint msz,
#endif
#ifdef NPY_OS_LINUX
/* allow kernel allocating huge pages for large arrays */
if (NPY_UNLIKELY(nelem * esz >= ((1u<<22u))) && _madvise_hugepage) {
if (NPY_UNLIKELY(nelem * esz >= ((1u<<22u))) &&
npy_thread_unsafe_state.madvise_hugepage) {
npy_uintp offset = 4096u - (npy_uintp)p % (4096u);
npy_uintp length = nelem * esz - offset;
/**
Expand Down
6 changes: 3 additions & 3 deletions numpy/_core/src/multiarray/array_converter.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include "abstractdtypes.h"
#include "convert_datatype.h"
#include "descriptor.h"
#include "multiarraymodule.h"
#include "npy_static_data.h"
#include "ctors.h"

#include "npy_config.h"
Expand Down Expand Up @@ -186,8 +186,8 @@ static int
pyscalar_mode_conv(PyObject *obj, scalar_policy *policy)
{
PyObject *strings[3] = {
npy_ma_str_convert, npy_ma_str_preserve,
npy_ma_str_convert_if_no_array};
npy_interned_str.convert, npy_interned_str.preserve,
npy_interned_str.convert_if_no_array};

/* First quick pass using the identity (should practically always match) */
for (int i = 0; i < 3; i++) {
Expand Down
45 changes: 12 additions & 33 deletions numpy/_core/src/multiarray/arrayfunction_override.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,25 @@
#include "numpy/ndarraytypes.h"
#include "get_attr_string.h"
#include "npy_import.h"
#include "npy_static_data.h"
#include "multiarraymodule.h"

#include "arrayfunction_override.h"

/* Return the ndarray.__array_function__ method. */
static PyObject *
get_ndarray_array_function(void)
{
PyObject* method = PyObject_GetAttrString((PyObject *)&PyArray_Type,
"__array_function__");
assert(method != NULL);
return method;
}


/*
* Get an object's __array_function__ method in the fastest way possible.
* Never raises an exception. Returns NULL if the method doesn't exist.
*/
static PyObject *
get_array_function(PyObject *obj)
{
static PyObject *ndarray_array_fun F438 ction = NULL;

if (ndarray_array_function == NULL) {
ndarray_array_function = get_ndarray_array_function();
}

/* Fast return for ndarray */
if (PyArray_CheckExact(obj)) {
Py_INCREF(ndarray_array_function);
return ndarray_array_function;
Py_INCREF(npy_static_pydata.ndarray_array_function);
return npy_static_pydata.ndarray_array_function;
}

PyObject *array_function = PyArray_LookupSpecial(obj, npy_ma_str_array_function);
PyObject *array_function = PyArray_LookupSpecial(obj, npy_interned_str.array_function);
if (array_function == NULL && PyErr_Occurred()) {
PyErr_Clear(); /* TODO[gh-14801]: propagate crashes during attribute access? */
}
Expand Down Expand Up @@ -142,12 +126,7 @@ get_implementing_args_and_methods(PyObject *relevant_args,
static int
is_default_array_function(PyObject *obj)
{
static PyObject *ndarray_array_function = NULL;

if (ndarray_array_function == NULL) {
ndarray_array_function = get_ndarray_array_function();
}
return obj == ndarray_array_function;
return obj == npy_static_pydata.ndarray_array_function;
}


Expand Down Expand Up @@ -175,7 +154,7 @@ array_function_method_impl(PyObject *func, PyObject *types, PyObject *args,
}
}

PyObject *implementation = PyObject_GetAttr(func, npy_ma_str_implementation);
PyObject *implementation = PyObject_GetAttr(func, npy_interned_str.implementation);
if (implementation == NULL) {
return NULL;
}
Expand Down Expand Up @@ -252,14 +231,14 @@ get_args_and_kwargs(
static void
set_no_matching_types_error(PyObject *public_api, PyObject *types)
{
static PyObject *errmsg_formatter = NULL;
/* No acceptable override found, raise TypeError. */
npy_cache_import("numpy._core._internal",
"array_function_errmsg_formatter",
&errmsg_formatter);
if (errmsg_formatter != NULL) {
&npy_thread_unsafe_state.array_function_errmsg_formatter);
if (npy_thread_unsafe_state.array_function_errmsg_formatter != NULL) {
PyObject *errmsg = PyObject_CallFunctionObjArgs(
errmsg_formatter, public_api, types, NULL);
npy_thread_unsafe_state.array_function_errmsg_formatter,
public_api, types, NULL);
if (errmsg != NULL) {
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
Expand Down Expand Up @@ -321,12 +300,12 @@ array_implement_c_array_function_creation(
}

/* The like argument must be present in the keyword arguments, remove it */
if (PyDict_DelItem(kwargs, npy_ma_str_like) < 0) {
if (PyDict_DelItem(kwargs, npy_interned_str.like) < 0) {
goto finish;
}

/* Fetch the actual symbol (the long way right now) */
numpy_module = PyImport_Import(npy_ma_str_numpy);
numpy_module = PyImport_Import(npy_interned_str.numpy);
if (numpy_module == NULL) {
goto finish;
}
Expand Down
9 changes: 4 additions & 5 deletions numpy/_core/src/multiarray/arrayobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ maintainer email: oliphant.travis@ieee.org

#include "binop_override.h"
#include "array_coercion.h"


NPY_NO_EXPORT npy_bool numpy_warn_if_no_mem_policy = 0;
#include "multiarraymodule.h"

/*NUMPY_API
Compute the size of an array (in number of items)
Expand Down Expand Up @@ -429,7 +427,7 @@ array_dealloc(PyArrayObject *self)
}
}
if (fa->mem_handler == NULL) {
if (numpy_warn_if_no_mem_policy) {
if (npy_thread_unsafe_state.warn_if_no_mem_policy) {
char const *msg = "Trying to dealloc data, but a memory policy "
"is not set. If you take ownership of the data, you must "
"set a base owning the data (e.g. a PyCapsule).";
Expand Down Expand Up @@ -927,7 +925,8 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
*/
if (result == NULL
&& (cmp_op == Py_EQ || cmp_op == Py_NE)
&& PyErr_ExceptionMatches(npy_UFuncNoLoopError)) {
&& PyErr_ExceptionMatches(
npy_static_pydata._UFuncNoLoopError)) {
PyErr_Clear();

PyArrayObject *array_other = (PyArrayObject *)PyArray_FROM_O(other);
Expand Down
2 changes: 0 additions & 2 deletions numpy/_core/src/multiarray/arrayobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
extern "C" {
#endif

extern NPY_NO_EXPORT npy_bool numpy_warn_if_no_mem_policy;

NPY_NO_EXPORT PyObject *
_strings_richcompare(PyArrayObject *self, PyArrayObject *other, int cmp_op,
int rstrip);
Expand Down
4 changes: 2 additions & 2 deletions numpy/_core/src/multiarray/arraytypes.c.src
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "arraytypes.h"

#include "umathmodule.h"
#include "npy_static_data.h"

/*
* Define a stack allocated dummy array with only the minimum information set:
Expand Down Expand Up @@ -4185,8 +4186,7 @@ NPY_NO_EXPORT _PyArray_LegacyDescr @from@_Descr = {

/* The smallest type number is ?, the largest bounded by 'z'. */
#define _MAX_LETTER ('z' + 1)
static npy_int16 _letter_to_num[_MAX_LETTER - '?'];
#define LETTER_TO_NUM(letter) _letter_to_num[letter - '?']
#define LETTER_TO_NUM(letter) npy_static_cdata._letter_to_num[letter - '?']

static _PyArray_LegacyDescr *_builtin_descrs[] = {
&BOOL_Descr,
Expand Down
Loading
0