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

Reply via email to