Skip to content

Commit

Permalink
REF: stats: refactor unuran wrapper to address memory leaks
Browse files Browse the repository at this point in the history
The previous wrapper had memory leaks due to non-local returns.
This PR eliminates the problem by using the `MessageStream` API
(originally used in Qhull to handle errors occurring in `qhull`
C API).

UNU.RAN uses a global `FILE *` stream which makes it thread-unsafe
to use those streams without first acquiring a lock. To expound on
the problem, we have to call `unur_set_stream` under a lock otherwise
some other thread could change the global `FILE *` variable and all
the errors will be redirected to that wrong file.

Moreover, as non-local jumps are not allowed, `PyErr_Occurred` is
used to catch errors inside callbacks once the UNU.RAN function has
been executed.
  • Loading branch information
tirthasheshpatel committed Jul 15, 2021
1 parent 8ce9e75 commit 01015cd
Show file tree
Hide file tree
Showing 6 changed files with 555 additions and 567 deletions.
4 changes: 2 additions & 2 deletions doc/source/tutorial/stats/sampling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ continuous and discrete distributions. Implementations of a fast C library
called `UNU.RAN <http://statmath.wu.ac.at/software/unuran/>`__ are used
for speed and performance. Please look at
`UNU.RAN's documentation <http://statmath.wu.ac.at/software/unuran/doc/unuran.html>`__
for an in-depth explanation of these methods. It is heavily referred
for an in-depth explanation of these methods. It is heavily referred to
for writing this tutorial and the documentation of all the generators.


Expand Down Expand Up @@ -81,7 +81,7 @@ parameter with a NumPy BitGenerator as the uniform random number generator.

.. warning:: Use of NumPy < 1.19.0 is discouraged as it doesn't have a fast
Cython API for generating uniform random numbers and might be
too slow to practically rely on.
too slow for practical use.

All the generators have a common ``rvs`` method that can be used to draw
samples from the given distribution.
Expand Down
3 changes: 2 additions & 1 deletion scipy/stats/_unuran/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .unuran_wrapper import (
TransformedDensityRejection,
DiscreteAliasUrn
DiscreteAliasUrn,
UNURANError
)
6 changes: 6 additions & 0 deletions scipy/stats/_unuran/unuran.pxd
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# File automatically generated using autopxd2

from libc.stdio cimport FILE

cdef extern from "unuran.h" nogil:

cdef struct unur_distr
Expand Down Expand Up @@ -1227,6 +1229,10 @@ cdef extern from "unuran.h" nogil:

UNUR_DISTR* unur_distr_zipf(double* params, int n_params)

FILE* unur_set_stream(FILE* new_stream)

FILE* unur_get_stream()

int unur_set_debug(UNUR_PAR* parameters, unsigned debug)

int unur_chg_debug(UNUR_GEN* generator, unsigned debug)
Expand Down
Loading

0 comments on commit 01015cd

Please sign in to comment.