[med-svn] [Git][med-team/python-hmmlearn][master] 3 commits: Replace my GIL hack with a proper patch from upstream.
Michael R. Crusoe (@crusoe)
gitlab at salsa.debian.org
Mon Oct 7 09:46:13 BST 2024
Michael R. Crusoe pushed to branch master at Debian Med / python-hmmlearn
Commits:
1d47d537 by Michael R. Crusoe at 2024-10-07T10:00:30+02:00
Replace my GIL hack with a proper patch from upstream.
- - - - -
aae16302 by Michael R. Crusoe at 2024-10-07T10:39:28+02:00
d/control: removed duplicated word from the description
- - - - -
7fbe6a14 by Michael R. Crusoe at 2024-10-07T10:45:23+02:00
relase 0.3.2-2
- - - - -
3 changed files:
- debian/changelog
- debian/control
- debian/patches/gil_fix
Changes:
=====================================
debian/changelog
=====================================
@@ -1,3 +1,11 @@
+python-hmmlearn (0.3.2-2) unstable; urgency=medium
+
+ * Team upload.
+ * Replace my GIL hack with a proper patch from upstream.
+ * d/control: removed duplicated word from the description
+
+ -- Michael R. Crusoe <crusoe at debian.org> Mon, 07 Oct 2024 10:45:05 +0200
+
python-hmmlearn (0.3.2-1) unstable; urgency=medium
* Team upload.
=====================================
debian/control
=====================================
@@ -31,5 +31,5 @@ Recommends: ${python3:Recommends},
python3-sklearn
Description: unsupervised learning and inference of Hidden Markov Models
Hmmlearn is a set of algorithms for unsupervised learning and inference
- of Hidden Markov Models. For supervised learning learning of HMMs and
+ of Hidden Markov Models. For supervised learning of HMMs and
similar models see seqlearn.
=====================================
debian/patches/gil_fix
=====================================
@@ -1,25 +1,159 @@
-From: Michael R. Crusoe <crusoe at debian.org>
-Subject: hack for GIL bug
-Forwarded: https://github.com/hmmlearn/hmmlearn/pull/564
-
-Fixes the follow error and many similar to it
-
- def _fit_scaling(self, X):
- frameprob = self._compute_subnorm_likelihood(X)
-> logprob, fwdlattice, scaling_factors = _hmmc.forward_scaling(
- self.startprob_subnorm_, self.transmat_subnorm_, frameprob)
-E RuntimeError: pybind11::handle::inc_ref() PyGILState_Check() failure.
-
-hmmlearn/base.py:1103: RuntimeError
------------------------------ Captured stderr call -----------------------------
-pybind11::handle::inc_ref() is being called while the GIL is either not held or invalid. Please see https://pybind11.readthedocs.io/en/stable/advanced/misc.html#common-sources-of-global-interpreter-lock-errors for debugging advice.
-If you are convinced there is no bug in your code, you can #define PYBIND11_NO_ASSERT_GIL_HELD_INCREF_DECREF to disable this check. In that case you have to ensure this #define is consistently used for all translation units linked into a given pybind11 extension, otherwise there will be ODR violations. The failing pybind11::handle::inc_ref() call was triggered on a numpy.ndarray object.
+From 38b559464e5f8212225acc4c8aa213732ce8f6e8 Mon Sep 17 00:00:00 2001
+From: Antony Lee <anntzer.lee at gmail.com>
+Date: Sun, 6 Oct 2024 22:47:34 +0200
+Subject: [PATCH] Reacquire GIL before constructing tuples containing numpy
+ arrays.
+... as explicitly required by pybind11. Compile with `#define
+PYBIND11_ASSERT_GIL_HELD_INCREF_DECREF` to observe GIL assertion
+failures in absence of this patch.
+---
+ src/_hmmc.cpp | 111 ++++++++++++++++++++++++++------------------------
+ 1 file changed, 58 insertions(+), 53 deletions(-)
--- python-hmmlearn.orig/src/_hmmc.cpp
+++ python-hmmlearn/src/_hmmc.cpp
-@@ -1,3 +1,4 @@
-+#define PYBIND11_NO_ASSERT_GIL_HELD_INCREF_DECREF
- #include <pybind11/pybind11.h>
- #include <pybind11/numpy.h>
- #include <cfenv>
+@@ -63,37 +63,39 @@
+ auto scaling_ = py::array_t<double>{{ns}};
+ auto scaling = scaling_.mutable_unchecked<1>();
+ auto log_prob = 0.;
+- py::gil_scoped_release nogil;
+- std::fill_n(fwd.mutable_data(0, 0), fwd.size(), 0);
+- for (auto i = 0; i < nc; ++i) {
+- fwd(0, i) = startprob(i) * frameprob(0, i);
+- }
+- auto sum = std::accumulate(&fwd(0, 0), &fwd(0, nc), 0.);
+- if (sum < min_sum) {
+- throw std::range_error{"forward pass failed with underflow; "
+- "consider using implementation='log' instead"};
+- }
+- auto scale = scaling(0) = 1. / sum;
+- log_prob -= std::log(scale);
+- for (auto i = 0; i < nc; ++i) {
+- fwd(0, i) *= scale;
+- }
+- for (auto t = 1; t < ns; ++t) {
+- for (auto j = 0; j < nc; ++j) {
+- for (auto i = 0; i < nc; ++i) {
+- fwd(t, j) += fwd(t - 1, i) * transmat(i, j);
+- }
+- fwd(t, j) *= frameprob(t, j);
++ {
++ py::gil_scoped_release nogil;
++ std::fill_n(fwd.mutable_data(0, 0), fwd.size(), 0);
++ for (auto i = 0; i < nc; ++i) {
++ fwd(0, i) = startprob(i) * frameprob(0, i);
+ }
+- auto sum = std::accumulate(&fwd(t, 0), &fwd(t, nc), 0.);
++ auto sum = std::accumulate(&fwd(0, 0), &fwd(0, nc), 0.);
+ if (sum < min_sum) {
+ throw std::range_error{"forward pass failed with underflow; "
+ "consider using implementation='log' instead"};
+ }
+- auto scale = scaling(t) = 1. / sum;
++ auto scale = scaling(0) = 1. / sum;
+ log_prob -= std::log(scale);
+- for (auto j = 0; j < nc; ++j) {
+- fwd(t, j) *= scale;
++ for (auto i = 0; i < nc; ++i) {
++ fwd(0, i) *= scale;
++ }
++ for (auto t = 1; t < ns; ++t) {
++ for (auto j = 0; j < nc; ++j) {
++ for (auto i = 0; i < nc; ++i) {
++ fwd(t, j) += fwd(t - 1, i) * transmat(i, j);
++ }
++ fwd(t, j) *= frameprob(t, j);
++ }
++ auto sum = std::accumulate(&fwd(t, 0), &fwd(t, nc), 0.);
++ if (sum < min_sum) {
++ throw std::range_error{"forward pass failed with underflow; "
++ "consider using implementation='log' instead"};
++ }
++ auto scale = scaling(t) = 1. / sum;
++ log_prob -= std::log(scale);
++ for (auto j = 0; j < nc; ++j) {
++ fwd(t, j) *= scale;
++ }
+ }
+ }
+ return {log_prob, fwdlattice_, scaling_};
+@@ -117,16 +119,18 @@
+ auto buf = std::vector<double>(nc);
+ auto fwdlattice_ = py::array_t<double>{{ns, nc}};
+ auto fwd = fwdlattice_.mutable_unchecked<2>();
+- py::gil_scoped_release nogil;
+- for (auto i = 0; i < nc; ++i) {
+- fwd(0, i) = log_startprob(i) + log_frameprob(0, i);
+- }
+- for (auto t = 1; t < ns; ++t) {
+- for (auto j = 0; j < nc; ++j) {
+- for (auto i = 0; i < nc; ++i) {
+- buf[i] = fwd(t - 1, i) + log_transmat(i, j);
++ {
++ py::gil_scoped_release nogil;
++ for (auto i = 0; i < nc; ++i) {
++ fwd(0, i) = log_startprob(i) + log_frameprob(0, i);
++ }
++ for (auto t = 1; t < ns; ++t) {
++ for (auto j = 0; j < nc; ++j) {
++ for (auto i = 0; i < nc; ++i) {
++ buf[i] = fwd(t - 1, i) + log_transmat(i, j);
++ }
++ fwd(t, j) = logsumexp(buf.data(), nc) + log_frameprob(t, j);
+ }
+- fwd(t, j) = logsumexp(buf.data(), nc) + log_frameprob(t, j);
+ }
+ }
+ auto log_prob = logsumexp(&fwd(ns - 1, 0), nc);
+@@ -290,30 +294,31 @@
+ auto viterbi_lattice_ = py::array_t<double>{{ns, nc}};
+ auto state_sequence = state_sequence_.mutable_unchecked<1>();
+ auto viterbi_lattice = viterbi_lattice_.mutable_unchecked<2>();
+- py::gil_scoped_release nogil;
+- for (auto i = 0; i < nc; ++i) {
+- viterbi_lattice(0, i) = log_startprob(i) + log_frameprob(0, i);
+- }
+- for (auto t = 1; t < ns; ++t) {
++ {
++ py::gil_scoped_release nogil;
+ for (auto i = 0; i < nc; ++i) {
+- auto max = -std::numeric_limits<double>::infinity();
+- for (auto j = 0; j < nc; ++j) {
+- max = std::max(max, viterbi_lattice(t - 1, j) + log_transmat(j, i));
++ viterbi_lattice(0, i) = log_startprob(i) + log_frameprob(0, i);
++ }
++ for (auto t = 1; t < ns; ++t) {
++ for (auto i = 0; i < nc; ++i) {
++ auto max = -std::numeric_limits<double>::infinity();
++ for (auto j = 0; j < nc; ++j) {
++ max = std::max(max, viterbi_lattice(t - 1, j) + log_transmat(j, i));
++ }
++ viterbi_lattice(t, i) = max + log_frameprob(t, i);
+ }
+- viterbi_lattice(t, i) = max + log_frameprob(t, i);
+ }
+- }
+- auto row = &viterbi_lattice(ns - 1, 0);
+- auto prev = state_sequence(ns - 1) = std::max_element(row, row + nc) - row;
+- auto log_prob = row[prev];
+- for (auto t = ns - 2; t >= 0; --t) {
+- auto max = std::make_pair(-std::numeric_limits<double>::infinity(), 0);
+- for (auto i = 0; i < nc; ++i) {
+- max = std::max(max, {viterbi_lattice(t, i) + log_transmat(i, prev), i});
++ auto row = &viterbi_lattice(ns - 1, 0);
++ auto prev = state_sequence(ns - 1) = std::max_element(row, row + nc) - row;
++ for (auto t = ns - 2; t >= 0; --t) {
++ auto max = std::make_pair(-std::numeric_limits<double>::infinity(), 0);
++ for (auto i = 0; i < nc; ++i) {
++ max = std::max(max, {viterbi_lattice(t, i) + log_transmat(i, prev), i});
++ }
++ state_sequence(t) = prev = max.second;
+ }
+- state_sequence(t) = prev = max.second;
+ }
+- return {log_prob, state_sequence_};
++ return {viterbi_lattice(ns - 1, state_sequence(ns - 1)), state_sequence_};
+ }
+
+ PYBIND11_MODULE(_hmmc, m) {
View it on GitLab: https://salsa.debian.org/med-team/python-hmmlearn/-/compare/25a3b7382fefa24967c498427535b162121cd91a...7fbe6a149579bf7e8f3dd7370a6f363dda16dcee
--
View it on GitLab: https://salsa.debian.org/med-team/python-hmmlearn/-/compare/25a3b7382fefa24967c498427535b162121cd91a...7fbe6a149579bf7e8f3dd7370a6f363dda16dcee
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20241007/0e4214b3/attachment-0001.htm>
More information about the debian-med-commit
mailing list