More work on quickstart.
authorRobert Bradshaw <robertwb@math.washington.edu>
Thu, 12 Nov 2009 07:23:36 +0000 (23:23 -0800)
committerRobert Bradshaw <robertwb@math.washington.edu>
Thu, 12 Nov 2009 07:23:36 +0000 (23:23 -0800)
--HG--
rename : src/tutorial/htmlreport.png => src/quickstart/htmlreport.png

src/quickstart/cythonize.rst
src/quickstart/demo.pyx [new file with mode: 0644]
src/quickstart/htmlreport.png [moved from src/tutorial/htmlreport.png with 100% similarity]

index efc708b6b22c8aa2bb0338fc91f4a01fcc2e4523..f3fd52501cd7d6bc598c2620859b0be75d4da209 100644 (file)
@@ -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
diff --git a/src/quickstart/demo.pyx b/src/quickstart/demo.pyx
new file mode 100644 (file)
index 0000000..b1851ff
--- /dev/null
@@ -0,0 +1,81 @@
+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")