提交 b12925dd authored 作者: notoraptor's avatar notoraptor

Wrap op params for theano.gpuarray.pool.GpuPool.

上级 2d3e9ef7
...@@ -217,8 +217,8 @@ KERNEL void ave_pool3d_kernel(const ga_size nthreads, ...@@ -217,8 +217,8 @@ KERNEL void ave_pool3d_kernel(const ga_size nthreads,
// output shape for a given input padded shape, window shape and stride // output shape for a given input padded shape, window shape and stride
// We use ssize_t in the max since this is done to avoid negative results. // We use ssize_t in the max since this is done to avoid negative results.
#define OUTPUT_DIMS(in_dim, ws, st) \ #define OUTPUT_DIMS(in_dim, ws, st, ignore_border) \
(IGNORE_BORDER ? (in_dim - ws)/st + 1 : \ (ignore_border ? (in_dim - ws)/st + 1 : \
(st > ws ? (in_dim - 1)/st + 1 : \ (st > ws ? (in_dim - 1)/st + 1 : \
std::max<ssize_t>(0, (in_dim - 1 - ws + st)/st) + 1)) std::max<ssize_t>(0, (in_dim - 1 - ws + st)/st) + 1))
...@@ -229,7 +229,10 @@ int APPLY_SPECIFIC(pool)(PyGpuArrayObject *x, ...@@ -229,7 +229,10 @@ int APPLY_SPECIFIC(pool)(PyGpuArrayObject *x,
PyArrayObject *stride, PyArrayObject *stride,
PyArrayObject *pad, PyArrayObject *pad,
PyGpuArrayObject **z, PyGpuArrayObject **z,
PyGpuContextObject *ctx) { PARAMS_TYPE* params) {
bool max_pool = (params->mode == POOLING_MAX);
bool inc_pad = (params->mode != POOLING_AVERAGE_COUNT_EXCLUDE_PADDING);
bool sum_mode = (params->mode == POOLING_SUM);
if (!GpuArray_IS_C_CONTIGUOUS(&x->ga)) if (!GpuArray_IS_C_CONTIGUOUS(&x->ga))
{ {
PyErr_Format(PyExc_ValueError, PyErr_Format(PyExc_ValueError,
...@@ -253,19 +256,19 @@ int APPLY_SPECIFIC(pool)(PyGpuArrayObject *x, ...@@ -253,19 +256,19 @@ int APPLY_SPECIFIC(pool)(PyGpuArrayObject *x,
w[i] = *((npy_int64*)PyArray_GETPTR1(ws, i)); w[i] = *((npy_int64*)PyArray_GETPTR1(ws, i));
s[i] = *((npy_int64*)PyArray_GETPTR1(stride, i)); s[i] = *((npy_int64*)PyArray_GETPTR1(stride, i));
p[i] = *((npy_int64*)PyArray_GETPTR1(pad, i)); p[i] = *((npy_int64*)PyArray_GETPTR1(pad, i));
z_dims[2 + i] = OUTPUT_DIMS(x_dims[2 + i] + 2*p[i], w[i], s[i]); z_dims[2 + i] = OUTPUT_DIMS(x_dims[2 + i] + 2*p[i], w[i], s[i], params->ignore_border);
if (p[i] > 0) { if (p[i] > 0) {
nonzero_padding = 1; nonzero_padding = 1;
} }
} }
if (!IGNORE_BORDER && nonzero_padding) { if (!params->ignore_border && nonzero_padding) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"GpuPool: padding works only with ignore_border=True"); "GpuPool: padding works only with ignore_border=True");
return 1; return 1;
} }
if (theano_prep_output(z, PyGpuArray_NDIM(x), z_dims, if (theano_prep_output(z, PyGpuArray_NDIM(x), z_dims,
x->ga.typecode, GA_C_ORDER, ctx) != 0) x->ga.typecode, GA_C_ORDER, params->context) != 0)
{ {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
"GpuPool: failed to allocate memory"); "GpuPool: failed to allocate memory");
...@@ -277,7 +280,7 @@ int APPLY_SPECIFIC(pool)(PyGpuArrayObject *x, ...@@ -277,7 +280,7 @@ int APPLY_SPECIFIC(pool)(PyGpuArrayObject *x,
if (ndims == 2) { if (ndims == 2) {
size_t num_kernels = z_dims[0] * z_dims[1] * z_dims[2] * z_dims[3]; size_t num_kernels = z_dims[0] * z_dims[1] * z_dims[2] * z_dims[3];
if (MAX_POOL) { if (max_pool) {
err = max_pool2d_kernel_scall(1, &num_kernels, 0, num_kernels, err = max_pool2d_kernel_scall(1, &num_kernels, 0, num_kernels,
z_dims[0], z_dims[1], z_dims[2], z_dims[3], z_dims[0], z_dims[1], z_dims[2], z_dims[3],
x_dims[2], x_dims[3], x_dims[2], x_dims[3],
...@@ -295,7 +298,7 @@ int APPLY_SPECIFIC(pool)(PyGpuArrayObject *x, ...@@ -295,7 +298,7 @@ int APPLY_SPECIFIC(pool)(PyGpuArrayObject *x,
x_dims[2], x_dims[3], x_dims[2], x_dims[3],
x->ga.data, x->ga.offset, x->ga.data, x->ga.offset,
w[0], w[1], s[0], s[1], p[0], p[1], w[0], w[1], s[0], s[1], p[0], p[1],
INC_PAD, SUM_MODE, inc_pad, sum_mode,
(*z)->ga.data, (*z)->ga.offset); (*z)->ga.data, (*z)->ga.offset);
if (err != GA_NO_ERROR) { if (err != GA_NO_ERROR) {
PyErr_Format(PyExc_RuntimeError, PyErr_Format(PyExc_RuntimeError,
...@@ -307,7 +310,7 @@ int APPLY_SPECIFIC(pool)(PyGpuArrayObject *x, ...@@ -307,7 +310,7 @@ int APPLY_SPECIFIC(pool)(PyGpuArrayObject *x,
} }
else if (ndims == 3) { else if (ndims == 3) {
size_t num_kernels = z_dims[0] * z_dims[1] * z_dims[2] * z_dims[3] * z_dims[4]; size_t num_kernels = z_dims[0] * z_dims[1] * z_dims[2] * z_dims[3] * z_dims[4];
if (MAX_POOL) { if (max_pool) {
err = max_pool3d_kernel_scall(1, &num_kernels, 0, num_kernels, err = max_pool3d_kernel_scall(1, &num_kernels, 0, num_kernels,
z_dims[0], z_dims[1], z_dims[2], z_dims[3], z_dims[4], z_dims[0], z_dims[1], z_dims[2], z_dims[3], z_dims[4],
x_dims[2], x_dims[3], x_dims[4], x_dims[2], x_dims[3], x_dims[4],
...@@ -326,7 +329,7 @@ int APPLY_SPECIFIC(pool)(PyGpuArrayObject *x, ...@@ -326,7 +329,7 @@ int APPLY_SPECIFIC(pool)(PyGpuArrayObject *x,
x->ga.data, x->ga.offset, x->ga.data, x->ga.offset,
w[0], w[1], w[2], s[0], s[1], s[2], w[0], w[1], w[2], s[0], s[1], s[2],
p[0], p[1], p[2], p[0], p[1], p[2],
INC_PAD, SUM_MODE, inc_pad, sum_mode,
(*z)->ga.data, (*z)->ga.offset); (*z)->ga.data, (*z)->ga.offset);
if (err != GA_NO_ERROR) { if (err != GA_NO_ERROR) {
PyErr_Format(PyExc_RuntimeError, PyErr_Format(PyExc_RuntimeError,
......
...@@ -3,9 +3,12 @@ import os.path ...@@ -3,9 +3,12 @@ import os.path
import theano import theano
from theano import Apply from theano import Apply
from theano.gof import ParamsType
from theano.scalar import bool as bool_t
from theano.tensor.basic import as_tensor_variable from theano.tensor.basic import as_tensor_variable
from theano.tensor.signal.pool import Pool from theano.tensor.signal.pool import Pool, PoolingMode_t
from .type import gpu_context_type
from .basic_ops import (CGpuKernelBase, infer_context_name, from .basic_ops import (CGpuKernelBase, infer_context_name,
as_gpuarray_variable, gpu_contiguous) as_gpuarray_variable, gpu_contiguous)
...@@ -22,6 +25,9 @@ class GpuPool(CGpuKernelBase): ...@@ -22,6 +25,9 @@ class GpuPool(CGpuKernelBase):
""" """
__props__ = ('ignore_border', 'mode', 'ndim') __props__ = ('ignore_border', 'mode', 'ndim')
params_type = ParamsType(ignore_border=bool_t,
mode=PoolingMode_t,
context=gpu_context_type)
def __init__(self, ignore_border, mode='max', ndim=2): def __init__(self, ignore_border, mode='max', ndim=2):
self.ndim = ndim self.ndim = ndim
...@@ -31,9 +37,12 @@ class GpuPool(CGpuKernelBase): ...@@ -31,9 +37,12 @@ class GpuPool(CGpuKernelBase):
self.mode = mode self.mode = mode
CGpuKernelBase.__init__(self, ['pool.c'], CGpuKernelBase.__init__(self, ['pool.c'],
'APPLY_SPECIFIC(pool)') 'APPLY_SPECIFIC(pool)')
assert mode in ('max', 'sum', 'average_inc_pad', 'average_exc_pad') assert PoolingMode_t.has_alias(self.mode)
assert self.ndim in [2, 3] assert self.ndim in [2, 3]
def get_params(self, node):
return self.params_type.get_params(self, context=node.inputs[0].type.context)
def c_headers(self): def c_headers(self):
return ['gpuarray_api.h', 'gpuarray_helper.h', 'numpy_compat.h'] return ['gpuarray_api.h', 'gpuarray_helper.h', 'numpy_compat.h']
...@@ -74,16 +83,6 @@ class GpuPool(CGpuKernelBase): ...@@ -74,16 +83,6 @@ class GpuPool(CGpuKernelBase):
return Apply(self, [inp, ws, stride, pad], [inp.type()]) return Apply(self, [inp, ws, stride, pad], [inp.type()])
def get_op_params(self):
ignore_border = int(self.ignore_border)
max_pool = int(self.mode == 'max')
inc_pad = int(self.mode != 'average_exc_pad')
sum_mode = int(self.mode == 'sum')
return [('IGNORE_BORDER', ignore_border),
('INC_PAD', inc_pad),
('MAX_POOL', max_pool),
('SUM_MODE', sum_mode)]
def infer_shape(self, node, in_shapes): def infer_shape(self, node, in_shapes):
ws, stride, pad = [node.inputs[1], node.inputs[2], node.inputs[3]] ws, stride, pad = [node.inputs[1], node.inputs[2], node.inputs[3]]
shp = Pool.out_shape(in_shapes[0], ws, self.ignore_border, stride, shp = Pool.out_shape(in_shapes[0], ws, self.ignore_border, stride,
......
...@@ -14,7 +14,7 @@ from six.moves import xrange ...@@ -14,7 +14,7 @@ from six.moves import xrange
import six.moves.builtins as builtins import six.moves.builtins as builtins
import theano import theano
from theano import gof, OpenMPOp, tensor, Variable, Apply from theano import gof, OpenMPOp, tensor, Variable, Apply
from theano.gof.params_type import ParamsType from theano.gof import ParamsType, EnumList
from theano.gradient import DisconnectedType from theano.gradient import DisconnectedType
from theano.scalar import bool as bool_t from theano.scalar import bool as bool_t
...@@ -258,6 +258,16 @@ def pool_3d(input, ws=None, ignore_border=None, stride=None, pad=(0, 0, 0), ...@@ -258,6 +258,16 @@ def pool_3d(input, ws=None, ignore_border=None, stride=None, pad=(0, 0, 0),
return output return output
# NB: This enum type is currently used in gpuarray/pool.py.
# It may be used later as op param in this current file.
# Enum name and constants names are inspired from cuDNN type `cudnnPoolingMode_t`
# (cf. `theano/gpuarray/cudnn_defs.py`).
PoolingMode_t = EnumList(('POOLING_MAX', 'max'),
('POOLING_SUM', 'sum'),
('POOLING_AVERAGE_COUNT_INCLUDE_PADDING', 'average_inc_pad'),
('POOLING_AVERAGE_COUNT_EXCLUDE_PADDING', 'average_exc_pad'))
class Pool(OpenMPOp): class Pool(OpenMPOp):
""" """
sum or average over different patches. sum or average over different patches.
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论