Brian Fisher wrote: > I love vector classes with operator overloading... I couldn't stand to > code without them (even though in python, it means there's probably a > lot of object allocation and function calls for simple vector math, > wasting performance). Code is just so much shorter & more readable > with them. I know that I pay for it in performance to use them, and I > know the one I use isn't the best performing one... I'll just wait to > care about that when it's a real problem. I did some back-of-the-envelope benchmarking of various implementations of Vector operations. Attached is the program that I used. My findings were: - Numeric is faster than map is faster than a list comprehension - explicitly storing two variables is even faster (not shown) - using functions from the operator module is faster than built-in math operators - tuples seem to be a little faster to iterate over than lists And some vector-unrelated findings: - function calls are faster than method calls - accessing a bound method is slower than accessing an instance variable In benchmarking my game, I found that I was creating a *lot* of new vector objects, and this does things to your performance. For this reason my vectors are not immutable, but take advantage of in-place operations to conserve objects. I found that it was rare that I needed to access individual elements of a vector, but implemented __iter__ by returning iter([x, y]). This was "good enough" and pretty straightforward. Ethan
s = '''from operator import sub
def add1(v1, v2):
return [a + b for (a, b) in zip(v1, v2)]
def sub1(v1, v2):
return [a - b for (a, b) in zip(v1, v2)]
def sub2(v1, v2):
return [sub(a,b) for (a, b) in zip(v1, v2)]
def sub3(v1, v2):
return map(sub, v1, v2)
v1a = [4.2, 5.4]
v1b = [12.0, -4.1]
v2a = (4.2, 5.4)
v2b = (12.0, -4.1)'''
import timeit
t = timeit.Timer()
print 'baseline', t.repeat()
for i in ['sub1', 'sub2', 'sub3']:
for j in [1, 2]:
t = timeit.Timer('a = %s(v%da,v%db)'%(i,j,j), s)
print i, j, t.repeat()
s2 = '''import Numeric
def sub4(v1, v2):
return Numeric.subtract(v1, v2)
v1a = Numeric.array([4.2, 5.4])
v1b = Numeric.array([12.0, -4.1])'''
t = timeit.Timer('a = sub4(v1a, v1b)', s2)
print 'numeric', t.repeat()
s3 = '''
class C(object):
x = None
def __init__(self):
pass
def f(self, o2):
pass
def g(self):
pass
def f(o1, o2):
pass
o1 = C()
o2 = C()'''
for i in ['o1.f(o2)', 'C.f(o1, o2)', 'f(o1, o2)']:
t = timeit.Timer(i, s3)
print i, t.repeat()
for i in ['o1.x', 'o1.g', 'o1.g()']:
t = timeit.Timer(i, s3)
print i, t.repeat()
Attachment:
signature.asc
Description: OpenPGP digital signature