提交 096a782b authored 作者: Gijs van Tulder's avatar Gijs van Tulder

GpuCorrMM and GpuCorr3dMM should always check provided output shapes.

上级 d327e49e
...@@ -528,7 +528,7 @@ class BaseGpuCorrMM(CGpuKernelBase): ...@@ -528,7 +528,7 @@ class BaseGpuCorrMM(CGpuKernelBase):
def c_code_cache_version(self): def c_code_cache_version(self):
# Raise this whenever modifying the code below. # Raise this whenever modifying the code below.
return (2,) return (3,)
def c_code_helper(self, bottom, weights, top, direction, sub, height=None, width=None): def c_code_helper(self, bottom, weights, top, direction, sub, height=None, width=None):
""" """
...@@ -558,19 +558,19 @@ class BaseGpuCorrMM(CGpuKernelBase): ...@@ -558,19 +558,19 @@ class BaseGpuCorrMM(CGpuKernelBase):
sub sub
Dictionary of substitutions useable to help generating the C code. Dictionary of substitutions useable to help generating the C code.
height height
If self.subsample[0] != 1, a variable giving the height of the Required if self.subsample[0] != 1, a variable giving the height of
filters for direction="backprop weights" or the height of the input the filters for direction="backprop weights" or the height of the
images for direction="backprop inputs". input images for direction="backprop inputs".
If self.border_mode == 'half', a variable giving the height of the Required if self.border_mode == 'half', a variable giving the height
filters for direction="backprop weights". of the filters for direction="backprop weights".
Ignored otherwise. Not required otherwise, but if a value is given this will be checked.
width width
If self.subsample[1] != 1, a variable giving the width of the Required if self.subsample[1] != 1, a variable giving the width of
filters for direction="backprop weights" or the width of the the filters for direction="backprop weights" or the width of the
input images for direction="backprop inputs". input images for direction="backprop inputs".
If self.border_mode == 'half', a variable giving the width of the Required if self.border_mode == 'half', a variable giving the width
filters for direction="backprop weights". of the filters for direction="backprop weights".
Ignored otherwise. Not required otherwise, but if a value is given this will be checked.
""" """
dH, dW = self.subsample dH, dW = self.subsample
...@@ -599,18 +599,18 @@ class BaseGpuCorrMM(CGpuKernelBase): ...@@ -599,18 +599,18 @@ class BaseGpuCorrMM(CGpuKernelBase):
# When subsampling, we cannot unambiguously infer the height and width # When subsampling, we cannot unambiguously infer the height and width
# of bottom and weights from top, so we require them to be given. # of bottom and weights from top, so we require them to be given.
# Similarly, when pad="half", we cannot infer the weight size. # Similarly, when pad="half", we cannot infer the weight size.
if ((direction != 0) and (dH != 1)) or ((direction == 1) and (padH == -1)): if height:
if not height:
raise ValueError("height must be given for backprop with vertical sampling or pad='half'")
height = '(*(npy_int*)(PyArray_DATA(%s)))' % height height = '(*(npy_int*)(PyArray_DATA(%s)))' % height
else: else:
height = '0' if ((direction != 0) and (dH != 1)) or ((direction == 1) and (padH == -1)):
if ((direction != 0) and (dW != 1)) or ((direction == 1) and (padW == -1)): raise ValueError("height must be given for backprop with vertical sampling or pad='half'")
if not width: height = '-1'
raise ValueError("width must be given for backprop with horizontal sampling or pad='half'") if width:
width = '(*(npy_int*)(PyArray_DATA(%s)))' % width width = '(*(npy_int*)(PyArray_DATA(%s)))' % width
else: else:
width = '0' if ((direction != 0) and (dW != 1)) or ((direction == 1) and (padW == -1)):
raise ValueError("width must be given for backprop with horizontal sampling or pad='half'")
width = '-1'
sync = "" sync = ""
if config.gpuarray.sync: if config.gpuarray.sync:
sync = """ sync = """
...@@ -643,7 +643,7 @@ class BaseGpuCorrMM(CGpuKernelBase): ...@@ -643,7 +643,7 @@ class BaseGpuCorrMM(CGpuKernelBase):
// Obtain or infer kernel width and height // Obtain or infer kernel width and height
// (we need to know it early to be able to handle auto-padding) // (we need to know it early to be able to handle auto-padding)
size_t kH, kW; size_t kH, kW, dil_kH, dil_kW;
if (direction != 1) { if (direction != 1) {
// weight is an input variable, we can just read its shape // weight is an input variable, we can just read its shape
kH = PyGpuArray_DIMS(weights)[2]; kH = PyGpuArray_DIMS(weights)[2];
...@@ -671,11 +671,20 @@ class BaseGpuCorrMM(CGpuKernelBase): ...@@ -671,11 +671,20 @@ class BaseGpuCorrMM(CGpuKernelBase):
else { else {
kW = (PyGpuArray_DIMS(bottom)[3] + 2*padW - (PyGpuArray_DIMS(top)[3] - 1) * dW - 1) / dilW + 1; kW = (PyGpuArray_DIMS(bottom)[3] + 2*padW - (PyGpuArray_DIMS(top)[3] - 1) * dW - 1) / dilW + 1;
} }
if ((%(height)s != -1 && %(height)s != kH) ||
(%(width)s != -1 && %(width)s != kW))
{
PyErr_Format(PyExc_ValueError,
"BaseGpuCorrMM: computed kernel shape %%lldx%%lld "
"does not match given shape %%lldx%%lld",
(long long)kH, (long long)kW, (long long)%(height)s, (long long)%(width)s);
%(fail)s
}
} }
// Implicit dilated kernel size // Implicit dilated kernel size
size_t dil_kH = (kH - 1) * dilH + 1; dil_kH = (kH - 1) * dilH + 1;
size_t dil_kW = (kW - 1) * dilW + 1; dil_kW = (kW - 1) * dilW + 1;
// Auto-padding if requested // Auto-padding if requested
if (padH == -1) { // vertical half padding if (padH == -1) { // vertical half padding
...@@ -733,12 +742,32 @@ class BaseGpuCorrMM(CGpuKernelBase): ...@@ -733,12 +742,32 @@ class BaseGpuCorrMM(CGpuKernelBase):
out_dim[3] = (dW != 1) ? %(width)s : (PyGpuArray_DIMS(top)[3] - 1) * dW + (PyGpuArray_DIMS(weights)[3]-1)*dilW + 1 - 2*padW; out_dim[3] = (dW != 1) ? %(width)s : (PyGpuArray_DIMS(top)[3] - 1) * dW + (PyGpuArray_DIMS(weights)[3]-1)*dilW + 1 - 2*padW;
out_typecode = top->ga.typecode; out_typecode = top->ga.typecode;
out_context = top->context; out_context = top->context;
if ((%(height)s != -1 && %(height)s != out_dim[2]) ||
(%(width)s != -1 && %(width)s != out_dim[3]))
{
PyErr_Format(PyExc_ValueError,
"BaseGpuCorrMM: computed output shape %%lldx%%lld "
"does not match given shape %%lldx%%lld",
(long long)out_dim[2], (long long)out_dim[3],
(long long)%(height)s, (long long)%(width)s);
%(fail)s
}
break; break;
default: default:
PyErr_SetString(PyExc_ValueError, "BaseGpuCorrMM: direction must be 0, 1, or 2\\n"); PyErr_SetString(PyExc_ValueError, "BaseGpuCorrMM: direction must be 0, 1, or 2\\n");
%(fail)s %(fail)s
} }
if (out_dim[0] < 0 || out_dim[1] < 0 || out_dim[2] < 0 || out_dim[3] < 0)
{
PyErr_Format(PyExc_ValueError,
"BaseGpuCorrMM: impossible output shape: "
"%%lldx%%lldx%%lldx%%lld",
(long long)out_dim[0], (long long)out_dim[1],
(long long)out_dim[2], (long long)out_dim[3]);
%(fail)s
}
// Prepare output array // Prepare output array
if (theano_prep_output(&%(out)s, 4, out_dim, out_typecode, GA_C_ORDER, out_context) != 0) if (theano_prep_output(&%(out)s, 4, out_dim, out_typecode, GA_C_ORDER, out_context) != 0)
{ {
...@@ -875,15 +904,15 @@ class GpuCorrMM_gradWeights(BaseGpuCorrMM): ...@@ -875,15 +904,15 @@ class GpuCorrMM_gradWeights(BaseGpuCorrMM):
raise TypeError('img must be 4D tensor') raise TypeError('img must be 4D tensor')
if topgrad.type.ndim != 4: if topgrad.type.ndim != 4:
raise TypeError('topgrad must be 4D tensor') raise TypeError('topgrad must be 4D tensor')
if self.subsample != (1, 1) or self.border_mode == "half": if shape is None:
if shape is None: if self.subsample != (1, 1) or self.border_mode == "half":
raise ValueError('shape must be given if subsample != (1, 1)' raise ValueError('shape must be given if subsample != (1, 1)'
' or border_mode == "half"') ' or border_mode == "half"')
height_width = []
else:
height_width = [shape[0], shape[1]] height_width = [shape[0], shape[1]]
assert shape[0].ndim == 0 assert shape[0].ndim == 0
assert shape[1].ndim == 0 assert shape[1].ndim == 0
else:
height_width = []
broadcastable = [topgrad.type.broadcastable[1], img.type.broadcastable[1], broadcastable = [topgrad.type.broadcastable[1], img.type.broadcastable[1],
False, False] False, False]
...@@ -946,10 +975,12 @@ class GpuCorrMM_gradInputs(BaseGpuCorrMM): ...@@ -946,10 +975,12 @@ class GpuCorrMM_gradInputs(BaseGpuCorrMM):
raise TypeError('kern must be 4D tensor') raise TypeError('kern must be 4D tensor')
if topgrad.type.ndim != 4: if topgrad.type.ndim != 4:
raise TypeError('topgrad must be 4D tensor') raise TypeError('topgrad must be 4D tensor')
if self.subsample != (1, 1) and shape is None: if shape is None:
raise ValueError('shape must be given if subsample != (1, 1)') if self.subsample != (1, 1):
height_width = [shape[0], shape[1]] if self.subsample != (1, 1) else [] raise ValueError('shape must be given if subsample != (1, 1)')
if height_width: height_width = []
else:
height_width = [shape[0], shape[1]]
assert shape[0].ndim == 0 assert shape[0].ndim == 0
assert shape[1].ndim == 0 assert shape[1].ndim == 0
...@@ -1074,7 +1105,7 @@ class BaseGpuCorr3dMM(CGpuKernelBase): ...@@ -1074,7 +1105,7 @@ class BaseGpuCorr3dMM(CGpuKernelBase):
def c_code_cache_version(self): def c_code_cache_version(self):
# raise this whenever modifying the code below. # raise this whenever modifying the code below.
return (2,) return (3,)
def c_code_helper(self, bottom, weights, top, direction, sub, def c_code_helper(self, bottom, weights, top, direction, sub,
height=None, width=None, depth=None): height=None, width=None, depth=None):
...@@ -1105,26 +1136,26 @@ class BaseGpuCorr3dMM(CGpuKernelBase): ...@@ -1105,26 +1136,26 @@ class BaseGpuCorr3dMM(CGpuKernelBase):
sub sub
Dictionary of substitutions useable to help generating the C code. Dictionary of substitutions useable to help generating the C code.
height height
If self.subsample[0] != 1, a variable giving the height of the Required if self.subsample[0] != 1, a variable giving the height of
filters for direction="backprop weights" or the height of the input the filters for direction="backprop weights" or the height of the
images for direction="backprop inputs". input images for direction="backprop inputs".
If self.border_mode == 'half', a variable giving the height of the Required if self.border_mode == 'half', a variable giving the height
filters for direction="backprop weights". of the filters for direction="backprop weights".
Ignored otherwise. Not required otherwise, but if a value is given this will be checked.
width width
If self.subsample[1] != 1, a variable giving the width of the Required if self.subsample[1] != 1, a variable giving the width of
filters for direction="backprop weights" or the width of the the filters for direction="backprop weights" or the width of the
input images for direction="backprop inputs". input images for direction="backprop inputs".
If self.border_mode == 'half', a variable giving the width of the Required if self.border_mode == 'half', a variable giving the width
filters for direction="backprop weights". of the filters for direction="backprop weights".
Ignored otherwise. Not required otherwise, but if a value is given this will be checked.
depth depth
If self.subsample[2] != 1, a variable giving the depth of the Required if self.subsample[2] != 1, a variable giving the depth of
filters for direction="backprop weights" or the depth of the the filters for direction="backprop weights" or the depth of the
input images for direction="backprop inputs". input images for direction="backprop inputs".
If self.border_mode == 'half', a variable giving the depth of the Required if self.border_mode == 'half', a variable giving the depth
filters for direction="backprop weights". of the filters for direction="backprop weights".
Ignored otherwise. Not required otherwise, but if a value is given this will be checked.
""" """
dH, dW, dD = self.subsample dH, dW, dD = self.subsample
...@@ -1153,24 +1184,24 @@ class BaseGpuCorr3dMM(CGpuKernelBase): ...@@ -1153,24 +1184,24 @@ class BaseGpuCorr3dMM(CGpuKernelBase):
# When subsampling, we cannot unambiguously infer the height and width # When subsampling, we cannot unambiguously infer the height and width
# of bottom and weights from top, so we require them to be given. # of bottom and weights from top, so we require them to be given.
# Similarly, when pad="half", we cannot infer the weight size. # Similarly, when pad="half", we cannot infer the weight size.
if ((direction != 0) and (dH != 1)) or ((direction == 1) and (padH == -1)): if height:
if not height:
raise ValueError("height must be given for backprop with vertical sampling or pad='half'")
height = '(*(npy_int*)(PyArray_DATA(%s)))' % height height = '(*(npy_int*)(PyArray_DATA(%s)))' % height
else: else:
height = '0' if ((direction != 0) and (dH != 1)) or ((direction == 1) and (padH == -1)):
if ((direction != 0) and (dW != 1)) or ((direction == 1) and (padW == -1)): raise ValueError("height must be given for backprop with vertical sampling or pad='half'")
if not width: height = '-1'
raise ValueError("width must be given for backprop with horizontal sampling or pad='half'") if width:
width = '(*(npy_int*)(PyArray_DATA(%s)))' % width width = '(*(npy_int*)(PyArray_DATA(%s)))' % width
else: else:
width = '0' if ((direction != 0) and (dW != 1)) or ((direction == 1) and (padW == -1)):
if ((direction != 0) and (dD != 1)) or ((direction == 1) and (padD == -1)): raise ValueError("width must be given for backprop with horizontal sampling or pad='half'")
if not depth: width = '-1'
raise ValueError("depth must be given for backprop with horizontal sampling or pad='half'") if depth:
depth = '(*(npy_int*)(PyArray_DATA(%s)))' % depth depth = '(*(npy_int*)(PyArray_DATA(%s)))' % depth
else: else:
depth = '0' if ((direction != 0) and (dD != 1)) or ((direction == 1) and (padD == -1)):
raise ValueError("depth must be given for backprop with horizontal sampling or pad='half'")
depth = '-1'
sync = "" sync = ""
if config.gpuarray.sync: if config.gpuarray.sync:
sync = """ sync = """
...@@ -1206,7 +1237,7 @@ class BaseGpuCorr3dMM(CGpuKernelBase): ...@@ -1206,7 +1237,7 @@ class BaseGpuCorr3dMM(CGpuKernelBase):
// Obtain or infer kernel height, width and depth // Obtain or infer kernel height, width and depth
// (we need to know it early to be able to handle auto-padding) // (we need to know it early to be able to handle auto-padding)
size_t kH, kW, kD; size_t kH, kW, kD, dil_kH, dil_kW, dil_kD;
if (direction != 1) { if (direction != 1) {
// weight is an input variable, we can just read its shape // weight is an input variable, we can just read its shape
kH = PyGpuArray_DIMS(weights)[2]; kH = PyGpuArray_DIMS(weights)[2];
...@@ -1244,12 +1275,23 @@ class BaseGpuCorr3dMM(CGpuKernelBase): ...@@ -1244,12 +1275,23 @@ class BaseGpuCorr3dMM(CGpuKernelBase):
else { else {
kD = (PyGpuArray_DIMS(bottom)[4] + 2*padD - (PyGpuArray_DIMS(top)[4] - 1) * dD - 1) / dilD + 1; kD = (PyGpuArray_DIMS(bottom)[4] + 2*padD - (PyGpuArray_DIMS(top)[4] - 1) * dD - 1) / dilD + 1;
} }
if ((%(height)s != -1 && %(height)s != kH) ||
(%(width)s != -1 && %(width)s != kW) ||
(%(depth)s != -1 && %(depth)s != kD))
{
PyErr_Format(PyExc_ValueError,
"BaseGpuCorr3dMM: computed kernel shape %%lldx%%lldx%%lld "
"does not match given shape %%lldx%%lldx%%lld",
(long long)kH, (long long)kW, (long long)kD,
(long long)%(height)s, (long long)%(width)s, (long long)%(depth)s);
%(fail)s
}
} }
// Implicit dilated kernel size // Implicit dilated kernel size
size_t dil_kH = (kH - 1) * dilH + 1; dil_kH = (kH - 1) * dilH + 1;
size_t dil_kW = (kW - 1) * dilW + 1; dil_kW = (kW - 1) * dilW + 1;
size_t dil_kD = (kD - 1) * dilD + 1; dil_kD = (kD - 1) * dilD + 1;
// Auto-padding if requested // Auto-padding if requested
if (padH == -1) { // vertical half padding if (padH == -1) { // vertical half padding
...@@ -1320,12 +1362,33 @@ class BaseGpuCorr3dMM(CGpuKernelBase): ...@@ -1320,12 +1362,33 @@ class BaseGpuCorr3dMM(CGpuKernelBase):
out_dim[4] = (dD != 1) ? %(depth)s : (PyGpuArray_DIMS(top)[4] - 1) * dD + (PyGpuArray_DIMS(weights)[4]-1)*dilD + 1 - 2*padD; out_dim[4] = (dD != 1) ? %(depth)s : (PyGpuArray_DIMS(top)[4] - 1) * dD + (PyGpuArray_DIMS(weights)[4]-1)*dilD + 1 - 2*padD;
out_typecode = top->ga.typecode; out_typecode = top->ga.typecode;
out_context = top->context; out_context = top->context;
if ((%(height)s != -1 && %(height)s != out_dim[2]) ||
(%(width)s != -1 && %(width)s != out_dim[3]) ||
(%(depth)s != -1 && %(depth)s != out_dim[4]))
{
PyErr_Format(PyExc_ValueError,
"BaseGpuCorr3dMM: computed output shape %%lldx%%lldx%%lld "
"does not match given shape %%lldx%%lldx%%lld",
(long long)out_dim[2], (long long)out_dim[3], (long long)out_dim[4],
(long long)%(height)s, (long long)%(width)s, (long long)%(depth)s);
%(fail)s
}
break; break;
default: default:
PyErr_SetString(PyExc_ValueError, "BaseGpuCorr3dMM: direction must be 0, 1, or 2\\n"); PyErr_SetString(PyExc_ValueError, "BaseGpuCorr3dMM: direction must be 0, 1, or 2\\n");
%(fail)s %(fail)s
} }
if (out_dim[0] < 0 || out_dim[1] < 0 || out_dim[2] < 0 || out_dim[3] < 0 || out_dim[4] < 0)
{
PyErr_Format(PyExc_ValueError,
"BaseGpuCorr3dMM: impossible output shape: "
"%%lldx%%lldx%%lldx%%lld%%lld",
(long long)out_dim[0], (long long)out_dim[1],
(long long)out_dim[2], (long long)out_dim[3], (long long)out_dim[4]);
%(fail)s
}
// Prepare output array // Prepare output array
if (theano_prep_output(&%(out)s, 5, out_dim, out_typecode, GA_C_ORDER, out_context) != 0) if (theano_prep_output(&%(out)s, 5, out_dim, out_typecode, GA_C_ORDER, out_context) != 0)
{ {
...@@ -1464,16 +1527,16 @@ class GpuCorr3dMM_gradWeights(BaseGpuCorr3dMM): ...@@ -1464,16 +1527,16 @@ class GpuCorr3dMM_gradWeights(BaseGpuCorr3dMM):
raise TypeError('img must be 5D tensor') raise TypeError('img must be 5D tensor')
if topgrad.type.ndim != 5: if topgrad.type.ndim != 5:
raise TypeError('topgrad must be 5D tensor') raise TypeError('topgrad must be 5D tensor')
if self.subsample != (1, 1, 1) or self.border_mode == "half": if shape is None:
if shape is None: if self.subsample != (1, 1, 1) or self.border_mode == "half":
raise ValueError('shape must be given if subsample != (1, 1, 1)' raise ValueError('shape must be given if subsample != (1, 1, 1)'
' or border_mode == "half"') ' or border_mode == "half"')
height_width_depth = []
else:
height_width_depth = [shape[0], shape[1], shape[2]] height_width_depth = [shape[0], shape[1], shape[2]]
assert shape[0].ndim == 0 assert shape[0].ndim == 0
assert shape[1].ndim == 0 assert shape[1].ndim == 0
assert shape[2].ndim == 0 assert shape[2].ndim == 0
else:
height_width_depth = []
broadcastable = [topgrad.type.broadcastable[1], img.type.broadcastable[1], broadcastable = [topgrad.type.broadcastable[1], img.type.broadcastable[1],
False, False, False] False, False, False]
...@@ -1536,10 +1599,12 @@ class GpuCorr3dMM_gradInputs(BaseGpuCorr3dMM): ...@@ -1536,10 +1599,12 @@ class GpuCorr3dMM_gradInputs(BaseGpuCorr3dMM):
raise TypeError('kern must be 5D tensor') raise TypeError('kern must be 5D tensor')
if topgrad.type.ndim != 5: if topgrad.type.ndim != 5:
raise TypeError('topgrad must be 5D tensor') raise TypeError('topgrad must be 5D tensor')
if self.subsample != (1, 1, 1) and shape is None: if shape is None:
raise ValueError('shape must be given if subsample != (1, 1, 1)') if self.subsample != (1, 1, 1):
height_width_depth = [shape[0], shape[1], shape[2]] if self.subsample != (1, 1, 1) else [] raise ValueError('shape must be given if subsample != (1, 1, 1)')
if height_width_depth: height_width_depth = []
else:
height_width_depth = [shape[0], shape[1], shape[2]]
assert shape[0].ndim == 0 assert shape[0].ndim == 0
assert shape[1].ndim == 0 assert shape[1].ndim == 0
assert shape[2].ndim == 0 assert shape[2].ndim == 0
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论