<div dir="auto">You need to reacquire the gil, then you can get the lock and rerelease the gil. <div dir="auto"><br></div><div dir="auto">I think this works (on phone, so untested)</div><div dir="auto"><br></div><div dir="auto">with gil:</div><div dir="auto"> with nogil, lock:</div><div dir="auto"> ...</div><div dir="auto"><br></div><div dir="auto">Kevin</div><div dir="auto"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Dec 14, 2020, 13:37 Evgeni Burovski <<a href="mailto:evgeny.burovskiy@gmail.com">evgeny.burovskiy@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
What would be the correct way of locking the bit generator of<br>
np.random.Generator in cython's nogil context?<br>
(This is threading 101, surely, so please forgive my ignorance).<br>
<br>
The docs for extending np.random.Generator in cython<br>
(<a href="https://numpy.org/doc/stable/reference/random/extending.html#cython" rel="noreferrer noreferrer" target="_blank">https://numpy.org/doc/stable/reference/random/extending.html#cython</a>)<br>
recommend the following idiom for generating uniform variates, where<br>
the GIL is released and a Generator-specific lock is held:<br>
<br>
x = PCG64()<br>
rng = <bitgen_t *> PyCapsule_GetPointer(x.capsule, capsule_name)<br>
with nogil, x.lock:<br>
rng.next_double(rng.state)<br>
<br>
What is the correct way of locking it when already in the nogil<br>
section (so that x.lock is not accessible)?<br>
<br>
The use case is a long-running MC process which generates random<br>
variates in a tight loop (so the loop is all nogil). In case it<br>
matters, I probably won't be using python threads, but may use<br>
multiprocessing.<br>
<br>
Basically,<br>
<br>
cdef double uniform(self) nogil:<br>
if self.idx >= self.buf.shape[0]:<br>
self._fill()<br>
cdef double value = self.buf[self.idx]<br>
self.idx += 1<br>
return value<br>
<br>
cdef void _fill(self) nogil:<br>
self.idx = 0<br>
# HERE: Lock ?<br>
for i in range(self.buf.shape[0]):<br>
self.buf[i] = self.rng.next_double(self.rng.state)<br>
<br>
<br>
Thanks,<br>
Evgeni<br>
<br>
<br>
P.S. The full cdef class, for completeness:<br>
<br>
cdef class RndmWrapper():<br>
cdef:<br>
double[::1] buf<br>
Py_ssize_t idx<br>
bitgen_t *rng<br>
object py_gen # keep the garbage collector away<br>
<br>
def __init__(self, seed=(1234, 0), buf_size=4096, bitgen_kind=None):<br>
if bitgen_kind is None:<br>
bitgen_kind = PCG64<br>
<br>
# cf Numpy-discussion list, K.~Sheppard, R.~Kern, June 29,<br>
2020 and below<br>
# <a href="https://mail.python.org/pipermail/numpy-discussion/2020-June/080794.html" rel="noreferrer noreferrer" target="_blank">https://mail.python.org/pipermail/numpy-discussion/2020-June/080794.html</a><br>
entropy, num = seed<br>
seed_seq = SeedSequence(entropy, spawn_key=(num,))<br>
py_gen = bitgen_kind(seed_seq)<br>
<br>
# store the python object to avoid it being garbage collected<br>
self.py_gen = py_gen<br>
<br>
capsule = py_gen.capsule<br>
self.rng = <bitgen_t *>PyCapsule_GetPointer(capsule, capsule_name)<br>
if not PyCapsule_IsValid(capsule, capsule_name):<br>
raise ValueError("Invalid pointer to anon_func_state")<br>
<br>
self.buf = np.empty(buf_size, dtype='float64')<br>
self._fill()<br>
<br>
@cython.boundscheck(False)<br>
@cython.wraparound(False)<br>
cdef void _fill(self) nogil:<br>
self.idx = 0<br>
for i in range(self.buf.shape[0]):<br>
self.buf[i] = self.rng.next_double(self.rng.state)<br>
<br>
@cython.boundscheck(False)<br>
@cython.wraparound(False)<br>
cdef double uniform(self) nogil:<br>
if self.idx >= self.buf.shape[0]:<br>
self._fill()<br>
cdef double value = self.buf[self.idx]<br>
self.idx += 1<br>
return value<br>
_______________________________________________<br>
NumPy-Discussion mailing list<br>
<a href="mailto:NumPy-Discussion@python.org" target="_blank" rel="noreferrer">NumPy-Discussion@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/numpy-discussion" rel="noreferrer noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/numpy-discussion</a><br>
</blockquote></div>