diff --git a/elephant/asset/asset.py b/elephant/asset/asset.py index 7a28089b5..7382718ba 100644 --- a/elephant/asset/asset.py +++ b/elephant/asset/asset.py @@ -136,7 +136,7 @@ import elephant.conversion as conv from elephant import spike_train_surrogates -from elephant.utils import get_cuda_capability_major +from elephant.utils import get_cuda_capability_major, get_opencl_capability try: from mpi4py import MPI @@ -513,9 +513,11 @@ def _choose_backend(self): use_cuda = int(os.getenv("ELEPHANT_USE_CUDA", '1')) use_opencl = int(os.getenv("ELEPHANT_USE_OPENCL", '1')) cuda_detected = get_cuda_capability_major() != 0 + opencl_detected = get_opencl_capability() + if use_cuda and cuda_detected: return self.pycuda - if use_opencl: + if use_opencl and opencl_detected: return self.pyopencl return self.cpu diff --git a/elephant/test/test_asset.py b/elephant/test/test_asset.py index 0962c5844..9a1f00f5a 100644 --- a/elephant/test/test_asset.py +++ b/elephant/test/test_asset.py @@ -33,7 +33,7 @@ try: import pyopencl - HAVE_PYOPENCL = True + HAVE_PYOPENCL = asset.get_opencl_capability() except ImportError: HAVE_PYOPENCL = False @@ -393,6 +393,39 @@ def test_intersection_matrix(self): spiketrains_i=[st1, st2], bin_size=bin_size, t_stop_j=5 * pq.ms) + # regression test Issue #481 + # see: https://github.com/NeuralEnsemble/elephant/issues/481 + def test_asset_choose_backend_opencl(self): + class TestClassBackend(asset._GPUBackend): + + def __init__(self): + super().__init__() + self.backend = self._choose_backend() + + def cpu(self): + return "cpu" + + def pycuda(self): + return "cuda" + + def pyopencl(self): + return "opencl" + + # check which backend is chosen if environment variable for opencl + # is not set + os.environ.pop('ELEPHANT_USE_OPENCL', None) + # create object of TestClass + backend_obj = TestClassBackend() + + if HAVE_PYOPENCL: + self.assertEqual(backend_obj.backend(), 'opencl') + else: + # if environment variable is not set and no module pyopencl or + # device is found: choose cpu backend + self.assertEqual(backend_obj.backend(), 'cpu') + + os.environ['ELEPHANT_USE_OPENCL'] = '0' + @unittest.skipUnless(HAVE_SKLEARN, 'requires sklearn') class TestJSFUniformOrderStat3D(unittest.TestCase): diff --git a/elephant/utils.py b/elephant/utils.py index 3ce1e9206..f634a570a 100644 --- a/elephant/utils.py +++ b/elephant/utils.py @@ -340,3 +340,25 @@ def get_cuda_capability_major(): ctypes.byref(cc_minor), device) return cc_major.value + + +def get_opencl_capability(): + """ + Return a list of available OpenCL devices. + + Returns + ------- + bool + True: if openCL platform detected and at least one device is found, + False: if OpenCL is not found or if no OpenCL devices are found + """ + try: + import pyopencl + platforms = pyopencl.get_platforms() + + if len(platforms) == 0: + return False + # len(platforms) is > 0, if it is not == 0 + return True + except ImportError: + return False