# HG changeset patch # User bergstra@is23.m # Date 1208504158 14400 # Node ID 810a8e3c85e1a63e915987419a889fcc59990cec # Parent 2508c373cf2935f1753f40241630379e648fee92 fixed horrible memory leak from crossentropy... diff -r 2508c373cf29 -r 810a8e3c85e1 nnet_ops.py --- a/nnet_ops.py Fri Apr 18 01:36:56 2008 -0400 +++ b/nnet_ops.py Fri Apr 18 03:35:58 2008 -0400 @@ -71,12 +71,7 @@ db = tensor.Sum(dx, axis = [0]).outputs[0] return dx, db, None - def c_validate_cleanup(self, (x, b, y_idx), (nll, sm), sub): - """Not sure...""" - return "" - def c_support_code(self): - return """ - """ + def c_headers(self): return [''] def c_code(self, (x, b, y_idx), (nll, sm), sub): # this implementation was lifted from # /u/bergstrj/cvs/bergstrj/src/feb07/nn.cxx @@ -89,25 +84,67 @@ return """ npy_intp* Nx = %(x)s->dimensions; - if (%(x)s->nd != 2) { %(fail)s } - if (%(b)s->nd != 1) { %(fail)s } - if (%(y_idx)s->nd != 1) { %(fail)s } - if (%(x)s->descr->type_num != PyArray_DOUBLE) { %(fail)s} - if (%(b)s->descr->type_num != PyArray_DOUBLE) { %(fail)s} - if (%(y_idx)s->descr->type_num != PyArray_INT64) { %(fail)s} - - %(nll)s = (PyArrayObject*)PyArray_SimpleNew(1, PyArray_DIMS(%(y_idx)s), type_num_%(x)s); - if(!%(nll)s){%(fail)s} + if (%(x)s->nd != 2) + { + PyErr_SetString(PyExc_ValueError, "a not 2d tensor"); + %(fail)s; + } + if (%(b)s->nd != 1) + { + PyErr_SetString(PyExc_ValueError, "b not 1d tensor"); + %(fail)s; + } + if (%(y_idx)s->nd != 1) + { + PyErr_SetString(PyExc_ValueError, "y_idx not 1d tensor"); + %(fail)s; + } + if (%(x)s->descr->type_num != PyArray_DOUBLE) + { + PyErr_SetString(PyExc_TypeError, "a not float64"); + %(fail)s; + } + if (%(b)s->descr->type_num != PyArray_DOUBLE) + { + PyErr_SetString(PyExc_TypeError, "b not float64"); + %(fail)s; + } + if (%(y_idx)s->descr->type_num != PyArray_INT64) + { + PyErr_SetString(PyExc_TypeError, "y_idx not int64"); + %(fail)s; + } + if ((%(x)s->dimensions[1] != %(b)s->dimensions[0]) + || (%(x)s->dimensions[0] != %(y_idx)s->dimensions[0])) + { + PyErr_SetString(PyExc_ValueError, "dimension mismatch in arguments"); + %(fail)s; + } - %(sm)s = (PyArrayObject*)PyArray_SimpleNew(2, PyArray_DIMS(%(x)s), type_num_%(x)s); - if(!%(sm)s) { - // The normal cleanup code will take care of %(nll)s - // Py_XDECREF(%(nll)s); %(nll)s=NULL; - %(fail)s + if ((NULL == %(nll)s) //initial condition + || (%(nll)s->dimensions[0] != %(y_idx)s->dimensions[0])) + { + if (NULL != %(nll)s) Py_XDECREF(%(nll)s); + %(nll)s = (PyArrayObject*)PyArray_SimpleNew(1, PyArray_DIMS(%(y_idx)s), type_num_%(x)s); + if(!%(nll)s) + { + PyErr_SetString(PyExc_MemoryError, "failed to alloc nll output"); + %(fail)s; + } } - if (%(x)s->dimensions[1] != %(b)s->dimensions[0]) {%(fail)s} - if (%(sm)s->dimensions[0] != %(x)s->dimensions[0]) {%(fail)s} - if (%(sm)s->dimensions[1] != %(x)s->dimensions[1]) {%(fail)s} + if ((NULL == %(sm)s) + || (%(sm)s->dimensions[0] != %(x)s->dimensions[0]) + || (%(sm)s->dimensions[1] != %(x)s->dimensions[1])) + { + if (NULL != %(sm)s) Py_XDECREF(%(sm)s); + %(sm)s = (PyArrayObject*)PyArray_SimpleNew(2, PyArray_DIMS(%(x)s), type_num_%(x)s); + if(!%(sm)s) { + // The normal cleanup code will take care of %(nll)s + // Py_XDECREF(%(nll)s); %(nll)s=NULL; + PyErr_SetString(PyExc_MemoryError, "failed to alloc sm output"); + %(fail)s + } + } for (size_t i = 0; i < Nx[0]; ++i) { @@ -204,36 +241,45 @@ self.outputs[0].data = dx def grad(self, *args): raise NotImplementedError() - def c_validate_update(self, (dnll, sm, y_idx), (dx,), sub): - """Allocate output storage""" - return """ - if (%(dnll)s->nd != 1) { %(fail)s } - if (%(sm)s->nd != 2) { %(fail)s } - if (%(y_idx)s->nd != 1) { %(fail)s } - if (%(dnll)s->descr->type_num != PyArray_DOUBLE) { %(fail)s} - if (%(sm)s->descr->type_num != PyArray_DOUBLE) { %(fail)s} - if (%(y_idx)s->descr->type_num != PyArray_INT64) { %(fail)s} - - %(dx)s = (PyArrayObject*)PyArray_SimpleNew(2, PyArray_DIMS(%(sm)s), type_num_%(sm)s); - if(!%(dx)s){%(fail)s} - - """ % dict(locals(), **sub) - def c_validate_cleanup(self, inputs, outputs, sub): - """Not sure...""" - return "" - def c_support_code(self): - return """ - """ def c_code(self, (dnll, sm, y_idx), (dx,), sub): return """ - npy_intp* shape = %(dx)s->dimensions; - if (%(dnll)s->dimensions[0] != %(sm)s->dimensions[0]) {%(fail)s} - if (%(dnll)s->dimensions[0] != %(y_idx)s->dimensions[0]) {%(fail)s} - if (%(dnll)s->dimensions[0] != %(dx)s->dimensions[0]) {%(fail)s} - if (%(sm)s->dimensions[1] != %(dx)s->dimensions[1]) {%(fail)s} + if ((%(dnll)s->descr->type_num != PyArray_DOUBLE) + || (%(sm)s->descr->type_num != PyArray_DOUBLE) + || (%(y_idx)s->descr->type_num != PyArray_INT64)) + { + PyErr_SetString(PyExc_TypeError, "types should be float64, float64, int64"); + %(fail)s; + } + if ((%(dnll)s->nd != 1) + || (%(sm)s->nd != 2) + || (%(y_idx)s->nd != 1)) + { + PyErr_SetString(PyExc_ValueError, "rank error"); + %(fail)s; + } + if ((%(dnll)s->dimensions[0] != %(sm)s->dimensions[0]) + || (%(dnll)s->dimensions[0] != %(y_idx)s->dimensions[0]) + || (%(dnll)s->dimensions[0] != %(dx)s->dimensions[0])) + { + PyErr_SetString(PyExc_ValueError, "dimension mismatch"); + %(fail)s; + } + if ((NULL == %(dx)s) + || (%(dx)s->dimensions[0] != %(sm)s->dimensions[0]) + || (%(dx)s->dimensions[1] != %(sm)s->dimensions[1])) + { + if (NULL != %(dx)s) Py_XDECREF(%(dx)s); + %(dx)s = (PyArrayObject*)PyArray_SimpleNew(2, PyArray_DIMS(%(x)s), type_num_%(x)s); + if(!%(dx)s) { + // The normal cleanup code will take care of %(nll)s + // Py_XDECREF(%(nll)s); %(nll)s=NULL; + PyErr_SetString(PyExc_MemoryError, "failed to alloc dx output"); + %(fail)s + } + } - for (size_t i = 0; i < shape[0]; ++i) + for (size_t i = 0; i < %(dx)s->dimensions[0]; ++i) { const double dnll_i = ((double*)(%(dnll)s->data + %(dnll)s->strides[0] * i))[0]; @@ -245,11 +291,11 @@ double* __restrict__ dx_i = (double*)(%(dx)s->data + %(dx)s->strides[0] * i); npy_intp Sdx = %(dx)s->strides[1]/sizeof(double); - for (size_t j = 0; j < shape[1]; ++j) + for (size_t j = 0; j < %(dx)s->dimensions[1]; ++j) { dx_i[j * Sdx] = dnll_i * sm_i[j * Ssm]; } - if (y_i >= shape[1]) + if (y_i >= %(dx)s->dimensions[1]) { %(fail)s; }