The PY_TYPE_CHECK macro exists primarily because Cython didn't used to
optimize isinstance.

On Mon, Dec 20, 2010 at 12:34 PM, Volker Braun <vbraun.n...@gmail.com> wrote:
> PY_TYPE_CHECK is just a wrapper macro around PyObject_TypeCheck which
> dereferences and compares the object type fields. So that part should be
> insanely fast.

If A is a cdef'd type (which is the precondition for using
PY_TYPE_CHECK), then "isinstance(x, A)" produces exactly the same code
as "PY_TYPE_CHECK(x, A)" (a single inline call to PyObject_TypeCheck).
Thus I'd say it's better to use the Pythonic isinstance. For some
builtins it can use even more specialized code.

> sage: cython('cpdef t(x):\n  for i in range(0,1000):\n
>  PY_TYPE_CHECK(x,int)'); timeit("t(5000)", repeat=100)
> 625 loops, best of 100: 14.1 µs per loop
> sage: cython('cpdef t(x):\n  for i in range(0,1000):\n
>  PY_TYPE_CHECK(x,float)'); timeit("t(5000)", repeat=100)
> 625 loops, best of 100: 14.1 µs per loop
> sage: cython('cpdef t(x):\n  for i in range(0,1000):\n
>  isinstance(x,int)'); timeit("t(5000)", repeat=100)
> 625 loops, best of 100: 182 ns per loop
> sage: cython('cpdef t(x):\n  for i in range(0,1000):\n
>  isinstance(x,float)'); timeit("t(5000)", repeat=100)
> 625 loops, best of 100: 14.1 µs per loop
> It seems like isinstance and PY_TYPE_CHECK are equally fast, except that
> isinstance caches the result if it was positive.
> But if you really write Cython code then you probably want to type the
> argument so that the compiler knows what x is. Then I get
> sage: cython('cpdef t(int x):\n  for i in range(0,1000):\n
>  PY_TYPE_CHECK(x,int)'); timeit("t(5000)", repeat=100)
> 625 loops, best of 100: 7.72 µs per loop
> sage: cython('cpdef t(int x):\n  for i in range(0,1000):\n
>  PY_TYPE_CHECK(x,float)'); timeit("t(5000)", repeat=100)
> 625 loops, best of 100: 12 µs per loop
> sage: cython('cpdef t(int x):\n  for i in range(0,10000):\n
>  isinstance(x,int)'); timeit("t(5000)", repeat=100)
> 625 loops, best of 100: 111 µs per loop
> sage: cython('cpdef t(int x):\n  for i in range(0,10000):\n
>  isinstance(x,float)'); timeit("t(5000)", repeat=100)
> 625 loops, best of 100: 118 µs per loop
> Now isinstance is a lot slower, while PY_TYPE_CHECK got moderately faster. I
> guess isinstance calls from C into Python while the PY_TYPE_CHECK stays in
> C?

No, it's because your loop is over 10000 rather than 1000.

- Robert

-- 
To post to this group, send email to sage-support@googlegroups.com
To unsubscribe from this group, send email to 
sage-support+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sage-support
URL: http://www.sagemath.org

Reply via email to