提交 65f5ae84 authored 作者: Gijs van Tulder's avatar Gijs van Tulder

GpuCorrMM in old backend should also check provided output shapes.

上级 096a782b
......@@ -922,7 +922,7 @@ class BaseGpuCorrMM(GpuOp):
def c_code_cache_version(self):
# raise this whenever modifying any of the support_code_files
return (0, 26)
return (0, 27)
def c_support_code_apply(self, node, nodename):
# REMEMBER TO RAISE c_code_cache_version when changing any of
......@@ -960,19 +960,19 @@ class BaseGpuCorrMM(GpuOp):
sub
Dictionary of substitutions useable to help generating the C code.
height
If self.subsample[0] != 1, a variable giving the height of the
filters for direction="backprop weights" or the height of the input
images for direction="backprop inputs".
If self.border_mode == 'half', a variable giving the height of the
filters for direction="backprop weights".
Ignored otherwise.
Required if self.subsample[0] != 1, a variable giving the height of
the filters for direction="backprop weights" or the height of the
input images for direction="backprop inputs".
Required if self.border_mode == 'half', a variable giving the height
of the filters for direction="backprop weights".
Not required otherwise, but if a value is given this will be checked.
width
If self.subsample[1] != 1, a variable giving the width of the
filters for direction="backprop weights" or the width of the
Required if self.subsample[1] != 1, a variable giving the width of
the filters for direction="backprop weights" or the width of the
input images for direction="backprop inputs".
If self.border_mode == 'half', a variable giving the width of the
filters for direction="backprop weights".
Ignored otherwise.
Required if self.border_mode == 'half', a variable giving the width
of the filters for direction="backprop weights".
Not required otherwise, but if a value is given this will be checked.
"""
dH, dW = self.subsample
......@@ -1001,18 +1001,18 @@ class BaseGpuCorrMM(GpuOp):
# When subsampling, we cannot unambiguously infer the height and width
# of bottom and weights from top, so we require them to be given.
# Similarly, when pad="half", we cannot infer the weight size.
if ((direction != 0) and (dH != 1)) or ((direction == 1) and (padH == -1)):
if not height:
raise ValueError("height must be given for backprop with vertical sampling or pad='half'")
if height:
height = '(*(npy_int*)(PyArray_DATA(%s)))' % height
else:
height = 'NULL'
if ((direction != 0) and (dW != 1)) or ((direction == 1) and (padW == -1)):
if not width:
raise ValueError("width must be given for backprop with horizontal sampling or pad='half'")
if ((direction != 0) and (dH != 1)) or ((direction == 1) and (padH == -1)):
raise ValueError("height must be given for backprop with vertical sampling or pad='half'")
height = '-1'
if width:
width = '(*(npy_int*)(PyArray_DATA(%s)))' % width
else:
width = 'NULL'
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'
sub = sub.copy()
sub.update(locals())
......@@ -1035,7 +1035,7 @@ class BaseGpuCorrMM(GpuOp):
// Obtain or infer kernel width and height
// (we need to know it early to be able to handle auto-padding)
int kH, kW;
int kH, kW, dil_kH, dil_kW;
if (direction != 1) {
// weight is an input variable, we can just read its shape
kH = CudaNdarray_HOST_DIMS(weights)[2];
......@@ -1063,11 +1063,20 @@ class BaseGpuCorrMM(GpuOp):
else {
kW = (CudaNdarray_HOST_DIMS(bottom)[3] + 2*padW - (CudaNdarray_HOST_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 %%dx%%d "
"does not match given shape %%dx%%d",
kH, kW, %(height)s, %(width)s);
%(fail)s
}
}
// Implicit dilated kernel size
int dil_kH = (kH - 1) * dilH + 1;
int dil_kW = (kW - 1) * dilW + 1;
dil_kH = (kH - 1) * dilH + 1;
dil_kW = (kW - 1) * dilW + 1;
// Auto-padding if requested
if (padH == -1) { // vertical half padding
......@@ -1117,12 +1126,32 @@ class BaseGpuCorrMM(GpuOp):
out_dim[1] = CudaNdarray_HOST_DIMS(weights)[1];
out_dim[2] = (dH != 1) ? %(height)s : (CudaNdarray_HOST_DIMS(top)[2] - 1) * dH + (CudaNdarray_HOST_DIMS(weights)[2]-1)*dilH + 1 - 2*padH;
out_dim[3] = (dW != 1) ? %(width)s : (CudaNdarray_HOST_DIMS(top)[3] - 1) * dW + (CudaNdarray_HOST_DIMS(weights)[3]-1)*dilW + 1 - 2*padW;
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 %%dx%%d "
"does not match given shape %%dx%%d",
out_dim[2], out_dim[3],
%(height)s, %(width)s);
%(fail)s
}
break;
default:
PyErr_SetString(PyExc_ValueError, "BaseGpuCorrMM: direction must be 0, 1, or 2\\n");
%(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: "
"%%dx%%dx%%dx%%d",
out_dim[0], out_dim[1],
out_dim[2], out_dim[3]);
%(fail)s
}
// Prepare output array
if ( !(%(out)s
&& %(out)s->nd==4
......@@ -1274,15 +1303,15 @@ class GpuCorrMM_gradWeights(BaseGpuCorrMM):
raise TypeError('img must be 4D tensor')
if topgrad.type.ndim != 4:
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)'
' or border_mode == "half"')
height_width = []
else:
height_width = [shape[0], shape[1]]
assert shape[0].ndim == 0
assert shape[1].ndim == 0
else:
height_width = []
broadcastable = [topgrad.type.broadcastable[1], img.type.broadcastable[1],
False, False]
......@@ -1343,10 +1372,12 @@ class GpuCorrMM_gradInputs(BaseGpuCorrMM):
raise TypeError('kern must be 4D tensor')
if topgrad.type.ndim != 4:
raise TypeError('topgrad must be 4D tensor')
if self.subsample != (1, 1) and shape is None:
raise ValueError('shape must be given if subsample != (1, 1)')
height_width = [shape[0], shape[1]] if self.subsample != (1, 1) else []
if height_width:
if shape is None:
if self.subsample != (1, 1):
raise ValueError('shape must be given if subsample != (1, 1)')
height_width = []
else:
height_width = [shape[0], shape[1]]
assert shape[0].ndim == 0
assert shape[1].ndim == 0
......@@ -1469,7 +1500,7 @@ class BaseGpuCorr3dMM(GpuOp):
def c_code_cache_version(self):
# raise this whenever modifying any of the support_code_files
return (0, 25)
return (0, 26)
def c_support_code_apply(self, node, nodename):
# REMEMBER TO RAISE c_code_cache_version when changing any of
......@@ -1510,26 +1541,26 @@ class BaseGpuCorr3dMM(GpuOp):
sub
Dictionary of substitutions useable to help generating the C code.
height
If self.subsample[0] != 1, a variable giving the height
of the filters for direction="backprop weights" or the height of the
Required if self.subsample[0] != 1, a variable giving the height of
the filters for direction="backprop weights" or the height of the
input images for direction="backprop inputs".
If self.pad == 'half', a variable giving the height of the filters
for direction="backprop weights".
Ignored otherwise.
Required if self.border_mode == 'half', a variable giving the height
of the filters for direction="backprop weights".
Not required otherwise, but if a value is given this will be checked.
width
If self.subsample[1] != 1, a variable giving the width
of the filters for direction="backprop weights" or the width of the
Required if self.subsample[1] != 1, a variable giving the width of
the filters for direction="backprop weights" or the width of the
input images for direction="backprop inputs".
If self.pad == 'half', a variable giving the width of the filters
for direction="backprop weights".
Ignored otherwise.
Required if self.border_mode == 'half', a variable giving the width
of the filters for direction="backprop weights".
Not required otherwise, but if a value is given this will be checked.
depth
If self.subsample[2] != 1, a variable giving the depth
of the filters for direction="backprop weights" or the depth of the
Required if self.subsample[2] != 1, a variable giving the depth of
the filters for direction="backprop weights" or the depth of the
input images for direction="backprop inputs".
If self.pad == 'half', a variable giving the depth of the filters
for direction="backprop weights".
Ignored otherwise.
Required if self.border_mode == 'half', a variable giving the depth
of the filters for direction="backprop weights".
Not required otherwise, but if a value is given this will be checked.
"""
dH, dW, dD = self.subsample
......@@ -1558,24 +1589,24 @@ class BaseGpuCorr3dMM(GpuOp):
# When subsampling, we cannot unambiguously infer the height and width
# of bottom and weights from top, so we require them to be given.
# Similarly, when pad="half", we cannot infer the weight size.
if ((direction != 0) and (dH != 1)) or ((direction == 1) and (padH == -1)):
if not height:
raise ValueError("height must be given for backprop with vertical sampling or pad='half'")
if height:
height = '(*(npy_int*)(PyArray_DATA(%s)))' % height
else:
height = 'NULL'
if ((direction != 0) and (dW != 1)) or ((direction == 1) and (padW == -1)):
if not width:
raise ValueError("width must be given for backprop with horizontal sampling or pad='half'")
if ((direction != 0) and (dH != 1)) or ((direction == 1) and (padH == -1)):
raise ValueError("height must be given for backprop with vertical sampling or pad='half'")
height = '-1'
if width:
width = '(*(npy_int*)(PyArray_DATA(%s)))' % width
else:
width = 'NULL'
if ((direction != 0) and (dD != 1)) or ((direction == 1) and (padD == -1)):
if not depth:
raise ValueError("depth must be given for backprop with horizontal sampling or pad='half'")
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'
if depth:
depth = '(*(npy_int*)(PyArray_DATA(%s)))' % depth
else:
depth = 'NULL'
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'
sub = sub.copy()
sub.update(locals())
......@@ -1601,7 +1632,7 @@ class BaseGpuCorr3dMM(GpuOp):
// Obtain or infer kernel width and height
// (we need to know it early to be able to handle auto-padding)
int kH, kW, kD;
int kH, kW, kD, dil_kH, dil_kW, dil_kD;
if (direction != 1)
{
// weight is an input variable, we can just read its shape
......@@ -1650,12 +1681,22 @@ class BaseGpuCorr3dMM(GpuOp):
{
kD = (CudaNdarray_HOST_DIMS(bottom)[4] + 2*padD - (CudaNdarray_HOST_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 %%dx%%dx%%d "
"does not match given shape %%dx%%dx%%d",
kH, kW, kD, %(height)s, %(width)s, %(depth)s);
%(fail)s
}
}
// Implicit dilated kernel size
int dil_kH = (kH - 1) * dilH + 1;
int dil_kW = (kW - 1) * dilW + 1;
int dil_kD = (kD - 1) * dilD + 1;
dil_kH = (kH - 1) * dilH + 1;
dil_kW = (kW - 1) * dilW + 1;
dil_kD = (kD - 1) * dilD + 1;
// Auto-padding if requested
if (padH == -1)
......@@ -1725,13 +1766,32 @@ class BaseGpuCorr3dMM(GpuOp):
out_dim[2] = (dH != 1) ? %(height)s : (CudaNdarray_HOST_DIMS(top)[2] - 1) * dH + (CudaNdarray_HOST_DIMS(weights)[2]-1)*dilH + 1 - 2*padH;
out_dim[3] = (dW != 1) ? %(width)s : (CudaNdarray_HOST_DIMS(top)[3] - 1) * dW + (CudaNdarray_HOST_DIMS(weights)[3]-1)*dilW + 1 - 2*padW;
out_dim[4] = (dD != 1) ? %(depth)s : (CudaNdarray_HOST_DIMS(top)[4] - 1) * dD + (CudaNdarray_HOST_DIMS(weights)[4]-1)*dilD + 1 - 2*padD;
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 %%dx%%dx%%d "
"does not match given shape %%dx%%dx%%d",
out_dim[2], out_dim[3], out_dim[4],
%(height)s, %(width)s, %(depth)s);
%(fail)s
}
break;
default:
PyErr_SetString(PyExc_ValueError, "BaseGpuCorr3dMM: direction must be 0, 1, or 2\\n");
%(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: "
"%%dx%%dx%%dx%%d%%d",
out_dim[0], out_dim[1],
out_dim[2], out_dim[3], out_dim[4]);
%(fail)s
}
// Prepare output array
if (!(%(out)s
......@@ -1876,16 +1936,16 @@ class GpuCorr3dMM_gradWeights(BaseGpuCorr3dMM):
raise TypeError('img must be 5D tensor')
if topgrad.type.ndim != 5:
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)'
' or border_mode == "half"')
height_width_depth = []
else:
height_width_depth = [shape[0], shape[1], shape[2]]
assert shape[0].ndim == 0
assert shape[1].ndim == 0
assert shape[2].ndim == 0
else:
height_width_depth = []
broadcastable = [topgrad.type.broadcastable[1], img.type.broadcastable[1],
False, False, False]
......@@ -1943,10 +2003,12 @@ class GpuCorr3dMM_gradInputs(BaseGpuCorr3dMM):
raise TypeError('kern must be 5D tensor')
if topgrad.type.ndim != 5:
raise TypeError('topgrad must be 5D tensor')
if self.subsample != (1, 1, 1) and shape is None:
raise ValueError('shape must be given if subsample != (1, 1, 1)')
height_width_depth = [shape[0], shape[1], shape[2]] if self.subsample != (1, 1, 1) else []
if height_width_depth:
if shape is None:
if self.subsample != (1, 1, 1):
raise ValueError('shape must be given if subsample != (1, 1, 1)')
height_width_depth = []
else:
height_width_depth = [shape[0], shape[1], shape[2]]
assert shape[0].ndim == 0
assert shape[1].ndim == 0
assert shape[2].ndim == 0
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论