fix: dev: cython import errors

This commit fixes issues observed in Windows where some
cython modules are successfully imported, and some are not.
This causes the global config cython.working to be inconsistent,
which causes import errors when unavailable cython modules
are tried to be imported (example
https://github.com/SheffieldML/GPy/issues/266). This commit uses
a separate flag for each module to fix the issue.
This commit is contained in:
Jayanth Koushik 2017-10-23 15:58:17 -04:00
parent 754c67f71d
commit a7af12e6ea
5 changed files with 32 additions and 21 deletions

View file

@ -6,11 +6,14 @@ import numpy as np
from ...core.parameterization import Param from ...core.parameterization import Param
from paramz.transformations import Logexp from paramz.transformations import Logexp
from ...util.config import config # for assesing whether to use cython from ...util.config import config # for assesing whether to use cython
try: try:
from . import coregionalize_cython from . import coregionalize_cython
config.set('cython', 'working', 'True') cython_coregionalize_working = True
except ImportError: except ImportError:
config.set('cython', 'working', 'False') print('warning in coregionalize: failed to import cython module: falling back to numpy')
cython_coregionalize_working = False
class Coregionalize(Kern): class Coregionalize(Kern):
""" """
@ -61,7 +64,7 @@ class Coregionalize(Kern):
self.B = np.dot(self.W, self.W.T) + np.diag(self.kappa) self.B = np.dot(self.W, self.W.T) + np.diag(self.kappa)
def K(self, X, X2=None): def K(self, X, X2=None):
if config.getboolean('cython', 'working'): if cython_coregionalize_working and config.getboolean('cython', 'working'):
return self._K_cython(X, X2) return self._K_cython(X, X2)
else: else:
return self._K_numpy(X, X2) return self._K_numpy(X, X2)
@ -92,7 +95,7 @@ class Coregionalize(Kern):
index2 = np.asarray(X2, dtype=np.int) index2 = np.asarray(X2, dtype=np.int)
#attempt to use cython for a nasty double indexing loop: fall back to numpy #attempt to use cython for a nasty double indexing loop: fall back to numpy
if config.getboolean('cython', 'working'): if cython_coregionalize_working and config.getboolean('cython', 'working'):
dL_dK_small = self._gradient_reduce_cython(dL_dK, index, index2) dL_dK_small = self._gradient_reduce_cython(dL_dK, index, index2)
else: else:
dL_dK_small = self._gradient_reduce_numpy(dL_dK, index, index2) dL_dK_small = self._gradient_reduce_numpy(dL_dK, index, index2)

View file

@ -14,9 +14,10 @@ from paramz.transformations import Logexp
try: try:
from . import stationary_cython from . import stationary_cython
cython_stationary_working = True
except ImportError: except ImportError:
print('warning in stationary: failed to import cython module: falling back to numpy') print('warning in stationary: failed to import cython module: falling back to numpy')
config.set('cython', 'working', 'false') cython_stationary_working = False
class Stationary(Kern): class Stationary(Kern):
@ -196,7 +197,7 @@ class Stationary(Kern):
tmp = dL_dr*self._inv_dist(X, X2) tmp = dL_dr*self._inv_dist(X, X2)
if X2 is None: X2 = X if X2 is None: X2 = X
if config.getboolean('cython', 'working'): if cython_stationary_working and config.getboolean('cython', 'working'):
self.lengthscale.gradient = self._lengthscale_grads_cython(tmp, X, X2) self.lengthscale.gradient = self._lengthscale_grads_cython(tmp, X, X2)
else: else:
self.lengthscale.gradient = self._lengthscale_grads_pure(tmp, X, X2) self.lengthscale.gradient = self._lengthscale_grads_pure(tmp, X, X2)
@ -239,7 +240,7 @@ class Stationary(Kern):
""" """
Given the derivative of the objective wrt K (dL_dK), compute the derivative wrt X Given the derivative of the objective wrt K (dL_dK), compute the derivative wrt X
""" """
if config.getboolean('cython', 'working'): if cython_stationary_working and config.getboolean('cython', 'working'):
return self._gradients_X_cython(dL_dK, X, X2) return self._gradients_X_cython(dL_dK, X, X2)
else: else:
return self._gradients_X_pure(dL_dK, X, X2) return self._gradients_X_pure(dL_dK, X, X2)

View file

@ -2,21 +2,25 @@ import numpy as np
import scipy as sp import scipy as sp
from GPy.util import choleskies from GPy.util import choleskies
import GPy import GPy
from ..util.config import config
import unittest import unittest
try: try:
from ..util import linalg_cython
from ..util import choleskies_cython from ..util import choleskies_cython
config.set('cython', 'working', 'True') choleskies_cython_working = True
except ImportError: except ImportError:
config.set('cython', 'working', 'False') choleskies_cython_working = False
try:
from ..kern.src import stationary_cython
stationary_cython_working = True
except ImportError:
stationary_cython_working = False
""" """
These tests make sure that the pure python and cython codes work the same These tests make sure that the pure python and cython codes work the same
""" """
@unittest.skipIf(not config.getboolean('cython', 'working'),"Cython modules have not been built on this machine") @unittest.skipIf(not choleskies_cython_working,"Cython cholesky module has not been built on this machine")
class CythonTestChols(np.testing.TestCase): class CythonTestChols(np.testing.TestCase):
def setUp(self): def setUp(self):
self.flat = np.random.randn(45,5) self.flat = np.random.randn(45,5)
@ -30,7 +34,7 @@ class CythonTestChols(np.testing.TestCase):
A2 = choleskies._triang_to_flat_cython(self.triang) A2 = choleskies._triang_to_flat_cython(self.triang)
np.testing.assert_allclose(A1, A2) np.testing.assert_allclose(A1, A2)
@unittest.skipIf(not config.getboolean('cython', 'working'),"Cython modules have not been built on this machine") @unittest.skipIf(not stationary_cython_working,"Cython stationary module has not been built on this machine")
class test_stationary(np.testing.TestCase): class test_stationary(np.testing.TestCase):
def setUp(self): def setUp(self):
self.k = GPy.kern.RBF(10) self.k = GPy.kern.RBF(10)
@ -60,7 +64,7 @@ class test_stationary(np.testing.TestCase):
g2 = self.k._lengthscale_grads_cython(self.dKxz, self.X, self.Z) g2 = self.k._lengthscale_grads_cython(self.dKxz, self.X, self.Z)
np.testing.assert_allclose(g1, g2) np.testing.assert_allclose(g1, g2)
@unittest.skipIf(not config.getboolean('cython', 'working'),"Cython modules have not been built on this machine") @unittest.skipIf(not choleskies_cython_working,"Cython cholesky module has not been built on this machine")
class test_choleskies_backprop(np.testing.TestCase): class test_choleskies_backprop(np.testing.TestCase):
def setUp(self): def setUp(self):
a =np.random.randn(10,12) a =np.random.randn(10,12)

View file

@ -14,10 +14,10 @@ from ..util.config import config
verbose = 0 verbose = 0
try: try:
from ..util import linalg_cython from ..util import choleskies_cython
config.set('cython', 'working', 'True') cython_choleskies_working = True
except ImportError: except ImportError:
config.set('cython', 'working', 'False') cython_choleskies_working = False
class Kern_check_model(GPy.core.Model): class Kern_check_model(GPy.core.Model):
@ -618,7 +618,7 @@ class KernelTestsNonContinuous(unittest.TestCase):
kern = GPy.kern.Coregionalize(1, output_dim=3, active_dims=[-1]) kern = GPy.kern.Coregionalize(1, output_dim=3, active_dims=[-1])
self.assertTrue(check_kernel_gradient_functions(kern, X=self.X, X2=self.X2, verbose=verbose, fixed_X_dims=-1)) self.assertTrue(check_kernel_gradient_functions(kern, X=self.X, X2=self.X2, verbose=verbose, fixed_X_dims=-1))
@unittest.skipIf(not config.getboolean('cython', 'working'),"Cython modules have not been built on this machine") @unittest.skipIf(not cython_choleskies_working,"Cython choleskies module has not been built on this machine")
class Coregionalize_cython_test(unittest.TestCase): class Coregionalize_cython_test(unittest.TestCase):
""" """
Make sure that the coregionalize kernel work with and without cython enabled Make sure that the coregionalize kernel work with and without cython enabled

View file

@ -4,11 +4,14 @@
import numpy as np import numpy as np
from . import linalg from . import linalg
from .config import config from .config import config
try: try:
from . import choleskies_cython from . import choleskies_cython
config.set('cython', 'working', 'True') cython_choleskies_working = True
except ImportError: except ImportError:
config.set('cython', 'working', 'False') print('warning in choleskies: failed to import cython module: falling back to numpy')
cython_choleskies_working = False
def safe_root(N): def safe_root(N):
i = np.sqrt(N) i = np.sqrt(N)
@ -100,7 +103,7 @@ def indexes_to_fix_for_low_rank(rank, size):
return np.setdiff1d(np.arange((size**2+size)/2), keep) return np.setdiff1d(np.arange((size**2+size)/2), keep)
if config.getboolean('cython', 'working'): if cython_choleskies_working and config.getboolean('cython', 'working'):
triang_to_flat = _triang_to_flat_cython triang_to_flat = _triang_to_flat_cython
flat_to_triang = _flat_to_triang_cython flat_to_triang = _flat_to_triang_cython
backprop_gradient = choleskies_cython.backprop_gradient_par_c backprop_gradient = choleskies_cython.backprop_gradient_par_c