Repository: Theano/Theano

Issue:
test MRG random stream with device=cuda and target=cpu, shared variable + computation in a real model stay on CPU.
test MRG random stream with device=cuda and target=cpu, shared variable + computation in a real model stay on CPU.

Other stuff like the back-ward optimization pass could move the computation to the GPU. Maybe it should be used in combination to a `optimizer_excluding=...` flag to do exactly what we want.

Test it manually and after we should also make a real theano tests under gpuarray.


Discussion:

Resolving patch:
diff --git a/theano/gpuarray/dnn.py b/theano/gpuarray/dnn.py
--- a/theano/gpuarray/dnn.py
+++ b/theano/gpuarray/dnn.py
@@ -119,7 +119,8 @@ def _make_handle(ctx):
     with ctx:
         err = cudnn.cudnnCreate(ctypes.byref(handle))
     if err != 0:
-        raise RuntimeError("error creating cudnn handle")
+        raise RuntimeError("Error creating cudnn handle. "
+                           "This can be a sign of a too old driver.", err)
     return handle
 
 
diff --git a/theano/gpuarray/rng_mrg.py b/theano/gpuarray/rng_mrg.py
--- a/theano/gpuarray/rng_mrg.py
+++ b/theano/gpuarray/rng_mrg.py
@@ -14,7 +14,7 @@
 from theano.scalar import int32 as int_t
 
 from .basic_ops import (GpuKernelBase, Kernel, infer_context_name,
-                        host_from_gpu, as_gpuarray_variable)
+                        GpuFromHost, host_from_gpu, as_gpuarray_variable)
 from .type import GpuArrayType, gpu_context_type
 from .fp16_help import write_w
 from .opt import register_opt, register_opt2
@@ -309,7 +309,10 @@ def c_code_cache_version(self):
 @register_opt2([mrg_uniform], 'fast_compile')
 def local_gpua_mrg_graph(op, context_name, inputs, outputs):
     if (type(op) == mrg_uniform and
-            isinstance(inputs[0].type, GpuArrayType)):
+            isinstance(inputs[0].type, GpuArrayType) and
+            (inputs[0].owner is None or
+             not isinstance(inputs[0].owner.op,
+                            GpuFromHost))):
         outs = GPUA_mrg_uniform.new(inputs[0],
                                     op.output_type.ndim,
                                     op.output_type.dtype,


Test patch:
diff --git a/theano/gpuarray/tests/config.py b/theano/gpuarray/tests/config.py
--- a/theano/gpuarray/tests/config.py
+++ b/theano/gpuarray/tests/config.py
@@ -7,15 +7,20 @@
 if theano.gpuarray.pygpu is None:
     raise SkipTest("pygpu not installed")
 
+
+init_error = None
 if (not theano.gpuarray.pygpu_activated and
         not theano.config.force_device):
     try:
         theano.gpuarray.init_dev('cuda')
-    except Exception:
-        pass
+    except Exception as e:
+        init_error = e
 
 if not theano.gpuarray.pygpu_activated:
-    raise SkipTest("pygpu disabled")
+    if init_error:
+        raise SkipTest(init_error)
+    else:
+        raise SkipTest("pygpu disabled")
 
 test_ctx_name = None
 
diff --git a/theano/gpuarray/tests/test_rng_mrg.py b/theano/gpuarray/tests/test_rng_mrg.py
--- a/theano/gpuarray/tests/test_rng_mrg.py
+++ b/theano/gpuarray/tests/test_rng_mrg.py
@@ -165,4 +165,31 @@ def test_validate_input_types_gpuarray_backend():
 
 
 def test_f16_nonzero():
-    cpu_f16_nonzero(mode=mode, op_to_check=GPUA_mrg_uniform)
+    try:
+        # To have theano.shared(x) try to move on the GPU
+        theano.compile.shared_constructor(gpuarray_shared_constructor)
+        cpu_f16_nonzero(mode=mode, op_to_check=GPUA_mrg_uniform)
+    finally:
+        theano.compile.shared_constructor(gpuarray_shared_constructor,
+                                          remove=True)
+
+
+def test_cpu_target_with_shared_variable():
+    srng = MRG_RandomStreams()
+    s = np.random.rand(2, 3).astype('float32')
+    x = gpuarray_shared_constructor(s, name='x')
+    try:
+        # To have theano.shared(x) try to move on the GPU
+        theano.compile.shared_constructor(gpuarray_shared_constructor)
+        y = srng.uniform(x.shape, target='cpu')
+        y.name = 'y'
+        z = (x * y).sum()
+        z.name = 'z'
+
+        fz = theano.function([], z, mode=mode)
+
+        nodes = fz.maker.fgraph.toposort()
+        assert not any([isinstance(node.op, GPUA_mrg_uniform) for node in nodes])
+    finally:
+        theano.compile.shared_constructor(gpuarray_shared_constructor,
+                                          remove=True)
diff --git a/theano/sandbox/tests/test_rng_mrg.py b/theano/sandbox/tests/test_rng_mrg.py
--- a/theano/sandbox/tests/test_rng_mrg.py
+++ b/theano/sandbox/tests/test_rng_mrg.py
@@ -740,7 +740,8 @@ def test_f16_nonzero(mode=None, op_to_check=rng_mrg.mrg_uniform):
     m = srng.uniform(size=(1000, 1000), dtype='float16')
     assert m.dtype == 'float16', m.type
     f = theano.function([], m, mode=mode)
-    assert any(isinstance(n.op, op_to_check) for n in f.maker.fgraph.apply_nodes)
+    assert any(isinstance(n.op, op_to_check)
+               for n in f.maker.fgraph.apply_nodes)
     m_val = f()
     assert np.all((0 < m_val) & (m_val < 1))