Commit 2bb1e147 authored by Robert Bradshaw's avatar Robert Bradshaw

More work on quickstart.

--HG--
rename : src/tutorial/htmlreport.png => src/quickstart/htmlreport.png
parent 6e0a3823
......@@ -20,7 +20,8 @@ point types, complex numbers, structs, unions and pointer types.
Cython can automatically and correctly convert between the types on
assignment. This also includes Python's arbitrary size integer types,
where value overflows on conversion to a C type will raise a Python
``OverflowError`` at runtime. The generated C code will handle the
``OverflowError`` at runtime. (It does not, however, check for overflow
when doing arithmetic.) The generated C code will handle the
platform dependent sizes of C types correctly and safely in this case.
Types are declared via the cdef keyword.
......@@ -31,10 +32,8 @@ Typing Variables
Consider the following pure Python code::
from math import sin
def f(x):
return sin(x**2)
return x**2-x
def integrate_f(a, b, N):
s = 0
......@@ -43,16 +42,14 @@ Consider the following pure Python code::
s += f(a+i*dx)
return s * dx
Simply compiling this in Cython merely gives a 5% speedup. This is
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
difference.
With additional type declarations, this might look like::
from math import sin
def f(double x):
return sin(x**2)
return x**2-x
def integrate_f(double a, double b, int N):
cdef int i
......@@ -69,7 +66,7 @@ in arithmetic withing the for-loop; typing ``b`` and ``N`` makes less of a
difference, but in this case it is not much extra work to be
consistent and type the entire function.
This results in a 24 times speedup over the pure Python version.
This results in a 4 times speedup over the pure Python version.
Typing Functions
----------------
......@@ -83,12 +80,15 @@ argument in order to pass it.
Therefore Cython provides a syntax for declaring a C-style function,
the cdef keyword::
cdef double f(double) except *:
return sin(x**2)
cdef double f(double) except? -2:
return x**2-x
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). Above ``except *`` is used which is always
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).
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.
......@@ -102,13 +102,25 @@ objects).
Note also that it is no longer possible to change ``f`` at runtime.
Speedup: 45 times over pure Python.
Speedup: 150 times over pure Python.
.. figure:: htmlreport.png
Determining where to add types
------------------------------
Using the ``-a`` switch to the ``cython`` command line program (or
following a link from the Sage notebook) results in an HTML report
of Cython code interleaved with the generated C code. Lines are
colored according to the level of "typedness" -- white lines
translates to pure C without any Python API calls. This report
is invaluable when optimizing a function for speed.
Because static typing is often the key to large speed gains, beginners
often have a tendency to type everything in site. This cuts down on both
readability and flexibility. On the other hand, it is easy to kill
performance by forgetting to type a critical loop variable. Two essential
tools to help with this task are profiling and annotation.
Profiling should be the first step of any optimization effort, and can
tell you where you are spending your time. Cython's annotation can then
tell you why your code is taking time.
Using the ``-a`` switch to the ``cython`` command line program (or
following a link from the Sage notebook) results in an HTML report
of Cython code interleaved with the generated C code. Lines are
colored according to the level of "typedness" -- white lines
translates to pure C without any Python API calls. This report
is invaluable when optimizing a function for speed.
.. figure:: htmlreport.png
from time import time
from math import sin
cdef double first_time = 0
def timeit(f, label):
global first_time
t = time()
f(1.0, 2.0, 10**7)
cdef double elapsed = time() - t
if first_time == 0:
first_time = elapsed
print label, elapsed, (100*elapsed/first_time), '% or', first_time/elapsed, 'x'
# Pure Python
py_funcs = {'sin': sin}
py_funcs.update(__builtins__.__dict__)
exec """
def f(x):
return x**2-x
def integrate_f(a, b, N):
s = 0
dx = (b-a)/N
for i in range(N):
s += f(a+i*dx)
return s * dx
""" in py_funcs
timeit(py_funcs['integrate_f'], "Python")
# Just compiled
def f0(x):
return x**2-x
def integrate_f0(a, b, N):
s = 0
dx = (b-a)/N
for i in range(N):
s += f0(a+i*dx)
return s * dx
timeit(integrate_f0, "Cython")
# Typed vars
def f1(double x):
return x**2-x
def integrate_f1(double a, double b, int N):
cdef int i
cdef double s, dx
s = 0
dx = (b-a)/N
for i in range(N):
s += f1(a+i*dx)
return s * dx
timeit(integrate_f1, "Typed vars")
# Typed func
cdef double f2(double x) except? -2:
return x**2-x
def integrate_f2(double a, double b, int N):
cdef int i
cdef double s, dx
s = 0
dx = (b-a)/N
for i in range(N):
s += f2(a+i*dx)
return s * dx
timeit(integrate_f2, "Typed func")
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment