summaryrefslogtreecommitdiff
path: root/docs/src/quickstart/cythonize.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/src/quickstart/cythonize.rst')
-rw-r--r--docs/src/quickstart/cythonize.rst63
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>`_.
-