提交 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): ...@@ -922,7 +922,7 @@ class BaseGpuCorrMM(GpuOp):
def c_code_cache_version(self): def c_code_cache_version(self):
# raise this whenever modifying any of the support_code_files # raise this whenever modifying any of the support_code_files
return (0, 26) return (0, 27)
def c_support_code_apply(self, node, nodename): def c_support_code_apply(self, node, nodename):
# REMEMBER TO RAISE c_code_cache_version when changing any of # REMEMBER TO RAISE c_code_cache_version when changing any of
...@@ -960,19 +960,19 @@ class BaseGpuCorrMM(GpuOp): ...@@ -960,19 +960,19 @@ class BaseGpuCorrMM(GpuOp):
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
...@@ -1001,18 +1001,18 @@ class BaseGpuCorrMM(GpuOp): ...@@ -1001,18 +1001,18 @@ class BaseGpuCorrMM(GpuOp):
# 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 height:
height = '(*(npy_int*)(PyArray_DATA(%s)))' % height
else:
if ((direction != 0) and (dH != 1)) or ((direction == 1) and (padH == -1)): 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'") raise ValueError("height must be given for backprop with vertical sampling or pad='half'")
height = '(*(npy_int*)(PyArray_DATA(%s)))' % height height = '-1'
if width:
width = '(*(npy_int*)(PyArray_DATA(%s)))' % width
else: else:
height = 'NULL'
if ((direction != 0) and (dW != 1)) or ((direction == 1) and (padW == -1)): 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'") raise ValueError("width must be given for backprop with horizontal sampling or pad='half'")
width = '(*(npy_int*)(PyArray_DATA(%s)))' % width width = '-1'
else:
width = 'NULL'
sub = sub.copy() sub = sub.copy()
sub.update(locals()) sub.update(locals())
...@@ -1035,7 +1035,7 @@ class BaseGpuCorrMM(GpuOp): ...@@ -1035,7 +1035,7 @@ class BaseGpuCorrMM(GpuOp):
// 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)
int kH, kW; int 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 = CudaNdarray_HOST_DIMS(weights)[2]; kH = CudaNdarray_HOST_DIMS(weights)[2];
...@@ -1063,11 +1063,20 @@ class BaseGpuCorrMM(GpuOp): ...@@ -1063,11 +1063,20 @@ class BaseGpuCorrMM(GpuOp):
else { else {
kW = (CudaNdarray_HOST_DIMS(bottom)[3] + 2*padW - (CudaNdarray_HOST_DIMS(top)[3] - 1) * dW - 1) / dilW + 1; 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 // Implicit dilated kernel size
int dil_kH = (kH - 1) * dilH + 1; dil_kH = (kH - 1) * dilH + 1;
int 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
...@@ -1117,12 +1126,32 @@ class BaseGpuCorrMM(GpuOp): ...@@ -1117,12 +1126,32 @@ class BaseGpuCorrMM(GpuOp):
out_dim[1] = CudaNdarray_HOST_DIMS(weights)[1]; 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[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[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; 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: "
"%%dx%%dx%%dx%%d",
out_dim[0], out_dim[1],
out_dim[2], out_dim[3]);
%(fail)s
}
// Prepare output array // Prepare output array
if ( !(%(out)s if ( !(%(out)s
&& %(out)s->nd==4 && %(out)s->nd==4
...@@ -1274,15 +1303,15 @@ class GpuCorrMM_gradWeights(BaseGpuCorrMM): ...@@ -1274,15 +1303,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]
...@@ -1343,10 +1372,12 @@ class GpuCorrMM_gradInputs(BaseGpuCorrMM): ...@@ -1343,10 +1372,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:
if self.subsample != (1, 1):
raise ValueError('shape must be given if subsample != (1, 1)') raise ValueError('shape must be given if subsample != (1, 1)')
height_width = [shape[0], shape[1]] if self.subsample != (1, 1) else [] height_width = []
if 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
...@@ -1469,7 +1500,7 @@ class BaseGpuCorr3dMM(GpuOp): ...@@ -1469,7 +1500,7 @@ class BaseGpuCorr3dMM(GpuOp):
def c_code_cache_version(self): def c_code_cache_version(self):
# raise this whenever modifying any of the support_code_files # raise this whenever modifying any of the support_code_files
return (0, 25) return (0, 26)
def c_support_code_apply(self, node, nodename): def c_support_code_apply(self, node, nodename):
# REMEMBER TO RAISE c_code_cache_version when changing any of # REMEMBER TO RAISE c_code_cache_version when changing any of
...@@ -1510,26 +1541,26 @@ class BaseGpuCorr3dMM(GpuOp): ...@@ -1510,26 +1541,26 @@ class BaseGpuCorr3dMM(GpuOp):
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 Required if self.subsample[0] != 1, a variable giving the height of
of the filters for direction="backprop weights" or the height of the the filters for direction="backprop weights" or the height of the
input images for direction="backprop inputs". input images for direction="backprop inputs".
If self.pad == 'half', a variable giving the height of the filters Required if self.border_mode == 'half', a variable giving the height
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 Required if self.subsample[1] != 1, a variable giving the width of
of the 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.pad == 'half', a variable giving the width of the filters Required if self.border_mode == 'half', a variable giving the width
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 Required if self.subsample[2] != 1, a variable giving the depth of
of the 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.pad == 'half', a variable giving the depth of the filters Required if self.border_mode == 'half', a variable giving the depth
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
...@@ -1558,24 +1589,24 @@ class BaseGpuCorr3dMM(GpuOp): ...@@ -1558,24 +1589,24 @@ class BaseGpuCorr3dMM(GpuOp):
# 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 height:
height = '(*(npy_int*)(PyArray_DATA(%s)))' % height
else:
if ((direction != 0) and (dH != 1)) or ((direction == 1) and (padH == -1)): 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'") raise ValueError("height must be given for backprop with vertical sampling or pad='half'")
height = '(*(npy_int*)(PyArray_DATA(%s)))' % height height = '-1'
if width:
width = '(*(npy_int*)(PyArray_DATA(%s)))' % width
else: else:
height = 'NULL'
if ((direction != 0) and (dW != 1)) or ((direction == 1) and (padW == -1)): 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'") raise ValueError("width must be given for backprop with horizontal sampling or pad='half'")
width = '(*(npy_int*)(PyArray_DATA(%s)))' % width width = '-1'
if depth:
depth = '(*(npy_int*)(PyArray_DATA(%s)))' % depth
else: else:
width = 'NULL'
if ((direction != 0) and (dD != 1)) or ((direction == 1) and (padD == -1)): 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'") raise ValueError("depth must be given for backprop with horizontal sampling or pad='half'")
depth = '(*(npy_int*)(PyArray_DATA(%s)))' % depth depth = '-1'
else:
depth = 'NULL'
sub = sub.copy() sub = sub.copy()
sub.update(locals()) sub.update(locals())
...@@ -1601,7 +1632,7 @@ class BaseGpuCorr3dMM(GpuOp): ...@@ -1601,7 +1632,7 @@ class BaseGpuCorr3dMM(GpuOp):
// 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)
int kH, kW, kD; int 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
...@@ -1650,12 +1681,22 @@ class BaseGpuCorr3dMM(GpuOp): ...@@ -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; 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 // Implicit dilated kernel size
int dil_kH = (kH - 1) * dilH + 1; dil_kH = (kH - 1) * dilH + 1;
int dil_kW = (kW - 1) * dilW + 1; dil_kW = (kW - 1) * dilW + 1;
int dil_kD = (kD - 1) * dilD + 1; dil_kD = (kD - 1) * dilD + 1;
// Auto-padding if requested // Auto-padding if requested
if (padH == -1) if (padH == -1)
...@@ -1725,13 +1766,32 @@ class BaseGpuCorr3dMM(GpuOp): ...@@ -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[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[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; 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; 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: "
"%%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 // Prepare output array
if (!(%(out)s if (!(%(out)s
...@@ -1876,16 +1936,16 @@ class GpuCorr3dMM_gradWeights(BaseGpuCorr3dMM): ...@@ -1876,16 +1936,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]
...@@ -1943,10 +2003,12 @@ class GpuCorr3dMM_gradInputs(BaseGpuCorr3dMM): ...@@ -1943,10 +2003,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:
if self.subsample != (1, 1, 1):
raise ValueError('shape must be given if subsample != (1, 1, 1)') 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 [] height_width_depth = []
if 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论