Repository: chainer/chainer

Issue:
Check availability of CUDA
Chainer only checks existence of dependent libraries. When these libraries are old and don't satisfy requirements of cuda environment, they cause serious errors.
We need to check versions of dependent libraries and show errors when `cuda` is imported.



Discussion:
With `pkg_resouces` we can easily check version of the required libraries.

http://pythonhosted.org/setuptools/pkg_resources.html#workingset-objects


Resolving patch:
diff --git a/chainer/cuda.py b/chainer/cuda.py
--- a/chainer/cuda.py
+++ b/chainer/cuda.py
@@ -36,9 +36,18 @@
 import os
 
 import numpy
+import pkg_resources
 import six
 
 try:
+    _requires = [
+        'pycuda>=2014.1',
+        'scikits.cuda>=0.5.0b2,!=0.042',
+        'Mako',
+        'six>=1.9.0',
+    ]
+    pkg_resources.require(_requires)
+
     import pycuda.cumath
     import pycuda.curandom
     import pycuda.driver as drv
@@ -58,9 +67,9 @@
     cumisc = scikits.cuda.misc
     cutools = pycuda.tools
     gpuarray = pycuda.gpuarray
-except ImportError as e:
+except pkg_resources.ResolutionError as e:
     available = False
-    _import_error = e
+    _resolution_error = e
 
 # ------------------------------------------------------------------------------
 # Basic types
@@ -131,10 +140,20 @@ def init(device=None):
     global _contexts, _cublas_handles, _generators, _pid, _pools
 
     if not available:
-        global _import_error
-        raise RuntimeError(
-            'CUDA environment is not correctly set up. ' +
-            'The original import error said: ' + str(_import_error))
+        global _resolution_error
+        msg = '''CUDA environment is not correctly set up.
+Use `pip install -U chainer-cuda-deps` to install libraries.
+'''
+
+        # Note that error message depends on its type
+        if isinstance(_resolution_error, pkg_resources.DistributionNotFound):
+            msg += 'Required package is not found: ' + str(_resolution_error)
+        elif isinstance(_resolution_error, pkg_resources.VersionConflict):
+            msg += 'Version conflict: ' + str(_resolution_error)
+        else:
+            msg += 'Unknwon error: ' + str(_resolution_error)
+
+        raise RuntimeError(msg)
 
     pid = os.getpid()
     if _pid == pid:  # already initialized


Test patch:
diff --git a/tests/test_cuda.py b/tests/test_cuda.py
new file mode 100644
--- /dev/null
+++ b/tests/test_cuda.py
@@ -0,0 +1,36 @@
+import os
+import re
+import unittest
+
+from chainer import cuda
+
+if cuda.available:
+    cuda.init()
+
+
+class TestCuda(unittest.TestCase):
+
+    def _get_cuda_deps_requires(self):
+        cwd = os.path.dirname(__file__)
+
+        cuda_deps_path = os.path.join(cwd, '..', 'cuda_deps', 'setup.py')
+        with open(cuda_deps_path) as f:
+            in_require = False
+            requires = []
+            for line in f:
+                if in_require:
+                    if ']' in line:
+                        in_require = False
+                    else:
+                        m = re.search(r'\'(.*)\',', line)
+                        requires.append(m.group(1))
+                else:
+                    if 'install_requires' in line:
+                        in_require = True
+
+        return requires
+
+    def test_requires(self):
+        requires = self._get_cuda_deps_requires()
+        self.assertSetEqual(set(['chainer'] + cuda._requires),
+                            set(requires))