Skip to content

Commit

Permalink
Merge pull request numpy#26294 from ngoldbaum/disable-coercion-cache
Browse files Browse the repository at this point in the history
MNT: disable the coercion cache for the nogil build
  • Loading branch information
ngoldbaum authored Apr 19, 2024
2 parents 1440eee + 1d976fc commit da95f8e
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
15 changes: 12 additions & 3 deletions numpy/_core/src/multiarray/array_coercion.c
Original file line number Diff line number Diff line change
Expand Up @@ -615,10 +615,13 @@ update_shape(int curr_ndim, int *max_ndim,
return success;
}


#ifndef Py_GIL_DISABLED
#define COERCION_CACHE_CACHE_SIZE 5
static int _coercion_cache_num = 0;
static coercion_cache_obj *_coercion_cache_cache[COERCION_CACHE_CACHE_SIZE];
#else
#define COERCION_CACHE_CACHE_SIZE 0
#endif

/*
* Steals a reference to the object.
Expand All @@ -629,11 +632,14 @@ npy_new_coercion_cache(
coercion_cache_obj ***next_ptr, int ndim)
{
coercion_cache_obj *cache;
#if COERCION_CACHE_CACHE_SIZE > 0
if (_coercion_cache_num > 0) {
_coercion_cache_num--;
cache = _coercion_cache_cache[_coercion_cache_num];
}
else {
else
#endif
{
cache = PyMem_Malloc(sizeof(coercion_cache_obj));
}
if (cache == NULL) {
Expand Down Expand Up @@ -662,11 +668,14 @@ npy_unlink_coercion_cache(coercion_cache_obj *current)
{
coercion_cache_obj *next = current->next;
Py_DECREF(current->arr_or_sequence);
#if COERCION_CACHE_CACHE_SIZE > 0
if (_coercion_cache_num < COERCION_CACHE_CACHE_SIZE) {
_coercion_cache_cache[_coercion_cache_num] = current;
_coercion_cache_num++;
}
else {
else
#endif
{
PyMem_Free(current);
}
return next;
Expand Down
21 changes: 21 additions & 0 deletions numpy/_core/tests/test_multithreading.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import concurrent.futures

import numpy as np
import pytest

from numpy.testing import IS_WASM

if IS_WASM:
pytest.skip(allow_module_level=True, reason="no threading support in wasm")


def test_parallel_errstate_creation():
# if the coercion cache is enabled and not thread-safe, creating
# RandomState instances simultaneously leads to a data race
def func(seed):
np.random.RandomState(seed)

with concurrent.futures.ThreadPoolExecutor(max_workers=8) as tpe:
futures = [tpe.submit(func, i) for i in range(500)]
for f in futures:
f.result()

0 comments on commit da95f8e

Please sign in to comment.