提交 135b6cc6 authored 作者: Pascal Lamblin's avatar Pascal Lamblin

Merge pull request #2663 from nouiz/conv2d_test

Conv2d test
......@@ -3342,13 +3342,15 @@ class GpuAlloc(GpuOp):
}
if (%(memset_0)s && CudaNdarray_is_c_contiguous(%(out)s))
{
if (cudaSuccess != cudaMemset(%(out)s->devdata, 0,
CudaNdarray_SIZE(%(out)s) * 4))
cudaError_t err = cudaMemset(%(out)s->devdata, 0,
CudaNdarray_SIZEt(%(out)s) * 4);
if (cudaSuccess != err)
{
PyErr_Format(PyExc_MemoryError,
"GpuAlloc: Error memsetting %%d"
" bytes of device memory.",
CudaNdarray_SIZE(%(out)s) * 4);
"GpuAlloc: Error memsetting %%ld"
" bytes of device memory. %%s",
(long)(CudaNdarray_SIZEt(%(out)s) * 4),
cudaGetErrorString(err));
Py_XDECREF(%(out)s);
%(out)s = NULL;
%(fail)s;
......@@ -3372,7 +3374,7 @@ class GpuAlloc(GpuOp):
return [None for i in inputs]
def c_code_cache_version(self):
return (7,)
return (9,)
def do_constant_folding(self, node):
for client in node.outputs[0].clients:
......
......@@ -5117,6 +5117,17 @@ CudaNdarray_SIZE(const CudaNdarray *self)
}
return size;
}
size_t
CudaNdarray_SIZEt(const CudaNdarray *self)
{
if (self->nd == -1) return 0;
size_t size = 1;
for (int i = 0; i < self->nd; ++i)
{
size *= CudaNdarray_HOST_DIMS(self)[i];
}
return size;
}
PyObject *
CudaNdarray_SIZE_Object(const CudaNdarray *self, void *closure)
......
......@@ -286,6 +286,9 @@ DllExport float *CudaNdarray_DEV_DATA(const CudaNdarray * self);
* Return the number of elements in the ndarray (product of the dimensions)
*/
DllExport int CudaNdarray_SIZE(const CudaNdarray *self);
// Useful as many cuda function use size_t as input. This make sure we use the
// most precission and not int.
DllExport size_t CudaNdarray_SIZEt(const CudaNdarray *self);
static PyObject *CudaNdarray_SIZE_Object(const CudaNdarray *self, void *closure);
......
......@@ -61,12 +61,14 @@ def conv2d(input, filters, image_shape=None, filter_shape=None,
:param subsample: factor by which to subsample the output.
Also called strides elsewhere.
:type image_shape: None, tuple/list of len 4 of int or Constant variable
:type image_shape: None, tuple/list of len 4 of int, None or
Constant variable
:param image_shape: The shape of the input parameter.
Optional, used for optimization like loop unrolling
You can put None for any element of the list
to tell that this element is not constant.
:type filter_shape: None, tuple/list of len 4 of int or Constant variable
:type filter_shape: None, tuple/list of len 4 of int, None or
Constant variable
:param filter_shape: Optional, used for optimization like loop unrolling
You can put None for any element of the list
to tell that this element is not constant.
......@@ -671,15 +673,23 @@ class ConvOp(OpenMPOp):
imshp = self.imshp
if any(x is None for x in imshp):
imshp = tuple(img2d.shape[1:])
if imshp != img2d.shape[1:]:
raise ValueError("bad shape", imshp, img2d.shape[1:])
kshp = self.kshp
if any(x is None for x in kshp):
kshp = tuple(filtersflipped.shape[2:])
if kshp != filtersflipped.shape[2:]:
raise ValueError("bad shape", kshp, filtersflipped.shape[2:])
bsize = self.bsize
if bsize is None:
bsize = img2d.shape[0]
elif bsize != img2d.shape[0]:
raise ValueError("bad shape", bsize, img2d.shape[0])
nkern = self.nkern
if nkern is None:
nkern = filtersflipped.shape[0]
elif nkern != filtersflipped.shape[0]:
raise ValueError("bad shape", nkern, filtersflipped.shape[0])
imshp_logical = self.imshp_logical
if imshp_logical[0] is None:
......@@ -974,7 +984,7 @@ class ConvOp(OpenMPOp):
return ['<numpy/noprefix.h>', '<iostream>', '<sstream>']
def c_code_cache_version(self):
return (13, self.openmp, blas.blas_header_version())
return (14, self.openmp, blas.blas_header_version())
def c_support_code(self):
return """
......@@ -1069,25 +1079,126 @@ using namespace std;
d["self_imshp2"] = "PyArray_DIMS(%(img2d)s)[3]" % d
d["self_kshp0"] = "PyArray_DIMS(%(filtersflipped)s)[2]" % d
d["self_kshp1"] = "PyArray_DIMS(%(filtersflipped)s)[3]" % d
d["assert_size"] = ""
# Override the default value if we have it
if self.kshp[0] is not None:
expected = d["self_kshp0"]
value = self.kshp[0]
d["assert_size"] += """
if(%(value)s != %(expected)s){
PyErr_Format(PyExc_ValueError,
"the hard coded shape (%%ld) isn't the run time shape (%%ld).",
(long)%(value)s, (long)%(expected)s);
%(fail)s;
}
""" % dict(expected=expected, value=value, **sub)
d["self_kshp0"] = self.kshp[0]
if self.kshp[1] is not None:
expected = d["self_kshp1"]
value = self.kshp[1]
d["assert_size"] += """
if(%(value)s != %(expected)s){
PyErr_Format(PyExc_ValueError,
"the hard coded shape (%%ld) isn't the run time shape (%%ld).",
(long)%(value)s, (long)%(expected)s);
%(fail)s;
}
""" % dict(expected=expected, value=value, **sub)
d["self_kshp1"] = self.kshp[1]
if self.outshp[0] is not None:
expected = "dim_zz[0]"
value = self.outshp[0]
d["assert_size"] += """
if(%(value)s != %(expected)s){
PyErr_Format(PyExc_ValueError,
"the hard coded shape (%%ld) isn't the run time shape (%%ld).",
(long)%(value)s, (long)%(expected)s);
%(fail)s;
}
""" % dict(expected=expected, value=value, **sub)
d["self_outshp0"] = self.outshp[0]
if self.outshp[1] is not None:
expected = "dim_zz[1]"
value = self.outshp[1]
d["assert_size"] += """
if(%(value)s != %(expected)s){
PyErr_Format(PyExc_ValueError,
"the hard coded shape (%%ld) isn't the run time shape (%%ld).",
(long)%(value)s, (long)%(expected)s);
%(fail)s;
}
""" % dict(expected=expected, value=value, **sub)
d["self_outshp1"] = self.outshp[1]
if self.imshp[0] is not None:
expected = d["self_imshp0"]
value = self.imshp[0]
d["assert_size"] += """
if(%(value)s != %(expected)s){
PyErr_Format(PyExc_ValueError,
"the hard coded shape (%%ld) isn't the run time shape (%%ld).",
(long)%(value)s, (long)%(expected)s);
%(fail)s;
}
""" % dict(expected=expected, value=value, **sub)
expected = "kerns_dim[1]"
value = self.imshp[0]
d["assert_size"] += """
if(%(value)s != %(expected)s){
PyErr_Format(PyExc_ValueError,
"the hard coded shape (%%ld) isn't the run time shape (%%ld).",
(long)%(value)s, (long)%(expected)s);
%(fail)s;
}
""" % dict(expected=expected, value=value, **sub)
d["self_imshp0"] = self.imshp[0]
if self.imshp[1] is not None:
expected = d["self_imshp1"]
value = self.imshp[1]
d["assert_size"] += """
if(%(value)s != %(expected)s){
PyErr_Format(PyExc_ValueError,
"the hard coded shape (%%ld) isn't the run time shape (%%ld).",
(long)%(value)s, (long)%(expected)s);
%(fail)s;
}
""" % dict(expected=expected, value=value, **sub)
d["self_imshp1"] = self.imshp[1]
if self.imshp[2] is not None:
expected = d["self_imshp2"]
value = self.imshp[2]
d["assert_size"] += """
if(%(value)s != %(expected)s){
PyErr_Format(PyExc_ValueError,
"the hard coded shape (%%ld) isn't the run time shape (%%ld).",
(long)%(value)s, (long)%(expected)s);
%(fail)s;
}
""" % dict(expected=expected, value=value, **sub)
d["self_imshp2"] = self.imshp[2]
if self.bsize is not None:
expected = d["self_bsize"]
value = self.bsize
d["assert_size"] += """
if(%(value)s != %(expected)s){
PyErr_Format(PyExc_ValueError,
"the hard coded shape (%%ld) isn't the run time shape (%%ld).",
(long)%(value)s, (long)%(expected)s);
%(fail)s;
}
""" % dict(expected=expected, value=value, **sub)
d["self_bsize"] = self.bsize
if self.nkern is not None:
expected = d["self_nkern"]
value = self.nkern
d["assert_size"] += """
if(%(value)s != %(expected)s){
PyErr_Format(PyExc_ValueError,
"the hard coded shape (%%ld) isn't the run time shape (%%ld).",
(long)%(value)s, (long)%(expected)s);
%(fail)s;
}
""" % dict(expected=expected, value=value, **sub)
d["self_nkern"] = self.nkern
# Other hard coded stuff only if we have all shapes
......@@ -1111,86 +1222,6 @@ using namespace std;
d["all_shape"] = "1"
d["dim_zz_const"] = "const"
d["dim_zz_affect"] = ""
d["assert_size"] = """
// Check the batch size and the number of kernels (sometimes constant in the graph)
if(img2d_dim[0] != %(self_bsize)s!=0){
PyErr_Format(PyExc_ValueError,
"the batch size in the image (%%ld) at run time is different"
" than at build time (%%ld) for the ConvOp.",
(long)img2d_dim[0], (long)%(self_bsize)s);
%(fail)s;
}
if(kerns_dim[0] != %(self_nkern)s!=0){
PyErr_Format(PyExc_ValueError,
"the number of kernels in the filter (%%ld) at run time is"
" different than at build time (%%ld) for the ConvOp.",
(long)kerns_dim[0], (long)%(self_nkern)s);
%(fail)s;
}
// Check the size of the image (sometimes constant in the graph)
if(img2d_dim[1] != %(self_imshp0)s){
PyErr_Format(PyExc_ValueError,
"the image stack size (%%ld) at run time is different than"
" at build time (%%ld) for the ConvOp.",
(long)img2d_dim[1], (long)%(self_imshp0)s);
%(fail)s;
}
if(img2d_dim[2] != %(self_imshp1)s){
PyErr_Format(PyExc_ValueError,
"the number of rows in the image (%%ld) at run time is different"
" than at build time (%%ld) for the ConvOp.",
(long)img2d_dim[2], (long)%(self_imshp1)s);
%(fail)s;
}
if(img2d_dim[3] != %(self_imshp2)s){
PyErr_Format(PyExc_ValueError,
"the number of columns in the image (%%ld) at run time is"
" different than at build time (%%ld) for the ConvOp.",
(long)img2d_dim[3], (long)%(self_imshp2)s);
%(fail)s;
}
// Check the size of the output (sometimes constant in the graph)
if(dim_zz[0] != %(self_outshp0)s!=0){
PyErr_Format(PyExc_ValueError,
"the precomputed number of rows in the output (%%ld) at run time"
" is different than at build time (%%ld) for the ConvOp.",
(long)dim_zz[0], (long)%(self_outshp0)s);
%(fail)s;
}
if(dim_zz[1] != %(self_outshp1)s!=0){
PyErr_Format(PyExc_ValueError,
"the precomputed number of columns in the output (%%ld) at run"
" time is different than at build time (%%ld) for the ConvOp.",
(long)dim_zz[1], (long)%(self_outshp1)s);
%(fail)s;
}
// Check the size of the filter (sometimes constant in the graph)
if(kerns_dim[1] %% %(self_imshp0)s!=0){
PyErr_Format(PyExc_ValueError,
"the filter stack size (%%ld) at run time is different than at"
" build time (%%ld) for the ConvOp.",
(long)kerns_dim[1], (long)%(self_imshp0)s);
%(fail)s;
}
if(kerns_dim[2] %% %(self_kshp0)s!=0){
PyErr_Format(PyExc_ValueError,
"the number of rows in the filter (%%ld) at run time is different"
" than at build time (%%ld) for the ConvOp.",
(long)kerns_dim[2], (long)%(self_kshp0)s);
%(fail)s;
}
if(kerns_dim[3] %% %(self_kshp1)s!=0){
PyErr_Format(PyExc_ValueError,
"the number of columns in the filter (%%ld) at run time is"
" different than at build time (%%ld) for the ConvOp.",
(long)kerns_dim[3], (long)%(self_kshp1)s);
%(fail)s;
}
""" % (locals())
else:
d["affectation"] = "+="
d["all_shape"] = "0"
......@@ -1204,7 +1235,7 @@ if(kerns_dim[3] %% %(self_kshp1)s!=0){
dim_zz[1] = (int)ceil((dim_im[1]-dim_ker1+1)/float(%(self_dy)s));
}
""" % d
d["assert_size"] = """
d["assert_size"] += """
// Check the stack size of the filter and images are equals
if(kerns_dim[1] != img2d_dim[1]){
PyErr_Format(PyExc_ValueError,
......
......@@ -449,6 +449,29 @@ class TestConv2D(utt.InferShapeTester):
print t2 - t1,
print
def test_fail(self):
k = theano.shared(numpy.ones((1, 1, 3, 3), dtype='float32'))
im = T.ftensor4()
out = theano.function([im],
T.nnet.conv2d(im, k, image_shape=(1, 1, 10, 10)))
self.assertRaises(ValueError, out, numpy.ones((1, 1, 20, 10),
dtype='float32'))
out = theano.function([im],
T.nnet.conv2d(im, k, filter_shape=(1, 1, 3, 2)))
self.assertRaises(ValueError, out, numpy.ones((1, 1, 10, 10),
dtype='float32'))
out = theano.function([im],
T.nnet.conv2d(im, k, filter_shape=(2, None,
None, None)))
self.assertRaises(ValueError, out, numpy.ones((1, 1, 10, 10),
dtype='float32'))
out = theano.function([im],
T.nnet.conv2d(im, k, image_shape=(1, None,
None, None)))
self.assertRaises(ValueError, out, numpy.ones((2, 1, 10, 10),
dtype='float32'))
def test_infer_shape(self):
# Note: infer_shape is incomplete and thus input and filter shapes
# must be provided explicitly
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论