提交 46305ee5 authored 作者: James Bergstra's avatar James Bergstra

Removed pointless dependence of test_debugmode on sparse stuff

上级 570d61d4
import sys
import numpy
import scipy.sparse
from theano import gof
import theano.sparse
import theano
import theano.tensor
from theano.compile import debugmode
......@@ -15,7 +13,7 @@ def test0():
f = theano.function([x], (2.*x + 7) / 2., mode=debugmode.DebugMode())
print f([1,2])
class BROKEN_ON_PURPOSE_StructuredDotCSC(gof.Op):
class BROKEN_ON_PURPOSE_Add(gof.Op):
def __init__(self, py_offset):
gof.Op.__init__(self)
self.py_offset = py_offset
......@@ -23,140 +21,65 @@ class BROKEN_ON_PURPOSE_StructuredDotCSC(gof.Op):
return type(self) == type(other) and (self.py_offset == other.py_offset)
def __hash__(self):
return 29834 ^ hash(type(self)) ^ hash(self.py_offset)
def make_node(self, a_val, a_ind, a_ptr, a_nrows, b):
a_nrows = theano.tensor.as_tensor_variable(a_nrows)
assert a_val.type.dtype == b.type.dtype
r = gof.Apply(self, [a_val, a_ind, a_ptr, a_nrows, b],
[theano.tensor.tensor(a_val.type.dtype, (False, False))])
def make_node(self, a, b):
a = theano.tensor.as_tensor_variable(a)
b = theano.tensor.as_tensor_variable(b)
assert a.type.dtype == 'float64'
assert a.type.dtype == b.type.dtype
assert a.type.ndim==1
r = gof.Apply(self, [a, b], [a.type()])
return r
def perform(self, node, (a_val, a_ind, a_ptr, a_nrows, b), (out,)):
a = scipy.sparse.csc_matrix((a_val, a_ind, a_ptr),
(a_nrows, b.shape[0]),
copy = False)
# TODO: todense() is automatic in 0.7.0, just remove the following line:
z = a * b
def perform(self, node, (a, b), (out,)):
z = a+b
#ERROR TO ADD THIS CRAPPY OFFSET
if self.py_offset:
out[0] = z+0.5
else: out[0] = z
def c_code(self, node, name, (a_val, a_ind, a_ptr, a_nrows, b), (z,), sub):
def c_code(self, node, name, (a, b), (z,), sub):
return """
if (%(a_val)s->nd != 1) {PyErr_SetString(PyExc_NotImplementedError, "rank(a_val) != 1"); %(fail)s;}
if (%(a_ind)s->nd != 1) {PyErr_SetString(PyExc_NotImplementedError, "rank(a_ind) != 1"); %(fail)s;}
if (%(a_ptr)s->nd != 1) {PyErr_SetString(PyExc_NotImplementedError, "rank(a_ptr) != 1"); %(fail)s;}
if (%(a_nrows)s->nd != 0) {PyErr_SetString(PyExc_NotImplementedError, "rank(nrows) != 0"); %(fail)s;}
if (%(b)s->nd != 2) {PyErr_SetString(PyExc_NotImplementedError, "rank(b) != 2"); %(fail)s;}
if (%(a)s->nd != 1) {PyErr_SetString(PyExc_NotImplementedError, "rank(a) != 1"); %(fail)s;}
if (%(b)s->nd != 1) {PyErr_SetString(PyExc_NotImplementedError, "rank(b) != 1"); %(fail)s;}
if (%(a_val)s->descr->type_num != PyArray_DOUBLE)
{PyErr_SetString(PyExc_NotImplementedError, "a_val dtype not NPY_DOUBLE"); %(fail)s;}
if (%(a_ind)s->descr->type_num != PyArray_INT32) {
PyErr_SetString(PyExc_NotImplementedError, "a_ind dtype not INT32"); %(fail)s;}
if (%(a_ptr)s->descr->type_num != PyArray_INT32)
{PyErr_SetString(PyExc_NotImplementedError, "a_ptr dtype not INT32"); %(fail)s;}
if (%(a_nrows)s->descr->type_num != PyArray_INT32)
{PyErr_SetString(PyExc_NotImplementedError, "a_nrows dtype not INT32"); %(fail)s;}
if (%(a)s->descr->type_num != PyArray_DOUBLE)
{PyErr_SetString(PyExc_NotImplementedError, "a dtype not NPY_DOUBLE"); %(fail)s;}
if (%(b)s->descr->type_num != PyArray_DOUBLE)
{PyErr_SetString(PyExc_NotImplementedError, "b's dtype not NPY_DOUBLE"); %(fail)s;}
if (%(a_val)s->dimensions[0] != %(a_ind)s->dimensions[0])
{PyErr_SetString(PyExc_NotImplementedError, "a_val and a_ind have different lengths"); %(fail)s;}
if (%(a_ptr)s->dimensions[0] != %(b)s->dimensions[0]+1)
{PyErr_SetString(PyExc_NotImplementedError, "a's number of columns doesn't match b's rows"); %(fail)s;}
if (%(a)s->dimensions[0] != %(b)s->dimensions[0])
{PyErr_SetString(PyExc_NotImplementedError, "a and b have different lengths"); %(fail)s;}
if ((!%(z)s)
|| (%(z)s->dimensions[0] != ((npy_int32 *)%(a_nrows)s->data)[0])
|| (%(z)s->dimensions[1] != %(b)s->dimensions[1])
|| (%(z)s->dimensions[0] != %(b)s->dimensions[0])
)
{
{Py_XDECREF(%(z)s);}
npy_intp dims[] = {0,0};
dims[0] = ((npy_int32 *)%(a_nrows)s->data)[0];
dims[1] = %(b)s->dimensions[1];
%(z)s = (PyArrayObject*) PyArray_SimpleNew(2, dims, %(b)s->descr->type_num);
npy_intp dims[] = {0};
dims[0] = %(b)s->dimensions[0];
%(z)s = (PyArrayObject*) PyArray_SimpleNew(1, dims, %(b)s->descr->type_num);
}
{
//the output array has size M x N
npy_intp M = %(z)s->dimensions[0];
npy_intp N = %(z)s->dimensions[1];
npy_intp K = %(b)s->dimensions[0];
npy_intp Szm = %(z)s->strides[0] / %(z)s->descr->elsize;
npy_intp Szn = %(z)s->strides[1] / %(z)s->descr->elsize;
//npy_intp Sbm = %(b)s->strides[0] / %(b)s->descr->elsize;
npy_intp Sbn = %(b)s->strides[1] / %(b)s->descr->elsize;
npy_intp Sval = %(a_val)s->strides[0] / %(a_val)s->descr->elsize;
npy_intp Sind = %(a_ind)s->strides[0] / %(a_ind)s->descr->elsize;
npy_intp Sptr = %(a_ptr)s->strides[0] / %(a_ptr)s->descr->elsize;
npy_double * __restrict__ Dz = (npy_double*)%(z)s->data;
//const npy_double * __restrict__ Db = (npy_double*)%(b)s->data;
const npy_double * __restrict__ Dval = (npy_double*)%(a_val)s->data;
const npy_int32 * __restrict__ Dind = (npy_int32*)%(a_ind)s->data;
const npy_int32 * __restrict__ Dptr = (npy_int32*)%(a_ptr)s->data;
//npy_intp nnz = %(a_ind)s->dimensions[0];
//clear the output array
for (npy_intp m = 0; m < M; ++m)
{
for (npy_intp n = 0; n < N; ++n)
{
//Dz[m*Szm + n*Szn] = 0.0;
Dz[m*Szm + n*Szn] = 0.5; //here is the py_offset amount
}
}
//iterate over the sparse array, making the most of an entry wherever we find it.
//
// Normal matrix matrix multiply:
// for m
// for n
// for k
// z[m,n] += a[m,k] * b[k,n]
// Here instead:
// for k
// for m (sparse)
// for n
// z[m,n] += a[m,k] * b[k,n]
for (npy_int32 k = 0; k < K; ++k)
for (npy_intp m = 0; m < %(z)s->dimensions[0]; ++m)
{
const npy_double * __restrict__ bk = (double *)(%(b)s->data + %(b)s->strides[0] * k);
for (npy_int32 m_idx = Dptr[k * Sptr]; m_idx < Dptr[(k+1) * Sptr]; ++m_idx)
{
npy_int32 m = Dind[m_idx * Sind];
const double Amk = Dval[m_idx * Sval];
npy_double * __restrict__ zm = (npy_double *)(%(z)s->data + %(z)s->strides[0] * m);
if (m >= %(z)s->dimensions[0])
{PyErr_SetString(PyExc_NotImplementedError, "illegal row index in a"); %(fail)s;}
for(npy_int32 n = 0; n < N; ++n)
{
zm[n*Szn] += Amk * bk[n*Sbn];
}
}
((double*)PyArray_GETPTR1(%(z)s, m))[0]
= 0.5
+ ((double*)PyArray_GETPTR1(%(a)s, m))[0]
+ ((double*)PyArray_GETPTR1(%(b)s, m))[0] ;
}
}
"""% dict(locals(), **sub)
# inconsistent is a invalid op, whose perform and c_code do not match
inconsistent = BROKEN_ON_PURPOSE_StructuredDotCSC(False)
inconsistent = BROKEN_ON_PURPOSE_Add(False)
# off_by_half is a good op, that is different from theano.sparse.sd_csc
off_by_half = BROKEN_ON_PURPOSE_StructuredDotCSC(True)
off_by_half = BROKEN_ON_PURPOSE_Add(True)
class WeirdBrokenOp(gof.Op):
"""
This op can be inplace if behaviour is times1_inplace
This op can be destructive if behaviour is times2_inplace
This op can be inplace if behaviour is 'times1_inplace'
This op can be destructive if behaviour is 'times2_inplace'
In both cases, it does not set the destroy_map or view_map correctly so it should raise an
error in DebugMode.
......@@ -245,32 +168,20 @@ wb1 = WeirdBrokenOp('times1')
def test_badclinkeroutput():
vals = theano.tensor.dvector()
inds = theano.tensor.ivector()
ptrs = theano.tensor.ivector()
nrows = theano.tensor.iscalar()
b = theano.tensor.dmatrix()
a = theano.tensor.dvector()
b = theano.tensor.dvector()
f_good = theano.function([vals, inds, ptrs, nrows, b],
theano.sparse.StructuredDotCSC()(vals, inds, ptrs, nrows, b),
f_good = theano.function([a, b],
off_by_half(a, b),
mode=debugmode.DebugMode(check_c_code=True))
f_inconsistent = theano.function([vals, inds, ptrs, nrows, b],
inconsistent(vals, inds, ptrs, nrows, b),
f_inconsistent = theano.function([a,b],
inconsistent(a, b),
mode=debugmode.DebugMode(check_c_code=True))
#this should evaluate with no error
rval_good = f_good([1.0, 2.0, 3.0],
[0,1,2],
[0,1,2,3],
3,
numpy.asarray([[0.,1.,2.],[3.,4.,5.],[6.,7.,8.]]))
f_good([1.0, 2.0, 3.0], [2,3,4])
try:
rval = f_inconsistent([1.0, 2.0, 3.0],
[0,1,2],
[0,1,2,3],
3,
numpy.asarray([[0.,1.,2.],[3.,4.,5.],[6.,7.,8.]]))
f_inconsistent([1.0, 2.0, 3.0], [2,3,4])
except debugmode.BadCLinkerOutput, e:
print repr(e)
assert e.r.owner.op is inconsistent
......@@ -280,34 +191,25 @@ def test_badclinkeroutput():
def test_badoptimization():
@gof.local_optimizer([theano.sparse.sd_csc])
def insert_broken_csc(node):
if node.op == theano.sparse.sd_csc:
@gof.local_optimizer([theano.tensor.add])
def insert_broken_add(node):
if node.op == theano.tensor.add:
return [off_by_half(*node.inputs)]
return False
edb = gof.EquilibriumDB()
edb.register('insert_broken_csc', insert_broken_csc, 'all')
edb.register('insert_broken_add', insert_broken_add, 'all')
opt = edb.query('+all')
vals = theano.tensor.dvector()
inds = theano.tensor.ivector()
ptrs = theano.tensor.ivector()
nrows = theano.tensor.iscalar()
a = theano.tensor.dvector()
b = theano.tensor.dvector()
b = theano.tensor.dmatrix()
f = theano.function([vals, inds, ptrs, nrows, b],
theano.sparse.sd_csc(vals, inds, ptrs, nrows, b),
f = theano.function([a, b], a+b,
mode=debugmode.DebugMode(optimizer=opt, check_c_code=True))
try:
rval = f([1.0, 2.0, 3.0],
[0,1,2],
[0,1,2,3],
3,
numpy.asarray([[0.,1.,2.],[3.,4.,5.],[6.,7.,8.]]))
rval = f([1.0, 2.0, 3.0], [2,3,4],)
except debugmode.BadOptimization, e:
assert str(e.reason) == 'insert_broken_csc'
assert str(e.reason) == 'insert_broken_add'
return #TEST PASS
assert False
......@@ -317,27 +219,23 @@ def test_stochasticoptimization():
# this optimization alternates between triggering and not triggering.
last_time_replaced=[False]
@gof.local_optimizer([theano.sparse.sd_csc])
def insert_broken_csc_sometimes(node):
if node.op == theano.sparse.sd_csc:
@gof.local_optimizer([theano.tensor.add])
def insert_broken_add_sometimes(node):
if node.op == theano.tensor.add:
last_time_replaced[0] = not last_time_replaced[0]
if last_time_replaced[0]:
return [off_by_half(*node.inputs)]
return False
edb = gof.EquilibriumDB()
edb.register('insert_broken_csc_sometimes', insert_broken_csc_sometimes, 'all')
edb.register('insert_broken_add_sometimes', insert_broken_add_sometimes, 'all')
opt = edb.query('+all')
vals = theano.tensor.dvector()
inds = theano.tensor.ivector()
ptrs = theano.tensor.ivector()
nrows = theano.tensor.iscalar()
b = theano.tensor.dmatrix()
a = theano.tensor.dvector()
b = theano.tensor.dvector()
try:
f = theano.function([vals, inds, ptrs, nrows, b],
theano.sparse.sd_csc(vals, inds, ptrs, nrows, b),
f = theano.function([a, b],
theano.tensor.add(a, b),
mode=debugmode.DebugMode(optimizer=opt, check_c_code=True))
except debugmode.StochasticOrder:
return #TEST PASS
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论