Menu

C programmers, by necessity, generally develop a mental model for understanding the performance characteristics of their code. Developing this intuition in a high level language like Python can be more of a challenge. While good Python tools exist for identifying time and memory performance (line_profiler by Robert Kern and guppy by Sverker Nilsson), you are largely on your own if you want to develop intuition for code that is yet to be written. Understanding the cost of basic operations in your Python implementation can help guide design decisions by ruling out extensive use of expensive operations.

Why is this important you ask? Interactive applications appear responsive when they react to user behaviour within a given time budget. In our consulting engagements, we often find that a lack of awareness regarding the cost of common operations can lead to sluggish application performance. Some examples of user interaction thresholds:

If you are targeting 60 fps in a multimedia application you have 16 milliseconds of processing time per frame. In this time, you need to update state, figure out what is visible, and then draw it.

Well behaved applications will load a functional screen that a user can interact with in under a second. Depending on your application, you may need to create an expensive datastructure upfront before your user can interact with the application. Often one needs to find a way to at least make it feel like the one second constraint is being respected.

You run Gentoo / Arch. In this case, obsessing over performance is a way of life.

Obviously rules are meant to be broken, but knowing where to be frugal can help you avoid or troubleshoot performance problems. Performance data for Python and PyPy are listed below.

PyPy timing data

I recently had the opportunity to attend SIGGRAPH in LA. For those of you who don’t know, SIGGRAPH is an annual conference for Graphics and Visualization that does a great job of attracting people from both the scientific and artistic halves of the visualization community. For broader coverage, you can read some of the usual blog coverage here. I was particularly interested, however, in the OpenGL developments.

Increased focus on performance/watt for mobile applications

SIGGRAPH 2012 was important for many reasons, but particularly for those of us that use OpenGL (this year was the 20th anniversary of the OpenGL API). OpenGL 4.3 and OpenGL ES 3.0 were announced and there were many interesting sessions on the new OpenGL release (more about this later) and graphics on mobile devices.

The rapid ascent of mobile and its dominance as the primary computer that people interact with on a daily basis has opened up an interesting challenge for people designing games and visualization — the difference in the power envelope between mobile devices and their desktop brethren. The power envelope of high-end desktop devices is ~300 watt while the power envelope of mobile gpu’s is < 1 watt. This power disparity implies a massive gulf in performance across the full spectrum of devices, assuming similar architectures are in use.

Multiple speakers stressed that power consumption should be a first class design metric when designing graphics algorithms along with the traditional metric of performance. Currently, the tools for profiling and measuring power consumption of algorithms are almost non-existent and nowhere near the sophistication of tools for measuring performance. Nevertheless, data transfers over a bus were recognized as an expensive power activity and a place where power savings can be realized.

To this end, OpenGL (finally) announced new texture compression formats that are royalty free, work on both OpenGL and OpenGL ES and are guaranteed on all compliant OpenGL implementations. This is great for developers since we can finally assume that this functionality will be available across all devices. More information about the new texture compression formats lives here.

Using OpenGL 4.3 from Python: Rabbit of Caerbannog

The OpenGL ARB committee started an effort to modernise OpenGL around OpenGL 3.x and large parts of the old fixed pipeline functionality was deprecated. These changes were great from a driver implementors point of view and should allow developers to write code that runs faster on modern GPU’s. However the deprecations have obsoleted much of the OpenGL tutorials that exist on the internet. I have listed two examples here which do not use deprecated functionality and can be used as a starting point to write modern OpenGL graphics examples in Python.

So, how do you use the brand spanking new 4.3 api’s from Python? I’ve written a code sample that uses modern opengl (no deprecated functionality used) to draw a triangle from Python.

You will require a trunk release of PyOpenGL to create a OpenGL 4.3 context

Code for the examples can be obtained from https://github.com/enthought/glfwpy.git

I have conservatively marked the OpenGL version as 3.2 here since many readers will not have 4.3 working on their machines. To enable OpenGL 4.3 change the OpenWindowHint call for OPENGL_VERSION_MAJOR to 4 and the OpenWindowHint call for OPENGL_VERSION_MINOR to 3.