Repository: Theano/Theano

Issue:
Slicing within tensordot
Hi,

I noticed a weird result using slicing within tensordot. The following code shows how slicing in a call to theano.tensor.tensordot produces a different result from slicing in a call to a function mapping inputs to the result of theano.tensor.tensortdot.

The second value seems to be right since numpy.tensordot produces the same result.

I checked the `t[..., 0]` syntax (t being a theano tensor) which seems to work properly. 

```
import numpy as np
import theano
import theano.tensor as T

floatX = theano.config.floatX

a1 = T.matrix(dtype=floatX)
b1 = T.tensor3(dtype=floatX)
c1 = T.tensordot(a1, b1[..., 0])

testFunc1 = theano.function([a1, b1], c1)

a2 = T.matrix(dtype=floatX)
b2 = T.matrix(dtype=floatX)
c2 = T.tensordot(a2, b2)

testFunc2 = theano.function([a2, b2], c2)

mat = np.random.random((3, 3)).astype(floatX)
tensor = np.random.random((3, 3, 2)).astype(floatX)

print(testFunc1(mat, tensor)) # slicing in call to theano.tensor.tensordot
print(testFunc2(mat, tensor[..., 0])) # slicing in call to theano function
print(np.tensordot(mat, tensor[..., 0])) # slicing in call to numpy.tensordot
print(np.tensordot(mat, tensor)[0]) # no slicing with numpy.tensordot
```

(This result was obtained using theano 0.9)


Discussion:
It seems to work for me with the latest master:
```
1.94397006514
1.94397006514
1.94397006514
1.94397006514
```
Could you try to update to the development version from GitHub?
Actually, I have an issue with `device=cuda,floatX=float32`:
```
Using cuDNN version 6021 on context None
Mapped name None to device cuda: GeForce GTX 750 Ti (0000:01:00.0)
-1.25619448681e+38
3.36419057846
3.36419057846
3.36419
```

Resolving patch:
diff --git a/theano/gpuarray/blas.py b/theano/gpuarray/blas.py
--- a/theano/gpuarray/blas.py
+++ b/theano/gpuarray/blas.py
@@ -120,16 +120,12 @@ def c_code(self, node, name, inp, out, sub):
             %(out)s->ga.nd = 0;
             %(A)s->ga.nd = 1;
             %(A)s->ga.dimensions[0] = %(A)s->ga.dimensions[1];
-            if (%(A)s->ga.flags & GA_C_CONTIGUOUS) {
-                ssize_t a_stride0 = %(A)s->ga.strides[0];
-                %(A)s->ga.strides[0] = %(A)s->ga.strides[1];
-                if (pygpu_blas_rdot(%(x)s, %(A)s, %(out)s, 0) == -1) {
-                    %(fail)s
-                }
-                %(A)s->ga.strides[0] = a_stride0;
-            } else if (pygpu_blas_rdot(%(x)s, %(A)s, %(out)s, 0) == -1) {
+            ssize_t a_stride0 = %(A)s->ga.strides[0];
+            %(A)s->ga.strides[0] = %(A)s->ga.strides[1];
+            if (pygpu_blas_rdot(%(x)s, %(A)s, %(out)s, 0) == -1) {
                 %(fail)s
             }
+            %(A)s->ga.strides[0] = a_stride0;
             %(out)s->ga.nd = 1;
             %(A)s->ga.nd = 2;
             %(A)s->ga.dimensions[0] = 1;
@@ -149,7 +145,7 @@ def c_code(self, node, name, inp, out, sub):
         return code
 
     def c_code_cache_version(self):
-        return (7,)
+        return (8,)
 
 gpugemv_no_inplace = GpuGemv(inplace=False)
 gpugemv_inplace = GpuGemv(inplace=True)


Test patch:
diff --git a/theano/gpuarray/tests/test_blas.py b/theano/gpuarray/tests/test_blas.py
--- a/theano/gpuarray/tests/test_blas.py
+++ b/theano/gpuarray/tests/test_blas.py
@@ -234,3 +234,14 @@ def test_gemv_zeros():
     tmp = f(A, b)
     assert np.allclose(tmp,
                        np.zeros((dim,)))
+
+
+def test_gemv_dot_strides():
+    # Reported in https://github.com/Theano/Theano/issues/6142
+    xv = rand(5)
+    yv = rand(5, 1)
+    x = gpuarray_shared_constructor(xv)
+    y = gpuarray_shared_constructor(yv, broadcastable=(False, True))
+    f = theano.function([], tensor.dot(x, y[::-1]), mode=mode_with_gpu)
+    out = f()
+    utt.assert_allclose(out, np.dot(xv, yv[::-1]))