On Mon, Dec 20, 2010 at 12:27 PM, Jason Grout <[email protected]> wrote: > On 12/20/10 1:42 PM, Simon King wrote: >> >> Dear sage-support, >> >> at #10496, David Roe gave me the advice to use PY_TYPE_CHECK rather >> than isinstance in Cython files. I did so. >> >> But actually I didn't know PY_TYPE_CHECK at all, and so I have a two >> questions: >> >> 1) Apparently there are several PY_... functions. Where can I read >> about them? > > > I see them imported in devel/sage/sage/ext/stdsage.pxi: > > ----------------------- > cdef extern from "stdsage.h": > ctypedef void PyObject > > # Global tuple -- useful optimization > void init_global_empty_tuple() > object PY_NEW(object t) > object PY_NEW_SAME_TYPE(object t) > > void* PY_TYPE(object o) > bint PY_TYPE_CHECK(object o, object t) > bint PY_TYPE_CHECK_EXACT(object o, object t) > > object IS_INSTANCE(object o, object t) > void PY_SET_TP_NEW(object t1, object t2) > bint HAS_DICTIONARY(object o) > bint PY_IS_NUMERIC(object o) > ----------------------- > > > The stdsage.h file is in devel/sage/c_lib/include/stdsage.h, where we find: > > ----------------------- > /** Tests whether zzz_obj is of type zzz_type. The zzz_type must be a > * built-in or extension type. This is just a C++-compatible wrapper > * for PyObject_TypeCheck. > */ > #define PY_TYPE_CHECK(zzz_obj, zzz_type) \ > (PyObject_TypeCheck((PyObject*)(zzz_obj), (PyTypeObject*)(zzz_type))) > ----------------------- > > in fact, we find later on: > > ----------------------- > > /** This is exactly the same as isinstance (and does return a Python > * bool), but the second argument must be a C-extension type -- so it > * can't be a Python class or a list. If you just want an int return > * value, i.e., aren't going to pass this back to Python, just use > * PY_TYPE_CHECK. > */ > #define IS_INSTANCE(zzz_obj, zzz_type) \ > PyBool_FromLong(PY_TYPE_CHECK(zzz_obj, zzz_type)) > ----------------------- > > > ...interpret how you will.... > > > >> >> 2) Is PY_TYPE_CHECK really quicker than isinstance? >> >> It doesn't seem so, actually. >> >> In testtype.pyx, I wrote >> cpdef t1(x): >> return PY_TYPE_CHECK(x,int) >> cpdef t2(x): >> return isinstance(x,int) >> >> >> Then, I got the following timings: >> {{{ >> sage: attach typecheck.pyx >> Compiling typecheck.pyx... >> sage: t1(5) >> False >> sage: t1(int(5)) >> True >> sage: t2(5) >> False >> sage: t2(int(5)) >> True >> sage: timeit("a=t1(5)") >> 625 loops, best of 3: 218 ns per loop >> sage: timeit("a=t2(5)") >> 625 loops, best of 3: 205 ns per loop >> sage: timeit("a=t1(int(5))") >> 625 loops, best of 3: 416 ns per loop >> sage: timeit("a=t2(int(5))") >> 625 loops, best of 3: 401 ns per loop >> }}} >> >> So, actually isinstance is slightly quicker than PY_TYPE_CHECK. Or do >> I misunderstand something? > > > > I notice in the generated C code, Cython is smart and makes isinstance > actually call PyInt_Check, which presumably is faster than PY_TYPE_CHECK. > > If instead, you are checking for the Integer type, I get faster numbers for > PY_TYPE_CHECK than isinstance. I also tried to lessen the effects of python > call overhead by running the call in a loop in Cython: > http://demo.sagenb.org/home/pub/65/
if you do "from sage.rings.integer cimport Integer" the speed difference should go away. - Robert -- To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/sage-support URL: http://www.sagemath.org
