diff options
Diffstat (limited to 'docs/src/quickstart/cythonize.rst')
-rw-r--r-- | docs/src/quickstart/cythonize.rst | 63 |
1 files changed, 50 insertions, 13 deletions
diff --git a/docs/src/quickstart/cythonize.rst b/docs/src/quickstart/cythonize.rst index 22cad0470..d4895e10d 100644 --- a/docs/src/quickstart/cythonize.rst +++ b/docs/src/quickstart/cythonize.rst @@ -1,6 +1,9 @@ Faster code via static typing ============================= +.. include:: + ../two-syntax-variants-used + Cython is a Python compiler. This means that it can compile normal Python code without changes (with a few obvious exceptions of some as-yet unsupported language features, see :ref:`Cython limitations<cython-limitations>`). @@ -33,6 +36,7 @@ Typing Variables Consider the following pure Python code: .. literalinclude:: ../../examples/quickstart/cythonize/integrate.py + :caption: integrate.py Simply compiling this in Cython merely gives a 35% speedup. This is better than nothing, but adding some static types can make a much larger @@ -40,7 +44,17 @@ difference. With additional type declarations, this might look like: -.. literalinclude:: ../../examples/quickstart/cythonize/integrate_cy.pyx +.. tabs:: + + .. group-tab:: Pure Python + + .. literalinclude:: ../../examples/quickstart/cythonize/integrate_cy.py + :caption: integrate_cy.py + + .. group-tab:: Cython + + .. literalinclude:: ../../examples/quickstart/cythonize/integrate_cy.pyx + :caption: integrate_cy.pyx Since the iterator variable ``i`` is typed with C semantics, the for-loop will be compiled to pure C code. Typing ``a``, ``s`` and ``dx`` is important as they are involved @@ -55,27 +69,40 @@ Typing Functions Python function calls can be expensive -- in Cython doubly so because one might need to convert to and from Python objects to do the call. -In our example above, the argument is assumed to be a C double both inside f() +In our example above, the argument is assumed to be a C double both inside ``f()`` and in the call to it, yet a Python ``float`` object must be constructed around the argument in order to pass it. -Therefore Cython provides a syntax for declaring a C-style function, -the cdef keyword: +Therefore, Cython provides a way for declaring a C-style function, +the Cython specific ``cdef`` statement, as well as the ``@cfunc`` decorator to +declare C-style functions in Python syntax. Both approaches are +equivalent and produce the same C code: + +.. tabs:: + + .. group-tab:: Pure Python + + .. literalinclude:: ../../examples/quickstart/cythonize/cdef_keyword.py -.. literalinclude:: ../../examples/quickstart/cythonize/cdef_keyword.pyx + .. group-tab:: Cython + + .. literalinclude:: ../../examples/quickstart/cythonize/cdef_keyword.pyx Some form of except-modifier should usually be added, otherwise Cython will not be able to propagate exceptions raised in the function (or a function it calls). The ``except? -2`` means that an error will be checked for if ``-2`` is returned (though the ``?`` indicates that ``-2`` may also -be used as a valid return value). +be used as a valid return value). The same can be expressed using only Python +syntax with the decorator ``@exceptval(-2, check=True)``. + Alternatively, the slower ``except *`` is always safe. An except clause can be left out if the function returns a Python object or if it is guaranteed that an exception will not be raised -within the function call. +within the function call. Again, Cython provides the decorator ``@exceptval(check=True)`` +providing the same functionality. -A side-effect of cdef is that the function is no longer available from -Python-space, as Python wouldn't know how to call it. It is also no +A side-effect of ``cdef`` (and the ``@cfunc`` decorator) is that the function is no longer +visible from Python-space, as Python wouldn't know how to call it. It is also no longer possible to change :func:`f` at runtime. Using the ``cpdef`` keyword instead of ``cdef``, a Python wrapper is also @@ -84,7 +111,8 @@ typed values directly) and from Python (wrapping values in Python objects). In fact, ``cpdef`` does not just provide a Python wrapper, it also installs logic to allow the method to be overridden by python methods, even when called from within cython. This does add a tiny overhead compared to ``cdef`` -methods. +methods. Again, Cython provides a ``@ccall`` decorator which provides the same +functionality as ``cpdef`` keyword. Speedup: 150 times over pure Python. @@ -115,10 +143,20 @@ Lines that translate to C code have a plus (``+``) in front and can be clicked to show the generated code. This report is invaluable when optimizing a function for speed, -and for determining when to :ref:`release the GIL <nogil>`: +and for determining when it is possible to :ref:`release the GIL <nogil>` +(be aware that releasing the GIL is only useful under limited +circumstances, see :ref:`cython_and_gil` for more details): in general, a ``nogil`` block may contain only "white" code. -.. figure:: htmlreport.png +.. tabs:: + + .. group-tab:: Pure Python + + .. figure:: htmlreport_py.png + + .. group-tab:: Cython + + .. figure:: htmlreport_pyx.png Note that Cython deduces the type of local variables based on their assignments (including as loop variable targets) which can also cut down on the need to @@ -135,4 +173,3 @@ with this language feature. It can be of great help to cut down on the need to t everything, but it also can lead to surprises. Especially if one isn't familiar with arithmetic expressions with c types. A quick overview of those can be found `here <https://www.eskimo.com/~scs/cclass/int/sx4cb.html>`_. - |