Optimisation problem

Skip Montanaro skip at pobox.com
Tue Nov 12 06:39:48 EST 2002


    Simon> I have created a quaternion class which I am using for rotations
    Simon> in OpenGL.
    ....
    Simon> Does anyone have any idea how I can optimise this code? It is
    Simon> going to be used in a very tight rendering loop. I would prefer
    Simon> to keep all the code in Python, and avoid writing any external
    Simon> modules.

That depends on a number of things.  Starting with the code itself and
sticking strictly to Python and using only eyeballs and a text editor (that
is, nearly no brain power ;-), you can eliminate some duplicate computations
and avoid a bunch of attribute references and a needless function call:

    from math import sin, cos
    class Quaternion:
        def __init__(self, degree, x, y, z):
            matrix = self.matrix = range(16)

            angle2 = degree * 0.0087266462599716477
            result = sin(angle2)

            self.w = cos(angle2)
            self.x = x * result
            self.y = y * result
            self.z = z * result

            # where __createMatrix() used to start...
            w,x,y,z = self.w, self.x, self.y, self.z
            zz = z*z
            yz = y*z
            yy = y*y
            xx = x*x
            xy = x*y
            xz = x*z
            wy = w*y
            wx = w*x
            wz = w*z
            matrix[0] = 1.0 - 2.0 * ( yy + zz )
            matrix[1] = 2.0 * ( xy - wz )
            matrix[2] = 2.0 * ( xz + wy )
            matrix[3] = 0.0

            matrix[4] = 2.0 * ( xy + wz )
            matrix[5] = 1.0 - 2.0 * ( xx + zz )
            matrix[6] = 2.0 * ( yz - wx )
            matrix[7] = 0.0

            matrix[8] = 2.0 * ( xz - wy )
            matrix[9] = 2.0 * ( yz + wx )
            matrix[10] = 1.0 - 2.0 * ( xx + yy )
            matrix[11] = 0.0

            matrix[12] = 0.0
            matrix[13] = 0.0
            matrix[14] = 0.0
            matrix[15] = 1.0

I believe that leaves the external interface of your Quaternion class intact
(its matrix, w, x, y, and z attributes should be the same as before) and
doesn't screw up the computation, but I didn't test the code.

To understand why these changes have any effect you need to understand a
little bit about the Python virtual machine.  It's worth running

    import dis
    dis.dis(Quaternion) 

before and after you make the above changes to see how the generated byte
code changes.

You might want to also check out any or all of

    Psyco:     http://psyco.sourceforge.net/
    PyInline:  http://pyinline.sourceforge.net/
    Weave:     http://www.scipy.org/
    Pyrex:     http://www.cosc.cantebury.ac.nz/~greg/python/Pyrex/

They all bend or break your "avoid writing any external modules" to a
greater or lesser degree, but are all worth investigating.  Psyco requires
next to no changes to your source code but is Pentium-specific.  PyInline
and Weave allow you to embed C/C++ code into your Python code and have them
compiled and linked on-the-fly.  Pyrex allows you to write extension modules
in a language that is almost exactly Python.

-- 
Skip Montanaro - skip at pobox.com
http://www.mojam.com/
http://www.musi-cal.com/




More information about the Python-list mailing list