pearu / sympycore

Automatically exported from code.google.com/p/sympycore
Other
10 stars 1 forks source link

compiling of functions to machine code #52

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
It would be a nice (but advanced) feature for really fast function evaluation.
It could be done transparently.
The Open Source CAS Axiom implements this for example.

Original issue reported on code.google.com by Vinzent.Steinberg@gmail.com on 28 Feb 2008 at 4:41

GoogleCodeExporter commented 8 years ago
While it's possible to generate machine code in pure Python, there's AFAIK no 
direct
way to run it (short of writing a binary file and executing it in a separate
process). Seems better to generate C code that can be used with (say) Weave.

We should definitely be able to generate optimized Python float code for 
plotting,
numerical integration, etc. This should be fast enough for most purposes, 
especially
if using numpy to thread the operations over arrays.

Original comment by fredrik....@gmail.com on 2 Mar 2008 at 12:53

GoogleCodeExporter commented 8 years ago
I wrote some quick and dirty code as a proof of concept (sorry for using sympy 
;) ):

from sympy import *
from sympy.utilities.lambdify import lambdastr
import os
cmd = os.system

x = Symbol('x')
f = integrate(exp(x), x)
lstr = lambdastr(f, [x]).split(': ')[1]

pyxfile = 'tmp.pyx'
cfile = 'tmp.c'
ofile = cfile.split('.')[0] + '.o'
sofile = cfile.split('.')[0] + '.so'
for filename in [pyxfile, cfile, ofile, sofile]:
    try:
        os.remove(filename)
    except OSError, e:
        pass #print e

code = '''
from math import acos, asin, atan, atan2, ceil, cos, cosh, degrees, e, exp, \
fabs, floor, fmod, frexp, hypot, ldexp, log, log10, modf, pi, pow, radians, \
sin, sinh, sqrt, tan, tanh

cdef float f(float x):
    return %s

def pyf(x):
    return f(x)
''' % lstr
f = open(pyxfile, 'w')
f.write(code)
f.close()
print cmd('cython -o %s %s' % (cfile, pyxfile))
print cmd('gcc -c -fPIC -I/usr/include/python/ %s' % cfile)
print cmd('gcc -shared %s -o %s' % (ofile, sofile))

import tmp
reload(tmp)

print tmp.pyf(1)

which results in something like:

0
0
0
2.71828174591

Of course this is highly messy and platform-dependent, but it does the job. I 
did not
measure performance, there will be much space for optimization anyway.

Using a separate process should be easy with Parallel Python or something else.

Original comment by Vinzent.Steinberg@gmail.com on 25 Mar 2008 at 9:55

GoogleCodeExporter commented 8 years ago
Thanks Vinzent for the code. I think such feature would be very useful. I made a
sympy issue for this too:

http://code.google.com/p/sympy/issues/detail?id=765

Original comment by ondrej.c...@gmail.com on 25 Mar 2008 at 10:14