diff nnet_ops.py @ 67:810a8e3c85e1

fixed horrible memory leak from crossentropy...
author bergstra@is23.m
date Fri, 18 Apr 2008 03:35:58 -0400
parents 1b152f46ad0c
children 315eb36ff954
line wrap: on
line diff
--- 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 ['<iostream>']
     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;
             }