Introduction IPython notebook, using compute $\pi$ example

To be read together with the slides (Hans Fangohr, FEEG6002, 2015)

We use a smaller number N in comparison to the slides as the convenient %timeit magic does a great job in obtaining meaningful timings for statements that execute fairly fast.

In [72]:
N = 100000
In [73]:
import math
def f(x):
    return math.sqrt(1. - x * x)

def pi(n):
    s = 0.5 * (f(-1) + f(1))
    h = 2. / n
    for i in range(1, n):
        x = -1 + i * h
        s += f(x)
    return s * h * 2
In [74]:
tbase = %timeit -o pi(N)
10 loops, best of 3: 43 ms per loop

Note: we have execution time available in the variable tbase.best (in seconds):

In [75]:
tbase.best
Out[75]:
0.04304039478302002

Inline function f

In [76]:
def pi_inline(n):
    s = 0.5 * (f(-1) + f(1))
    h = 2. / n
    for i in range(1, n):
        x = -1 + i * h
        s += math.sqrt(1. - x * x)
    return s * h * 2
In [77]:
tinline = %timeit -o pi_inline(N)
10 loops, best of 3: 32.2 ms per loop
In [78]:
print("inlined function code is {:5.1f} times faster than pure python ".format(
        tbase.best / tinline.best))
inlined function code is   1.3 times faster than pure python 

Using Numpy

In [79]:
import numpy as np
In [80]:
def pi_numpy(n):
    h = 2. / n
    xs = np.linspace(-1, 1, n)
    ys = np.sqrt(1 - xs * xs)
    return np.sum(ys) * h * 2
In [81]:
tnumpy = %timeit -o pi_numpy(N)
1000 loops, best of 3: 720 µs per loop
In [82]:
print("numpy code is {:5.1f} times faster than pure python ".format(
        tbase.best / tnumpy.best))
numpy code is  59.8 times faster than pure python 

Using weave

In [83]:
import scipy.weave as weave
In [84]:
def pi_weave(n):
    my_C_code = """
	  double s=0;       /* this is C code */ 
	  double h=2./n;      /* in a string    */
	  double x;
	  long i;
	  for (i=1; i<n; i++) {
	    x = -1+i*h;
	    s += sqrt(1.-x*x);
	  }
	  return_val = s*h*2;  /* last line C code */
	"""
    return weave.inline(my_C_code, ['n'], compiler='gcc')
In [85]:
tweave = %timeit -o pi_weave(N)
1000 loops, best of 3: 548 µs per loop
In [86]:
print("weave code (essentially c) is {:5.1f} times faster than pure python ".format(
        tbase.best / tweave.best))
weave code (essentially c) is  78.5 times faster than pure python 

Report results

In [87]:
results = {'simple' : tbase, 
          'inline_f': tinline,
          'numpy' : tnumpy,
          'weave' : tweave}

time_base = tbase.best
for method in results.keys():
    time_ = results[method].best 
    print("{:10} took {:10.5f}ms, speed up of {:6.6f}".format(
        method, time_*1000, time_base / time_ ))
simple     took   43.04039ms, speed up of 1.000000
inline_f   took   32.23901ms, speed up of 1.335041
numpy      took    0.72005ms, speed up of 59.773831
weave      took    0.54803ms, speed up of 78.535966

Exercise

Try to change the number N to see how the speed up changes as the computation required changes. Can you explain what you see?