Repository: lisa-lab/pylearn2

Issue:
FilterActs in unshared_conv.py might use non-contiguous array when calculating grad
In unshared_conv.py under theano_linear/unshared_conv
the calculation of gradient in FilterActs will make use of ImgActs, WeightActs.
Both ImgActs and WeightActs requires that the input is C-contiguous. However, it is not guaranteed in FilterActs.grad().

When I use FilterActs, I met with exceptions when calculating gradient, where ImgActs complains that 'hidacts' is not C-contiguous.
One possible work-around is to add two lines in FilterActs.grad() before instantiating ImgActs and WeightActs:

``` python
from theano.sandbox.cuda.basic_ops import gpu_contiguous
hidacts = gpu_contiguous(hidacts)
```

But this solution doesn't look nice. And it seems that gpu_contiguous only work with float32.
Thanks.



Discussion:
I think this is the good solution. The current Theano back-end only support
float32 everywhere. This isn't particular to gpu_contiguous.

Do you want to make a PR with the fix? That way, the history will show your
contribution.

Otherwise, we can make it.

thanks

On Mon, Nov 10, 2014 at 7:59 AM, Yuxin Wu notifications@github.com wrote:

> In unshared_conv.py under theano_linear/unshared_conv
> the calculation of gradient in FilterActs will make use of ImgActs,
> WeightActs.
> Both ImgActs and WeightActs requires that the input is C-contiguous.
> However, it is not guaranteed in FilterActs.grad().
> 
> When I use FilterActs, I met with exceptions when calculating gradient,
> where ImgActs complains that 'hidacts' is not C-contiguous.
> One possible work-around is to add two lines in FilterActs.grad() before
> instantiating ImgActs and WeightActs:
> 
> from theano.sandbox.cuda.basic_ops import gpu_contiguous
> hidacts = gpu_contiguous(hidacts)
> 
> But this solution doesn't look nice. And it seems that gpu_contiguous only
> work with float32.
> Thanks.
> 
> —
> Reply to this email directly or view it on GitHub
> https://github.com/lisa-lab/pylearn2/issues/1220.


Resolving patch:
diff --git a/pylearn2/packaged_dependencies/theano_linear/unshared_conv/gpu_unshared_conv.py b/pylearn2/packaged_dependencies/theano_linear/unshared_conv/gpu_unshared_conv.py
--- a/pylearn2/packaged_dependencies/theano_linear/unshared_conv/gpu_unshared_conv.py
+++ b/pylearn2/packaged_dependencies/theano_linear/unshared_conv/gpu_unshared_conv.py
@@ -10,6 +10,7 @@
 from theano.gof import local_optimizer
 from theano.sandbox.cuda.opt import register_opt
 from theano.sandbox.cuda import gpu_from_host, host_from_gpu
+from theano.sandbox.cuda.basic_ops import gpu_contiguous
 
 from .unshared_conv import FilterActs
 from .unshared_conv import WeightActs
@@ -546,7 +547,7 @@ def insert_gpu_weight_acts(node):
                     partial_sum=1)
             return [host_from_gpu(gpu_weight_acts(
                 gpu_from_host(images),
-                gpu_from_host(hidacts),
+                gpu_contiguous(hidacts),
                 frows,
                 fcols,
                 ))]
@@ -784,7 +785,7 @@ def insert_gpu_img_acts(node):
                     partial_sum=1)
             return [host_from_gpu(gpu_img_acts(
                 gpu_from_host(filters),
-                gpu_from_host(hidacts),
+                gpu_contiguous(hidacts),
                 irows,
                 icols,
                 ))]
diff --git a/pylearn2/packaged_dependencies/theano_linear/unshared_conv/unshared_conv.py b/pylearn2/packaged_dependencies/theano_linear/unshared_conv/unshared_conv.py
--- a/pylearn2/packaged_dependencies/theano_linear/unshared_conv/unshared_conv.py
+++ b/pylearn2/packaged_dependencies/theano_linear/unshared_conv/unshared_conv.py
@@ -122,7 +122,7 @@ def perform(self, node, iargs, ostor):
                             raise
                     hidacts[gg, :, mR, mC, :] = rc_hidacts
         ostor[0][0] = hidacts
-        
+
         print_sizes = 0
         if print_sizes:
             print 'FilterActs shapes: images', images.shape


Test patch: