Repository: chainer/chainer

Issue:
xxx_pooling_nd fails with CUDNN_STATUS_NOT_SUPPORTED when spatial dimensions>3 and using cuDNN
### Code
```
import chainer
import numpy
import cupy

x_shape = (1, 1, 1, 1, 1, 1)
x = cupy.ones(x_shape, dtype=numpy.float32)
y = chainer.functions.max_pooling_nd(x, ksize=1, stride=1, pad=0)
```

### Result
```
Traceback (most recent call last):
  File "test-cudnn.py", line 8, in <module>
    y = chainer.functions.max_pooling_nd(x, ksize=1, stride=1, pad=0)
  File "/data/work/w/repos/chainer/chainer/functions/pooling/max_pooling_nd.py", line 148, in max_pooling_nd
    return MaxPoolingND(ndim, ksize, stride, pad, cover_all)(x)
  File "/data/work/w/repos/chainer/chainer/function.py", line 212, in __call__
    ret = node.apply(inputs)
  File "/data/work/w/repos/chainer/chainer/function_node.py", line 223, in apply
    outputs = self.forward(in_data)
  File "/data/work/w/repos/chainer/chainer/function.py", line 117, in forward
    return self._function.forward(inputs)
  File "/data/work/w/repos/chainer/chainer/function.py", line 319, in forward
    return self.forward_gpu(inputs)
  File "/data/work/w/repos/chainer/chainer/functions/pooling/max_pooling_nd.py", line 50, in forward_gpu
    return super(MaxPoolingND, self).forward_gpu(x)
  File "/data/work/w/repos/chainer/chainer/functions/pooling/pooling_nd.py", line 62, in forward_gpu
    x.data.ptr, zero.data, y_desc.value, y.data.ptr)
  File "cupy/cuda/cudnn.pyx", line 925, in cupy.cuda.cudnn.poolingForward
  File "cupy/cuda/cudnn.pyx", line 933, in cupy.cuda.cudnn.poolingForward
  File "cupy/cuda/cudnn.pyx", line 445, in cupy.cuda.cudnn.check_status
cupy.cuda.cudnn.CuDNNError: CUDNN_STATUS_NOT_SUPPORTED: b'CUDNN_STATUS_NOT_SUPPORTED'
```

### Cause
`cudnnPoolingForward` does not support spatial dimensions > 3.
(See cuDNN's official developer guide)

### Environment
Version: current master (5b5bea2)

```
$ /usr/local/cuda/bin/nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2016 NVIDIA Corporation
Built on Tue_Jan_10_13:22:03_CST_2017
Cuda compilation tools, release 8.0, V8.0.61
```

```
$ cudnnenv version
v7-cuda8
```


Discussion:

Resolving patch:
diff --git a/chainer/functions/pooling/average_pooling_nd.py b/chainer/functions/pooling/average_pooling_nd.py
--- a/chainer/functions/pooling/average_pooling_nd.py
+++ b/chainer/functions/pooling/average_pooling_nd.py
@@ -40,7 +40,7 @@ def forward_cpu(self, x):
         return y,
 
     def forward_gpu(self, x):
-        if chainer.should_use_cudnn('>=auto') and self.ndim >= 2:
+        if chainer.should_use_cudnn('>=auto') and 2 <= self.ndim <= 3:
             # With cuDNN v3 or greater, use cuDNN implementation for inputs
             # with spatial dimensions of two or more.
             return super(AveragePoolingND, self).forward_gpu(x)
diff --git a/chainer/functions/pooling/max_pooling_nd.py b/chainer/functions/pooling/max_pooling_nd.py
--- a/chainer/functions/pooling/max_pooling_nd.py
+++ b/chainer/functions/pooling/max_pooling_nd.py
@@ -44,7 +44,7 @@ def forward_cpu(self, x):
         return y,
 
     def forward_gpu(self, x):
-        if chainer.should_use_cudnn('>=auto') and self.ndim >= 2:
+        if chainer.should_use_cudnn('>=auto') and 2 <= self.ndim <= 3:
             # With cuDNN v3 or greater, use cuDNN implementation for inputs
             # with spatial dimensions of two or more.
             return super(MaxPoolingND, self).forward_gpu(x)


Test patch:
diff --git a/tests/chainer_tests/functions_tests/pooling_tests/test_average_pooling_nd.py b/tests/chainer_tests/functions_tests/pooling_tests/test_average_pooling_nd.py
--- a/tests/chainer_tests/functions_tests/pooling_tests/test_average_pooling_nd.py
+++ b/tests/chainer_tests/functions_tests/pooling_tests/test_average_pooling_nd.py
@@ -18,7 +18,7 @@
 
 
 @testing.parameterize(*testing.product({
-    'dims': [(4,), (4, 3), (4, 3, 2)],
+    'dims': [(4,), (4, 3), (4, 3, 2), (1, 1, 1, 1)],
     'dtype': [numpy.float16, numpy.float32, numpy.float64],
 }))
 class TestAveragePoolingND(unittest.TestCase):
diff --git a/tests/chainer_tests/functions_tests/pooling_tests/test_max_pooling_nd.py b/tests/chainer_tests/functions_tests/pooling_tests/test_max_pooling_nd.py
--- a/tests/chainer_tests/functions_tests/pooling_tests/test_max_pooling_nd.py
+++ b/tests/chainer_tests/functions_tests/pooling_tests/test_max_pooling_nd.py
@@ -19,7 +19,7 @@
 
 
 @testing.parameterize(*testing.product({
-    'dims': [(4,), (4, 3), (4, 3, 2)],
+    'dims': [(4,), (4, 3), (4, 3, 2), (1, 1, 1, 1)],
     'cover_all': [True, False],
     'dtype': [numpy.float16, numpy.float32, numpy.float64],
 }))