I am experimenting with some 3d rendering in Python. I keep reading that Python is soooooooo very slow! I simply MUST harness the C-awesomeness of Numpy for all the matrix stuff I can’t do in the shaders! Otherwise nothing will work, yadda, yadda (paraphrasing here..).
BUT: I did some testing!
Here’s a random matrix, once in Numpy-flavour:
matrix1 = numpy.matrix([[1, 1, 0, 0,], [0, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]])
>>> matrix([[1, 1, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 1],
[0, 0, 0, 1]])
and once as a bog-standard tuple:
matrix2 = (1, 1, 0, 0,\
0, 1, 0, 0,\
0, 0, 1, 1,\
0, 0, 0, 1)
Now, if I want the inverse of that, I can either do it in Numpy:
def inv_1():
return matrix1.I
or as pure Python (I omitted some of the maths because it hurts my head):
def inv_2():
m0, m1, m2, m3, \
m4, m5, m6, m7, \
m8, m9, m10, m11, \
m12, m13, m14, m15 = matrix2
A0 = (( m0 * m5) - ( m1 * m4)) ....
...B5 = ((m10 * m15) - (m11 * m14))
det = 1.0 / det
return (
(+ ( m5 * B5) - ( m6 * B4) + ( m7 * B3)) * det, ...
...(+ ( m8 * A3) - ( m9 * A1) + (m10 * A0)) * det
)
both work fine:
inv_1()
>>>> matrix([[ 1., -1., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., -1.],
[ 0., 0., 0., 1.]])
inv_2()
>>>> (1.0, -1.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, -1.0,
0.0, 0.0, 0.0, 1.0) (I added the line-breaks here for clarity)
But the pure Python code runs consistently about ten times faster than the highly praised Numpy:
timeit.timeit(inv_1, number=100000)
>>>> 3.0659120082855225
timeit.timeit(inv_2, number=100000)
>>>> 0.4014430046081543
And if you add the overhead of converting my beautiful tuple-matrices into Numpy matrices it will be even slower.
So what’s going on here? Am I doing something wrong? Is it all due to the overhead of invoking a C-function? Did the guy who’s inversion-code I stole break the laws of physics?
Thanks for de-noobing me! Love you all!
You’re inverting the matrix analytically (which is possible since you know the dimensions and since they’re not too big). numpy must invert the matrix using some other (numerical) algorithm which works if the matrix is 4×4 as well as 10000×10000. In other words, the general problem is much harder than the simple 4×4 case that you have.