If a NumPy array is shared between two threads, NumPy doesn’t do anything to synchronize array access. This is true in all Python versions and build configurations - since NumPy releases the GIL during most array operations whether or not you’re using free-threaded Python doesn’t change much except for e.g. object arrays, which do hold the GIL.
See: https://numpy.org/doc/stable/reference/thread_safety.html IMO you probably shouldn’t try to enforce more strict thread safety than NumPy itself does. We didn’t add any locking to support free-threaded Python because it’s always worked like this, and introducing locking might lead to performance bottlenecks in read-only multithreaded applications and would substantially increase NumPy’s internal complexity. Long-term, I’d like to see more effort put towards adding stronger guarantees around freezing arrays. I also want to look closer at adding runtime checks to detect races and report them. One example: you could imagine each array having an internal “version” counter that is incremented every time the array is mutated. Doing an atomic read on the version before and after a mutation should hopefully have a small overhead compared with the rest of NumPy, and we could report runtime errors when arrays are mutated “underneath” a thread doing an operation. The devil is in the details though - there are *a lot* of ways to mutate NumPy arrays. This also doesn’t consider the buffer protocol or accessing arrays via third-party C extensions. See e.g. Alex Gaynor’s blog post on this from the perspective of Rust and PyO3: https://alexgaynor.net/2022/oct/23/buffers-on-the-edge/ On Thu, Jul 3, 2025 at 5:50 AM Benjamin Root via NumPy-Discussion < numpy-discussion@python.org> wrote: > On a related note, does numpy's gufunc mechanism provide any thread > safety, or is the responsibility on the extension writer to do that? For > simple numpy array inputs, I would think that I don't have to worry about > free-threaded python messing things up (unless I have a global state), I'm > wondering if something like dask array inputs could mess up calls to a > thread-unsafe function. > > If it is on the extension writer, are there any examples on how to do > that? Are there other guarantees (or lack thereof) that a gufunc writer > should be aware of? How about reorderability? gufuncs operates on > subarrays, so wouldn't dask inputs that are chunked potentially operate on > the chunks in any order they like? > > Thanks, > Ben Root > > > On Tue, Jul 1, 2025 at 4:26 PM Benjamin Root <ben.v.r...@gmail.com> wrote: > >> Warren, >> >> The examples in ufunclab helped clear up a few things and I was able to >> experiment and get a working gufunc! Thank you for your help! >> >> Ben Root >> >> On Fri, Jun 27, 2025 at 8:54 PM Benjamin Root <ben.v.r...@gmail.com> >> wrote: >> >>> Warren, >>> >>> I'm fine with implementing it in C. I just didn't think gufuncs were for >>> me. I couldn't tell from the description if it would be for my usecase >>> since I wasn't looping over subarrays, and I didn't see any good examples. >>> Maybe the documentation could be clearer. I'll have a look at your examples. >>> >>> I did try that signature with np.vectorize() with the signature keyword >>> argument, but it didn't seem to work. Maybe it didn't work for the reasons >>> in that open issue. >>> >>> Thank you, >>> Ben Root >>> >>> On Fri, Jun 27, 2025 at 8:03 PM Warren Weckesser via NumPy-Discussion < >>> numpy-discussion@python.org> wrote: >>> >>>> On Fri, Jun 27, 2025 at 5:29 PM Benjamin Root via NumPy-Discussion >>>> <numpy-discussion@python.org> wrote: >>>> > >>>> > I'm looking at a situation where I like to wrap a C++ function that >>>> takes two doubles as inputs, and returns an error code, a position vector, >>>> and a velocity vector so that I essentially would have a function signature >>>> of (N), (N) -> (N), (N, 3), (N, 3). When I try to use np.vectorize() or >>>> np.frompyfunc() on the python version of this function, I keep running into >>>> issues where it wants to make the outputs into object arrays of tuples. And >>>> looking at utilizing PyUFunc_FromFuncAndData, it isn't clear to me how I >>>> can tell it to expect those two output arrays to have a size 3 outer >>>> dimension. >>>> > >>>> > Are ufuncs the wrong thing here? How should I go about this? Is it >>>> even possible? >>>> >>>> Ben, >>>> >>>> It looks like the simplest signature for your core operation would be >>>> (),()->(),(3),(3), with broadcasting taking care of higher dimensional >>>> inputs. Because not all the core shapes are scalars, that would >>>> require a *generalized* ufunc (gufunc). There is an open issue >>>> (https://github.com/numpy/numpy/issues/14020) with a request for a >>>> function to generate a gufunc from a Python function. >>>> >>>> numba has the @guvectorize decorator, but I haven't use it much, and >>>> in my few quick attempts just now, it appeared to not accept fixed >>>> integer sizes in the output shape. But wait to see if any numba gurus >>>> respond with a definitive answer about whether or not it can handle >>>> the shape signature (),()->(),(3),(3). >>>> >>>> You could implement the gufunc in a C or C++ extension module, if you >>>> don't mind the additional development effort and packaging hassle. I >>>> know that works--I've implemented quite a few gufuncs in ufunclab >>>> (https://github.com/WarrenWeckesser/ufunclab). >>>> >>>> Warren >>>> >>>> >>>> > >>>> > Thanks in advance, >>>> > Ben Root >>>> > _______________________________________________ >>>> > NumPy-Discussion mailing list -- numpy-discussion@python.org >>>> > To unsubscribe send an email to numpy-discussion-le...@python.org >>>> > https://mail.python.org/mailman3//lists/numpy-discussion.python.org >>>> > Member address: warren.weckes...@gmail.com >>>> _______________________________________________ >>>> NumPy-Discussion mailing list -- numpy-discussion@python.org >>>> To unsubscribe send an email to numpy-discussion-le...@python.org >>>> https://mail.python.org/mailman3//lists/numpy-discussion.python.org >>>> Member address: ben.v.r...@gmail.com >>>> >>> _______________________________________________ > NumPy-Discussion mailing list -- numpy-discussion@python.org > To unsubscribe send an email to numpy-discussion-le...@python.org > https://mail.python.org/mailman3//lists/numpy-discussion.python.org > Member address: nathan12...@gmail.com >
_______________________________________________ NumPy-Discussion mailing list -- numpy-discussion@python.org To unsubscribe send an email to numpy-discussion-le...@python.org https://mail.python.org/mailman3//lists/numpy-discussion.python.org Member address: arch...@mail-archive.com