ASKSAGE: Sage Q&A Forum - Individual question feedhttp://ask.sagemath.org/questions/Q&A Forum for SageenCopyright Sage, 2010. Some rights reserved under creative commons license.Thu, 19 Jan 2012 02:05:01 -0600compile a symbolic function and use it in cythonhttp://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/I have written [code to create plots of Newton fractals](https://lestum.mat.uam.es/home/pub/32/). Cython was key, pure python was way too slow.
But I'd like to create an interact: write the polynomial and watch the fractal. The problem is the user should enter the polynomial in a text box as a symbolic expression, then I should send that to cython and the cython code should do the rest, calling that function when necessary.
I've managed to do so: I create a fast_callable on the expression, and pass the output of fast_callable to cython, but it is **very slow**. Unfortunately, I cannot make the different data types for complex numbers match, and there might be something else.
Maybe you can think of a different approach...Tue, 17 Jan 2012 00:32:36 -0600http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/Answer by Jason Grout for <p>I have written <a href="https://lestum.mat.uam.es/home/pub/32/">code to create plots of Newton fractals</a>. Cython was key, pure python was way too slow.</p>
<p>But I'd like to create an interact: write the polynomial and watch the fractal. The problem is the user should enter the polynomial in a text box as a symbolic expression, then I should send that to cython and the cython code should do the rest, calling that function when necessary. </p>
<p>I've managed to do so: I create a fast_callable on the expression, and pass the output of fast_callable to cython, but it is <strong>very slow</strong>. Unfortunately, I cannot make the different data types for complex numbers match, and there might be something else.</p>
<p>Maybe you can think of a different approach...</p>
http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?answer=13147#post-id-13147You probably want to use the fast_callable's `call_c` function. I've posted some examples at [http://sagenb.org/home/pub/4086/](http://sagenb.org/home/pub/4086/), but I repeat them below for convenience:
%cython
from sage.ext.interpreters.wrapper_rdf cimport Wrapper_rdf
from libc.math cimport sqrt
def benchmark(float n):
cdef int i
for i in range(1000):
n = sqrt(n)
return n
def iterate_c(Wrapper_rdf f,float n):
cdef double *result = [n]
cdef int i
for i in range(1000):
f.call_c(result, result)
return result[0]
def iterate_py(f, float n):
cdef int i
for i in range(1000):
n=f(n)
return n
Then
g(x)=sqrt(x)
f=fast_callable(g,vars=[x],domain=float)
Timings:
sage: timeit('benchmark(1e23)')
625 loops, best of 3: 7.15 µs per loop
sage: timeit('iterate_c(f,1e23)')
625 loops, best of 3: 18.3 µs per loop
sage: timeit('iterate_py(f,1e23)')
625 loops, best of 3: 162 µs per loop
sage: timeit('iterate_py(g,1e23)')
5 loops, best of 3: 77.2 ms per loop
Wed, 18 Jan 2012 11:34:36 -0600http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?answer=13147#post-id-13147Comment by pang for <p>You probably want to use the fast_callable's <code>call_c</code> function. I've posted some examples at <a href="http://sagenb.org/home/pub/4086/">http://sagenb.org/home/pub/4086/</a>, but I repeat them below for convenience:</p>
<pre><code>%cython
from sage.ext.interpreters.wrapper_rdf cimport Wrapper_rdf
from libc.math cimport sqrt
def benchmark(float n):
cdef int i
for i in range(1000):
n = sqrt(n)
return n
def iterate_c(Wrapper_rdf f,float n):
cdef double *result = [n]
cdef int i
for i in range(1000):
f.call_c(result, result)
return result[0]
def iterate_py(f, float n):
cdef int i
for i in range(1000):
n=f(n)
return n
</code></pre>
<p>Then </p>
<pre><code>g(x)=sqrt(x)
f=fast_callable(g,vars=[x],domain=float)
</code></pre>
<p>Timings:</p>
<pre><code>sage: timeit('benchmark(1e23)')
625 loops, best of 3: 7.15 µs per loop
sage: timeit('iterate_c(f,1e23)')
625 loops, best of 3: 18.3 µs per loop
sage: timeit('iterate_py(f,1e23)')
625 loops, best of 3: 162 µs per loop
sage: timeit('iterate_py(g,1e23)')
5 loops, best of 3: 77.2 ms per loop
</code></pre>
http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?comment=20494#post-id-20494Awesome! Repeating the trick with "double complex", "double_complex", and a rusty knowledge of C was not easy, though.Thu, 19 Jan 2012 00:03:48 -0600http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?comment=20494#post-id-20494Comment by kcrisman for <p>You probably want to use the fast_callable's <code>call_c</code> function. I've posted some examples at <a href="http://sagenb.org/home/pub/4086/">http://sagenb.org/home/pub/4086/</a>, but I repeat them below for convenience:</p>
<pre><code>%cython
from sage.ext.interpreters.wrapper_rdf cimport Wrapper_rdf
from libc.math cimport sqrt
def benchmark(float n):
cdef int i
for i in range(1000):
n = sqrt(n)
return n
def iterate_c(Wrapper_rdf f,float n):
cdef double *result = [n]
cdef int i
for i in range(1000):
f.call_c(result, result)
return result[0]
def iterate_py(f, float n):
cdef int i
for i in range(1000):
n=f(n)
return n
</code></pre>
<p>Then </p>
<pre><code>g(x)=sqrt(x)
f=fast_callable(g,vars=[x],domain=float)
</code></pre>
<p>Timings:</p>
<pre><code>sage: timeit('benchmark(1e23)')
625 loops, best of 3: 7.15 µs per loop
sage: timeit('iterate_c(f,1e23)')
625 loops, best of 3: 18.3 µs per loop
sage: timeit('iterate_py(f,1e23)')
625 loops, best of 3: 162 µs per loop
sage: timeit('iterate_py(g,1e23)')
5 loops, best of 3: 77.2 ms per loop
</code></pre>
http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?comment=20491#post-id-20491@pang: if you end up with something even better (better looking, faster, or both) for the Newton basins, please add it to #11837. Sage will probably always be slower on this sort of thing, but it doesn't have to be ''too'' slow.Thu, 19 Jan 2012 02:05:01 -0600http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?comment=20491#post-id-20491Comment by Jason Grout for <p>You probably want to use the fast_callable's <code>call_c</code> function. I've posted some examples at <a href="http://sagenb.org/home/pub/4086/">http://sagenb.org/home/pub/4086/</a>, but I repeat them below for convenience:</p>
<pre><code>%cython
from sage.ext.interpreters.wrapper_rdf cimport Wrapper_rdf
from libc.math cimport sqrt
def benchmark(float n):
cdef int i
for i in range(1000):
n = sqrt(n)
return n
def iterate_c(Wrapper_rdf f,float n):
cdef double *result = [n]
cdef int i
for i in range(1000):
f.call_c(result, result)
return result[0]
def iterate_py(f, float n):
cdef int i
for i in range(1000):
n=f(n)
return n
</code></pre>
<p>Then </p>
<pre><code>g(x)=sqrt(x)
f=fast_callable(g,vars=[x],domain=float)
</code></pre>
<p>Timings:</p>
<pre><code>sage: timeit('benchmark(1e23)')
625 loops, best of 3: 7.15 µs per loop
sage: timeit('iterate_c(f,1e23)')
625 loops, best of 3: 18.3 µs per loop
sage: timeit('iterate_py(f,1e23)')
625 loops, best of 3: 162 µs per loop
sage: timeit('iterate_py(g,1e23)')
5 loops, best of 3: 77.2 ms per loop
</code></pre>
http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?comment=20495#post-id-20495I can't for the life of me figure out what you updated, kcrisman. Is there a place I can see the history? (Edit: oh, I see; just "edit" and then I can see the revisions...you just updated a link. I was afraid I made a coding error.)Wed, 18 Jan 2012 15:17:48 -0600http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?comment=20495#post-id-20495Answer by kcrisman for <p>I have written <a href="https://lestum.mat.uam.es/home/pub/32/">code to create plots of Newton fractals</a>. Cython was key, pure python was way too slow.</p>
<p>But I'd like to create an interact: write the polynomial and watch the fractal. The problem is the user should enter the polynomial in a text box as a symbolic expression, then I should send that to cython and the cython code should do the rest, calling that function when necessary. </p>
<p>I've managed to do so: I create a fast_callable on the expression, and pass the output of fast_callable to cython, but it is <strong>very slow</strong>. Unfortunately, I cannot make the different data types for complex numbers match, and there might be something else.</p>
<p>Maybe you can think of a different approach...</p>
http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?answer=13133#post-id-13133I'm not sure if this answers your actual question, but you might be interested in code that Simon King and I have at [# 11837](http://trac.sagemath.org/sage_trac/ticket/11837) for generating Newton basin fractals. You are right that it is slow. Hopefully not quite as slow as yours, though, maybe it's all you need.
Incidentally, even at [David Joyce's awesome generator page](http://aleph0.clarku.edu/~djoyce/newton/newtongen.html) he just takes the roots; trying to get that from a generic polynomial first will severely slow you down, I'm sure.Tue, 17 Jan 2012 04:16:03 -0600http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?answer=13133#post-id-13133Comment by pang for <p>I'm not sure if this answers your actual question, but you might be interested in code that Simon King and I have at <a href="http://trac.sagemath.org/sage_trac/ticket/11837"># 11837</a> for generating Newton basin fractals. You are right that it is slow. Hopefully not quite as slow as yours, though, maybe it's all you need. </p>
<p>Incidentally, even at <a href="http://aleph0.clarku.edu/~djoyce/newton/newtongen.html">David Joyce's awesome generator page</a> he just takes the roots; trying to get that from a generic polynomial first will severely slow you down, I'm sure.</p>
http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?comment=20493#post-id-20493Well, both things are great to know. Thanks!Thu, 19 Jan 2012 00:04:50 -0600http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?comment=20493#post-id-20493Comment by pang for <p>I'm not sure if this answers your actual question, but you might be interested in code that Simon King and I have at <a href="http://trac.sagemath.org/sage_trac/ticket/11837"># 11837</a> for generating Newton basin fractals. You are right that it is slow. Hopefully not quite as slow as yours, though, maybe it's all you need. </p>
<p>Incidentally, even at <a href="http://aleph0.clarku.edu/~djoyce/newton/newtongen.html">David Joyce's awesome generator page</a> he just takes the roots; trying to get that from a generic polynomial first will severely slow you down, I'm sure.</p>
http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?comment=20509#post-id-20509Well, asking for the roots instead of the polynomial does the trick for polynomials, but the question remains: how can I get a symbolic function (or some string representing a function) from an interact, compile it, and use it in cython with similar speed to a function that was written in cython.Tue, 17 Jan 2012 22:02:24 -0600http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?comment=20509#post-id-20509Comment by kcrisman for <p>I'm not sure if this answers your actual question, but you might be interested in code that Simon King and I have at <a href="http://trac.sagemath.org/sage_trac/ticket/11837"># 11837</a> for generating Newton basin fractals. You are right that it is slow. Hopefully not quite as slow as yours, though, maybe it's all you need. </p>
<p>Incidentally, even at <a href="http://aleph0.clarku.edu/~djoyce/newton/newtongen.html">David Joyce's awesome generator page</a> he just takes the roots; trying to get that from a generic polynomial first will severely slow you down, I'm sure.</p>
http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?comment=20507#post-id-20507That's why I wasn't sure if it answered your actual question; I wasn't sure if you wanted Newton basins specifically, or the cython. I don't know how to use symbolic things in Cython, though Ginac is C++ so maybe there is something possible.Wed, 18 Jan 2012 02:15:33 -0600http://ask.sagemath.org/question/8632/compile-a-symbolic-function-and-use-it-in-cython/?comment=20507#post-id-20507