Synthetic Programming with Python

Christopher Mueller and Andrew Lumsdaine
Open Systems Lab, Indiana University

In this talk, we introduce the Synthetic Programming Environment (SPE) for Python. Synthetic programming is a meta-programming technique for generating high-performance computational kernels from high level scripting languages (synthetic as in code synthesis). The SPE exposes the underlying processor's instruction set to the developer and supplies a set of tools for generating and executing custom instruction streams.

In contrast to in-line code systems such as PyASM and Weave, the SPE does not introduce a new language, but rather presents the underlying instruction set as a module containing native Python functions. And, while Psyco performs the code generation behind the scenes and is limited by the semantic information available in the Python language, the SPE lets the user map their domain semantics directly to the processor's instruction set.

As a quick demonstration of the SPE, the following Python code adds two numbers together using the PowerPC addi (add immediate) instruction:

  code = InstructionStream()

  code.add(ppc.addi(3, 0, 31)) # Initialize register r3 to int(31)
  code.add(ppc.addi(3, 3, 11)) # Add int(11) to the value in r3

  proc = Processor()
  result = proc.exucute(code)  # Execute the instructions
                               # (r3 just happens to be the return
                               #  register for int functions)
  print result
  --> 42
In addition to the core system, we'll demonstrate how to use the SPE with Python generators, operator overloading, and Numeric arrays to create a natural syntax for generating machine instructions, similar to expression templates in C++. For example, consider the following two functions for performing the element-wise array operation, c[i] = a[i] + b[i] * 5 :
  def NumericSum(a, b, c):
    Numeric.multiply(b, 5, c)
    Numeric.add(a, c, c)
    return

  def VecSum(code, a, b, c):
    ai = vec_iter(code, a)
    bi = vec_iter(code, b)
    ci = vec_iter(code, c)
  
    for i, j, k in syn_zip(code, ai, bi, ci):
      k.v = i + j * 5

    return
NumericSum uses standard Numeric Python ufuncs to perform the operation. VecSum uses vector iterators to synthesize code for the AltiVec SIMD unit, executing 4 element-wise operations per instruction. It achieves a 8x performance gain over the equivalent Numeric code while allowing the developer to express the algorithm using common Python idioms.

The Synthetic Programming Environment is currently available for the PowerPC and AltiVec instruction sets running on Mac OS X. It supports multi-threaded execution of synthetic programs and includes a set of example applications, including a molecular fingerprint comparison tool and a graphical particle system. We are exploring the possibility of porting it to other platforms, including IA-32/SSE and IBM's Cell Broadband Engine, and look forward to community feedback to help guide our efforts.

The SPE can be downloaded as a limited distribution research release at: http://www.osl.iu.edu/~chemuell/new/sp.php

Contact: chemuell [at] cs indiana edu