Repository: chainer/chainer

Issue:
xxx_pooling_nd fails with CUDNN_STATUS_BAD_PARAM when size==0 and using cuDNN
### Code
```
import chainer
import numpy
import cupy

x_shape = (1, 1, 1, 0)
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-cudnn2.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 54, in forward_gpu
    x_desc = cudnn.create_tensor_descriptor(x)
  File "/data/work/w/repos/cupy/cupy/cudnn.py", line 81, in create_tensor_descriptor
    cudnn.setTensor4dDescriptor(desc.value, format, data_type, *arr.shape)
  File "cupy/cuda/cudnn.pyx", line 497, in cupy.cuda.cudnn.setTensor4dDescriptor
  File "cupy/cuda/cudnn.pyx", line 502, in cupy.cuda.cudnn.setTensor4dDescriptor
  File "cupy/cuda/cudnn.pyx", line 445, in cupy.cuda.cudnn.check_status
cupy.cuda.cudnn.CuDNNError: CUDNN_STATUS_BAD_PARAM: b'CUDNN_STATUS_BAD_PARAM'

```

### 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/pooling_nd.py b/chainer/functions/pooling/pooling_nd.py
--- a/chainer/functions/pooling/pooling_nd.py
+++ b/chainer/functions/pooling/pooling_nd.py
@@ -21,6 +21,10 @@ def __init__(self, ndim, ksize, stride=None, pad=0, cover_all=True):
         if stride is None:
             stride = ksize
 
+        if ndim <= 0:
+            raise ValueError(
+                'pooling operation requires at least one spatial dimension.')
+
         self.ndim = ndim
         self.ksize = conv_nd.as_tuple(ksize, ndim)
         self.stride = conv_nd.as_tuple(stride, ndim)
@@ -33,7 +37,8 @@ def check_type_forward(self, in_types):
         type_check.expect(
             in_types.size() == 1,
             in_types[0].dtype.kind == 'f',
-            in_types[0].ndim == 2 + self.ndim
+            in_types[0].ndim == 2 + self.ndim,
+            in_types[0].size > 0,
         )
 
     def forward_gpu(self, x):
diff --git a/chainer/utils/type_check.py b/chainer/utils/type_check.py
--- a/chainer/utils/type_check.py
+++ b/chainer/utils/type_check.py
@@ -1,4 +1,5 @@
 import contextlib
+import functools
 import operator
 import sys
 import threading
@@ -38,6 +39,10 @@ def __init__(self, shape, dtype):
         self.dtype = dtype
         self.ndim = len(shape)
 
+    @property
+    def size(self):
+        return functools.reduce(operator.mul, self.shape, 1)
+
 
 class TypeInfoTuple(tuple):
 


Test patch: