diff options
author | Travis Oliphant <oliphant@enthought.com> | 2006-04-24 20:44:33 +0000 |
---|---|---|
committer | Travis Oliphant <oliphant@enthought.com> | 2006-04-24 20:44:33 +0000 |
commit | 448bb44cca09075c0281f0857109db3925908098 (patch) | |
tree | d840339bb1f55de400b89db0c5170ca86c53ff34 /numpy/core/src | |
parent | 9867cad08e60ed9232a721dc9a95b7951455bfc1 (diff) | |
download | numpy-448bb44cca09075c0281f0857109db3925908098.tar.gz |
Fix so USE_USE_DEFAULTS code works in multi-threaded case. Speed up 1-d array indexing by an integer.
Diffstat (limited to 'numpy/core/src')
-rw-r--r-- | numpy/core/src/arrayobject.c | 31 | ||||
-rw-r--r-- | numpy/core/src/ufuncobject.c | 99 |
2 files changed, 70 insertions, 60 deletions
diff --git a/numpy/core/src/arrayobject.c b/numpy/core/src/arrayobject.c index 0bd14c251..d4b4bb83f 100644 --- a/numpy/core/src/arrayobject.c +++ b/numpy/core/src/arrayobject.c @@ -1468,10 +1468,22 @@ array_big_item(PyArrayObject *self, intp i) return (PyObject *)r; } +/* contains optimization for 1-d arrays */ static PyObject * array_item_nice(PyArrayObject *self, _int_or_ssize_t i) { - return PyArray_Return((PyArrayObject *)array_big_item(self, (intp) i)); + if (self->nd == 1) { + char *item; + if (i < 0) { + i += self->dimensions[0]; + } + if ((item = index2ptr(self, i)) == NULL) return NULL; + return PyArray_Scalar(item, self->descr, (PyObject *)self); + } + else { + return PyArray_Return((PyArrayObject *)\ + array_big_item(self, (intp) i)); + } } static int @@ -2344,7 +2356,22 @@ array_subscript_nice(PyArrayObject *self, PyObject *op) implementation may be possible by refactoring array_subscript */ - PyArrayObject *mp = (PyArrayObject *)array_subscript(self, op); + PyArrayObject *mp; + + /* optimization for integer select and 1-d */ + if (self->nd == 1 && (PyInt_Check(op) || PyLong_Check(op))) { + intp value; + char *item; + value = PyArray_PyIntAsIntp(op); + if (PyErr_Occurred()) + return NULL; + else if (value < 0) { + value += self->dimensions[0]; + } + if ((item = index2ptr(self, value)) == NULL) return NULL; + return PyArray_Scalar(item, self->descr, (PyObject *)self); + } + mp = (PyArrayObject *)array_subscript(self, op); if (mp == NULL) return NULL; diff --git a/numpy/core/src/ufuncobject.c b/numpy/core/src/ufuncobject.c index bc439b61c..40cf40735 100644 --- a/numpy/core/src/ufuncobject.c +++ b/numpy/core/src/ufuncobject.c @@ -35,9 +35,9 @@ typedef void (CdoubleBinaryFunc)(cdouble *x, cdouble *y, cdouble *res); typedef void (CfloatBinaryFunc)(cfloat *x, cfloat *y, cfloat *res); typedef void (ClongdoubleBinaryFunc)(clongdouble *x, clongdouble *y, \ clongdouble *res); -
-#define USE_USE_DEFAULTS 0
-
+ +#define USE_USE_DEFAULTS 1 + /*UFUNC_API*/ static void @@ -699,11 +699,11 @@ select_types(PyUFuncObject *self, int *arg_types, return 0; } -
-#if USE_USE_DEFAULTS -static int PyUFunc_USEDEFAULTS=0;
+ +#if USE_USE_DEFAULTS==1 +static int PyUFunc_NUM_NODEFAULTS=0; #endif -static PyObject *PyUFunc_PYVALS_NAME=NULL;
+static PyObject *PyUFunc_PYVALS_NAME=NULL; /*UFUNC_API*/ @@ -713,20 +713,21 @@ PyUFunc_GetPyValues(char *name, int *bufsize, int *errmask, PyObject **errobj) PyObject *thedict; PyObject *ref=NULL; PyObject *retval; -
- #if USE_USE_DEFAULTS - if (!PyUFunc_USEDEFAULTS) {
+ + #if USE_USE_DEFAULTS==1 + if (PyUFunc_NUM_NODEFAULTS != 0) { #endif if (PyUFunc_PYVALS_NAME == NULL) { - PyUFunc_PYVALS_NAME = PyString_InternFromString(UFUNC_PYVALS_NAME); + PyUFunc_PYVALS_NAME = \ + PyString_InternFromString(UFUNC_PYVALS_NAME); } thedict = PyThreadState_GetDict(); if (thedict == NULL) { thedict = PyEval_GetBuiltins(); } - ref = PyDict_GetItem(thedict, PyUFunc_PYVALS_NAME);
- #if USE_USE_DEFAULTS - }
+ ref = PyDict_GetItem(thedict, PyUFunc_PYVALS_NAME); + #if USE_USE_DEFAULTS==1 + } #endif if (ref == NULL) { *errmask = UFUNC_ERR_DEFAULT; @@ -2768,7 +2769,6 @@ ufunc_geterr(PyObject *dummy, PyObject *args) return res; } /* Construct list of defaults */ - fprintf(stderr, "Nothing found... return defaults.\n"); res = PyList_New(3); if (res == NULL) return NULL; PyList_SET_ITEM(res, 0, PyInt_FromLong(PyArray_BUFSIZE)); @@ -2776,43 +2776,39 @@ ufunc_geterr(PyObject *dummy, PyObject *args) PyList_SET_ITEM(res, 2, Py_None); Py_INCREF(Py_None); return res; } -
-#if USE_USE_DEFAULTS
-/*
-This doesn't look it will work in the presence of threads. It updates
-PyUFunc_USEDEFAULTS based on the current thread. If some other thread is
-around, it will see an incorrect value for use_defaults.
-
-I think the following strategy would fix this:
- 1. Change PyUFunc_USEDEFAULTS to PyUFunc_NONDEFAULTCOUNT or similar
- 2. Increment PyUFunc_NONDEFAULTCOUNT whenever a value is set to a nondefault
- value
- 3. Only use defaults when PyUFunc_NONDEFAULTCOUNT is nonzero.
-
-However, I'm not sure that it's worth the trouble. I've done a few small
-benchmarks and I see at most marginal speed improvements with the
-default values. So, for the time being, I'm simply ifdefing out the
-nonworking code and not worrying about it. If those benchmarks hold up, we
-should go ahead and rip the code out so as not to confuse future generations.
-
+ +#if USE_USE_DEFAULTS==1 +/* +This is a strategy to buy a little speed up and avoid the dictionary +look-up in the default case. It should work in the presence of +threads. If it is deemed too complicated or it doesn't actually work +it could be taken out. */ static int ufunc_update_use_defaults(void) { PyObject *errobj; int errmask, bufsize; - - PyUFunc_USEDEFAULTS = 0; - if (PyUFunc_GetPyValues("test", &bufsize, &errmask, &errobj) < 0) return -1; + int res; - if ((errmask == UFUNC_ERR_DEFAULT) && \ - (bufsize == PyArray_BUFSIZE) && \ - (PyTuple_GET_ITEM(errobj, 1) == Py_None)) { - PyUFunc_USEDEFAULTS = 1; + PyUFunc_NUM_NODEFAULTS += 1; + res = PyUFunc_GetPyValues("test", &bufsize, &errmask, + &errobj); + PyUFunc_NUM_NODEFAULTS -= 1; + + if (res < 0) return -1; + + if ((errmask != UFUNC_ERR_DEFAULT) || \ + (bufsize != PyArray_BUFSIZE) || \ + (PyTuple_GET_ITEM(errobj, 1) != Py_None)) { + PyUFunc_NUM_NODEFAULTS += 1; + } + else if (PyUFunc_NUM_NODEFAULTS > 0) { + PyUFunc_NUM_NODEFAULTS -= 1; } return 0; } -#endif
+#endif static PyObject * ufunc_seterr(PyObject *dummy, PyObject *args) @@ -2823,21 +2819,9 @@ ufunc_seterr(PyObject *dummy, PyObject *args) static char *msg = "Error object must be a list of length 3"; if (!PyArg_ParseTuple(args, "O", &val)) return NULL; - - if (!PyList_CheckExact(val)) { - PyObject *new; - new = PyObject_GetAttrString(val, "_val_obj"); - if (new == NULL) { - PyErr_SetString(PyExc_ValueError, msg); - return NULL; - } - val = new; - } - else Py_INCREF(val); if (!PyList_CheckExact(val) || PyList_GET_SIZE(val) != 3) { PyErr_SetString(PyExc_ValueError, msg); - Py_DECREF(val); return NULL; } if (PyUFunc_PYVALS_NAME == NULL) { @@ -2848,10 +2832,9 @@ ufunc_seterr(PyObject *dummy, PyObject *args) thedict = PyEval_GetBuiltins(); } res = PyDict_SetItem(thedict, PyUFunc_PYVALS_NAME, val); - Py_DECREF(val); - if (res < 0) return NULL;
-#if USE_USE_DEFAULTS - if (ufunc_update_use_defaults() < 0) return NULL;
+ if (res < 0) return NULL; +#if USE_USE_DEFAULTS==1 + if (ufunc_update_use_defaults() < 0) return NULL; #endif Py_INCREF(Py_None); return Py_None; |