Introduction to Pyrex September 2002 Brian Quinlan [email protected].

16
Introduction to Pyrex http://www.sweetapp.com/pyrex September 2002 Brian Quinlan [email protected]

Transcript of Introduction to Pyrex September 2002 Brian Quinlan [email protected].

Page 1: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Introduction to Pyrexhttp://www.sweetapp.com/pyrex

September 2002

Brian Quinlan

[email protected]

Page 2: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 2 ©2002 Brian Quinlan

What is Pyrex?

• Pyrex is a language for writing Python extension modules

• Pyrex has a Python-like syntax that gets compiled into C code

• Pyrex let’s you mix Python and C data types and function calls freely

Brian Quinlan
This slide sucks. Would be nice to make points 2 and 3 more integrated and logical
Page 3: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 3 ©2002 Brian Quinlan

The perfect example

• Let’s compute perfect numbers!

• Perfect numbers are number whose positive divisors (except for itself) sum to itself

e.g. 6 is a perfect number because:

1 x 6 = 6

2 x 3 = 6

1 + 2 + 3 = 6

• Naïve methods of computing perfect numbers are slow – so let’s use one and optimize

Page 4: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 4 ©2002 Brian Quinlan

The Python code

from math import sqrt, ceil

from operator import add

def _calculate_factors(x):

factors = [1]

sqrt_x = int(ceil(sqrt(x)))

for i in xrange(2, sqrt_x):

if x % i == 0:

factors.append(i)

factors.append(x / i)

if sqrt_x ** 2 == x: factors.append(sqrt_x)

return factors

def is_perfect(x):

return reduce(add, _calculate_factors(x), 0) == x

Page 5: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 5 ©2002 Brian Quinlan

The Pyrex code

from math import sqrt, ceil

from operator import add

def _calculate_factors(x):

factors = [1]

sqrt_x = int(ceil(sqrt(x)))

for i in xrange(2, sqrt_x):

if x % i == 0:

factors.append(i)

factors.append(x / i)

if sqrt_x ** 2 == x: factors.append(sqrt_x)

return factors

def is_perfect(x):

return reduce(add, _calculate_factors(x), 0) == x

Page 6: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 6 ©2002 Brian Quinlan

Pyrex is VERY like Python

• Pyrex syntax is VERY similar to Python syntax

• Running the same code using Pyrex is about 15% faster

• There are Pyrex-specific features that allow us to improve the performance even more

Page 7: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 7 ©2002 Brian Quinlan

Use C types

from math import sqrt, ceil

from operator import add

def _calculate_factors(int x):

cdef int sqrt_x, i

factors = [1]

sqrt_x = ceil(sqrt(x))

for i in xrange(2, sqrt_x):

if x % i == 0:

factors.append(i)

factors.append(x / i)

if sqrt_x ** 2 == x: factors.append(sqrt_x)

return factors

def is_perfect(int x):

return reduce(add, _calculate_factors(x), 0) == x

Page 8: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 8 ©2002 Brian Quinlan

Use a Pyrex “for” construct

from math import sqrt, ceil

from operator import add

def _calculate_factors(int x):

cdef int sqrt_x, i

factors = [1]

sqrt_x = ceil(sqrt(x))

for i from 2 <= i < sqrt_x:

if x % i == 0:

factors.append(i)

factors.append(x / i)

if sqrt_x ** 2 == x: factors.append(sqrt_x)

return factors

def is_perfect(int x):

return reduce(add, _calculate_factors(x), 0) == x

Page 9: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 9 ©2002 Brian Quinlan

Use the C math library

cdef extern from "math.h":

double sqrt(double x)

double ceil(double x)

from operator import add

def _calculate_factors(int x):

cdef int sqrt_x, i

factors = [1]

sqrt_x = ceil(sqrt(x))

for i from 2 <= i < sqrt_x:

if x % i == 0:

factors.append(i)

factors.append(x / i)

Page 10: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 10 ©2002 Brian Quinlan

Use C functions

cdef extern from "math.h":

from operator import add

cdef object _calculate_factors(int x):

cdef int sqrt_x, i

factors = [1]

sqrt_x = ceil(sqrt(x))

for i from 2 <= i < sqrt_x:

if x % i == 0:

factors.append(i)

factors.append(x / i)

if sqrt_x ** 2 == x: factors.append(sqrt_x)

return factors

Page 11: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 11 ©2002 Brian Quinlan

Do our own summation

def is_perfect(int x):

cdef int sum

cdef int i

sum = 0

for i in _calculate_factors(x):

sum = sum + i

return sum == x

Page 12: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 12 ©2002 Brian Quinlan

Results

6.81

5.96

3.58

2.21.92 1.79

1.38

0

1

2

3

4

5

6

7

Time(s)

Pyt

ho

n

Pyr

ex

+ cd

efs

+ fo

r

+ m

ath

+ fu

nc

+ su

m

Page 13: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 13 ©2002 Brian Quinlan

A vector class

cdef class Vector3:

cdef double x

cdef double y

cdef double z

def __init__(self, double x, double y, double z):

self.x, self.y, self.z = x, y, z

Page 14: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 14 ©2002 Brian Quinlan

Getting it’s attributes

def __getattr__(self, name):

if name == 'x':

return self.x

elif name == 'y':

return self.y

elif name == 'z':

return self.z

else:

raise AttributeError(

'Vector3 has no attribute "%s"' % name

)

Page 15: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 15 ©2002 Brian Quinlan

Some operations

def __add__(Vector3 a, Vector3 b):

return Vector3(a.x + b.x, a.y + b.y, a.z + b.z)

cdef int __nonzero__(Vector3 self):

return self.x or self.y or self.z

def __str__(self):

return 'Vector3(x=%s, y=%s, z=%s)' % (

self.x, self.y, self.z)

def __repr__(self): # __repr__ = __str__ not allowed

return 'Vector3(x=%r, y=%r, z=%r)' % (

self.x, self.y, self.z)

Page 16: Introduction to Pyrex  September 2002 Brian Quinlan brian@sweetapp.com.

Slide 16 ©2002 Brian Quinlan

Using Pyrex

• The hassle-factor is low (easy to install Pyrex, easy to get Pyrex to compile your code - so long as you have a C compiler)

• Documentation is minimal but understandable

• Writing simple functions using Pyrex features is easy (though there are a few gotchas)

• Writing classes is harder (more gotches, more bugs, more unfinished features)

• C and the Python C API has more gotches than Pyrex