diff options
author | m-d-w <mw9050@gmail.com> | 2013-06-06 14:57:16 -0400 |
---|---|---|
committer | m-d-w <mw9050@gmail.com> | 2013-06-10 18:17:52 -0400 |
commit | 3abe4fd00ab1eead3a5a35163821a3edac504a36 (patch) | |
tree | 465e82b24cd16455cc41ef7e346e2db4eb255390 | |
parent | 16c55bad4aa4c49116d963eee85550258c83b934 (diff) | |
download | numpy-3abe4fd00ab1eead3a5a35163821a3edac504a36.tar.gz |
ENH: Optimize array creation by avoiding errors
-rw-r--r-- | numpy/core/src/multiarray/common.c | 122 | ||||
-rw-r--r-- | numpy/core/src/multiarray/common.h | 3 | ||||
-rw-r--r-- | numpy/core/src/multiarray/ctors.c | 62 | ||||
-rw-r--r-- | numpy/core/src/multiarray/multiarraymodule.c | 3 |
4 files changed, 126 insertions, 64 deletions
diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c index 01bf9cd74..4787c6482 100644 --- a/numpy/core/src/multiarray/common.c +++ b/numpy/core/src/multiarray/common.c @@ -27,6 +27,60 @@ * be allowed under the NPY_SAME_KIND_CASTING rules, and if not we issue a * warning (that people's code will be broken in a future release.) */ + +/* + * PyArray_GetAttrString_SuppressException: + * + * Stripped down version of PyObject_GetAttrString, + * avoids lookups for None, tuple, and List objects, + * and doesn't create a PyErr since this code ignores it. + * + * This can be much faster then PyObject_GetAttrString where + * exceptions are not used by caller. + * + * 'obj' is the object to search for attribute. + * + * 'name' is the attribute to search for. + * + * Returns attribute value on success, 0 on failure. + */ +PyObject * +PyArray_GetAttrString_SuppressException(PyObject *obj, char *name) +{ + PyTypeObject *tp = Py_TYPE(obj); + PyObject *res = (PyObject *)NULL; + if (/* Is not trivial type */ + obj != Py_None && + !PyList_CheckExact(obj) && + !PyTuple_CheckExact(obj)) { + /* Attribute referenced by (char *)name */ + if (tp->tp_getattr != NULL) { + res = (*tp->tp_getattr)(obj, name); + if (res == NULL) { + PyErr_Clear(); + } + } + /* Attribute referenced by (PyObject *)name */ + else if (tp->tp_getattro != NULL) { +#if defined(NPY_PY3K) + PyObject *w = PyUnicode_InternFromString(name); +#else + PyObject *w = PyString_InternFromString(name); +#endif + if (w == NULL) + return (PyObject *)NULL; + Py_DECREF(w); + res = (*tp->tp_getattro)(obj, w); + if (res == NULL) { + PyErr_Clear(); + } + } + } + return res; +} + + + NPY_NO_EXPORT NPY_CASTING NPY_DEFAULT_ASSIGN_CASTING = NPY_INTERNAL_UNSAFE_CASTING_BUT_WARN_UNLESS_SAME_KIND; @@ -156,8 +210,17 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims, goto promote_types; } + /* See if it's a python None */ + if (obj == Py_None) { + dtype = PyArray_DescrFromType(NPY_OBJECT); + if (dtype == NULL) { + goto fail; + } + Py_INCREF(dtype); + goto promote_types; + } /* Check if it's a NumPy scalar */ - if (PyArray_IsScalar(obj, Generic)) { + else if (PyArray_IsScalar(obj, Generic)) { if (!string_type) { dtype = PyArray_DescrFromScalar(obj); if (dtype == NULL) { @@ -308,32 +371,35 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims, } /* PEP 3118 buffer interface */ - memset(&buffer_view, 0, sizeof(Py_buffer)); - if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_FORMAT|PyBUF_STRIDES) == 0 || - PyObject_GetBuffer(obj, &buffer_view, PyBUF_FORMAT) == 0) { - - PyErr_Clear(); - dtype = _descriptor_from_pep3118_format(buffer_view.format); - PyBuffer_Release(&buffer_view); - if (dtype) { + if (PyObject_CheckBuffer(obj) == 1) { + memset(&buffer_view, 0, sizeof(Py_buffer)); + if (PyObject_GetBuffer(obj, &buffer_view, + PyBUF_FORMAT|PyBUF_STRIDES) == 0 || + PyObject_GetBuffer(obj, &buffer_view, PyBUF_FORMAT) == 0) { + + PyErr_Clear(); + dtype = _descriptor_from_pep3118_format(buffer_view.format); + PyBuffer_Release(&buffer_view); + if (dtype) { + goto promote_types; + } + } + else if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_STRIDES) == 0 || + PyObject_GetBuffer(obj, &buffer_view, PyBUF_SIMPLE) == 0) { + + PyErr_Clear(); + dtype = PyArray_DescrNewFromType(NPY_VOID); + dtype->elsize = buffer_view.itemsize; + PyBuffer_Release(&buffer_view); goto promote_types; } - } - else if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_STRIDES) == 0 || - PyObject_GetBuffer(obj, &buffer_view, PyBUF_SIMPLE) == 0) { - - PyErr_Clear(); - dtype = PyArray_DescrNewFromType(NPY_VOID); - dtype->elsize = buffer_view.itemsize; - PyBuffer_Release(&buffer_view); - goto promote_types; - } - else { - PyErr_Clear(); + else { + PyErr_Clear(); + } } /* The array interface */ - ip = PyObject_GetAttrString(obj, "__array_interface__"); + ip = PyArray_GetAttrString_SuppressException(obj, "__array_interface__"); if (ip != NULL) { if (PyDict_Check(ip)) { PyObject *typestr; @@ -364,12 +430,9 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims, } Py_DECREF(ip); } - else { - PyErr_Clear(); - } /* The array struct interface */ - ip = PyObject_GetAttrString(obj, "__array_struct__"); + ip = PyArray_GetAttrString_SuppressException(obj, "__array_struct__"); if (ip != NULL) { PyArrayInterface *inter; char buf[40]; @@ -389,9 +452,6 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims, } Py_DECREF(ip); } - else { - PyErr_Clear(); - } /* The old buffer interface */ #if !defined(NPY_PY3K) @@ -407,7 +467,9 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims, #endif /* The __array__ attribute */ - if (PyObject_HasAttrString(obj, "__array__")) { + ip = PyArray_GetAttrString_SuppressException(obj, "__array__"); + if (ip != NULL) { + Py_DECREF(ip); ip = PyObject_CallMethod(obj, "__array__", NULL); if(ip && PyArray_Check(ip)) { dtype = PyArray_DESCR((PyArrayObject *)ip); diff --git a/numpy/core/src/multiarray/common.h b/numpy/core/src/multiarray/common.h index a474cf820..68f8d246d 100644 --- a/numpy/core/src/multiarray/common.h +++ b/numpy/core/src/multiarray/common.h @@ -25,6 +25,9 @@ NPY_NO_EXPORT int PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims, PyArray_Descr **out_dtype, int string_status); +NPY_NO_EXPORT PyObject * +PyArray_GetAttrString_SuppressException(PyObject *v, char *name); + /* * Returns NULL without setting an exception if no scalar is matched, a * new dtype reference otherwise. diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index 5c692bd02..c96258417 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -646,32 +646,35 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it, /* obj is a PEP 3118 buffer */ #if PY_VERSION_HEX >= 0x02060000 /* PEP 3118 buffer interface */ - memset(&buffer_view, 0, sizeof(Py_buffer)); - if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_STRIDES) == 0 || - PyObject_GetBuffer(obj, &buffer_view, PyBUF_ND) == 0) { - int nd = buffer_view.ndim; - if (nd < *maxndim) { - *maxndim = nd; + if (PyObject_CheckBuffer(obj) == 1) { + memset(&buffer_view, 0, sizeof(Py_buffer)); + if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_STRIDES) == 0 || + PyObject_GetBuffer(obj, &buffer_view, PyBUF_ND) == 0) { + int nd = buffer_view.ndim; + if (nd < *maxndim) { + *maxndim = nd; + } + for (i=0; i<*maxndim; i++) { + d[i] = buffer_view.shape[i]; + } + PyBuffer_Release(&buffer_view); + return 0; } - for (i=0; i<*maxndim; i++) { - d[i] = buffer_view.shape[i]; + else if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_SIMPLE) == 0) { + d[0] = buffer_view.len; + *maxndim = 1; + PyBuffer_Release(&buffer_view); + return 0; + } + else { + PyErr_Clear(); } - PyBuffer_Release(&buffer_view); - return 0; - } - else if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_SIMPLE) == 0) { - d[0] = buffer_view.len; - *maxndim = 1; - PyBuffer_Release(&buffer_view); - return 0; - } - else { - PyErr_Clear(); } #endif /* obj has the __array_struct__ interface */ - if ((e = PyObject_GetAttrString(obj, "__array_struct__")) != NULL) { + e = PyArray_GetAttrString_SuppressException(obj, "__array_struct__"); + if (e != NULL) { int nd = -1; if (NpyCapsule_Check(e)) { PyArrayInterface *inter; @@ -693,12 +696,10 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it, return 0; } } - else { - PyErr_Clear(); - } /* obj has the __array_interface__ interface */ - if ((e = PyObject_GetAttrString(obj, "__array_interface__")) != NULL) { + e = PyArray_GetAttrString_SuppressException(obj, "__array_interface__"); + if (e != NULL) { int nd = -1; if (PyDict_Check(e)) { PyObject *new; @@ -728,9 +729,6 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it, return 0; } } - else { - PyErr_Clear(); - } n = PySequence_Size(obj); @@ -1934,9 +1932,8 @@ PyArray_FromStructInterface(PyObject *input) PyArrayObject *ret; char endian = NPY_NATBYTE; - attr = PyObject_GetAttrString(input, "__array_struct__"); + attr = PyArray_GetAttrString_SuppressException(input, "__array_struct__"); if (attr == NULL) { - PyErr_Clear(); return Py_NotImplemented; } if (!NpyCapsule_Check(attr)) { @@ -2009,9 +2006,9 @@ PyArray_FromInterface(PyObject *origin) /* Get the memory from __array_data__ and __array_offset__ */ /* Get the strides */ - iface = PyObject_GetAttrString(origin, "__array_interface__"); + iface = PyArray_GetAttrString_SuppressException(origin, + "__array_interface__"); if (iface == NULL) { - PyErr_Clear(); return Py_NotImplemented; } if (!PyDict_Check(iface)) { @@ -2226,9 +2223,8 @@ PyArray_FromArrayAttr(PyObject *op, PyArray_Descr *typecode, PyObject *context) PyObject *new; PyObject *array_meth; - array_meth = PyObject_GetAttrString(op, "__array__"); + array_meth = PyArray_GetAttrString_SuppressException(op, "__array__"); if (array_meth == NULL) { - PyErr_Clear(); return Py_NotImplemented; } if (context == NULL) { diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index 7332a26d0..426ab695c 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -52,6 +52,7 @@ NPY_NO_EXPORT int NPY_NUMUSERTYPES = 0; #include "shape.h" #include "ctors.h" #include "array_assign.h" +#include "common.h" /* Only here for API compatibility */ NPY_NO_EXPORT PyTypeObject PyBigArray_Type; @@ -68,7 +69,7 @@ PyArray_GetPriority(PyObject *obj, double default_) if (PyArray_CheckExact(obj)) return priority; - ret = PyObject_GetAttrString(obj, "__array_priority__"); + ret = PyArray_GetAttrString_SuppressException(obj, "__array_priority__"); if (ret != NULL) { priority = PyFloat_AsDouble(ret); } |