Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

65x penalty in performance for using float instead of RealNumber #11332

Closed
sagetrac-pang mannequin opened this issue May 12, 2011 · 10 comments
Closed

65x penalty in performance for using float instead of RealNumber #11332

sagetrac-pang mannequin opened this issue May 12, 2011 · 10 comments

Comments

@sagetrac-pang
Copy link
Mannequin

sagetrac-pang mannequin commented May 12, 2011

The function random() returns a "float", but 1.0*random() is a "RealNumber". The following code:

%time
#1
N=5000
x=random()
for c in xrange(N):
    kk = exp(x)

takes 5.24 seconds, while

%time
#1
N=5000
x=random()*1.0
for c in xrange(N):
    kk = exp(x)

takes 0.08

Component: symbolics

Keywords: float, RealNumber

Reviewer: Maarten Derickx

Issue created by migration from https://trac.sagemath.org/ticket/11332

@sagetrac-pang sagetrac-pang mannequin added this to the sage-5.11 milestone May 12, 2011
@sagetrac-pang
Copy link
Mannequin Author

sagetrac-pang mannequin commented May 13, 2011

comment:1

It's a bit worse:

x=random()
timeit('exp(x)')

125 loops, best of 3: 7.88 ms per loop

while

x=random()*1.0
timeit('exp(x)')

625 loops, best of 3: 48.3 µs per loop

so the ratio is rather around 150x.

@nbruin
Copy link
Contributor

nbruin commented May 16, 2011

comment:2

note that "float" is the standard python float type, whereas RealNumber is a preferred type for sage. Furthermore, "exp" is a general sage function that can do all kinds of "exponentiation" (symbolic, numeric etc.), and that incurs overhead. Apparently a particularly bad one for "float" types. Setting the base line:

sage: x=random()
sage: y=RealNumber(x)
sage: z=RDF(x)
sage: timeit('exp(x)')
625 loops, best of 3: 1.15 ms per loop
sage: timeit('exp(y)')
625 loops, best of 3: 10.3 µs per loop
sage: timeit('exp(z)')
625 loops, best of 3: 3.52 µs per loop

Using python's own "exp" is the fastest:

sage: timeit('math.exp(x)')
625 loops, best of 3: 373 ns per loop

You can shave off some time from the RealNumber one too by calling a method specific for it. It's slower, but RealNumber has much more functionality (also multiprecision)

sage: timeit('y.exp()')
625 loops, best of 3: 6.28 µs per loop

RDF is supposed to be Sage's version of "double precision floats" and is indeed comparable:

sage: timeit('z.exp()')
625 loops, best of 3: 704 ns per loop

If you don't mind a float, math.exp seems to receive a fairly efficiently coerced float from either RealNumber or RDF

sage: timeit('math.exp(y)')
625 loops, best of 3: 510 ns per loop
sage: timeit('math.exp(z)')
625 loops, best of 3: 419 ns per loop

It would be nice if the generic "exp" would find a bit faster codepaths for some of these types, but I wouldn't consider the current behaviour a "defect".

@jdemeyer jdemeyer modified the milestones: sage-5.11, sage-5.12 Aug 13, 2013
@sagetrac-vbraun-spam sagetrac-vbraun-spam mannequin modified the milestones: sage-6.1, sage-6.2 Jan 30, 2014
@sagetrac-vbraun-spam sagetrac-vbraun-spam mannequin modified the milestones: sage-6.2, sage-6.3 May 6, 2014
@sagetrac-vbraun-spam sagetrac-vbraun-spam mannequin modified the milestones: sage-6.3, sage-6.4 Aug 10, 2014
@mezzarobba
Copy link
Member

comment:8

Fixed?

sage: sage: x=random()
sage: sage: y=RealNumber(x)
sage: sage: z=RDF(x)
sage: sage: timeit('exp(x)')
625 loops, best of 3: 17.7 µs per loop
sage: sage: timeit('exp(y)')
625 loops, best of 3: 5.9 µs per loop
sage: sage: timeit('exp(z)')
625 loops, best of 3: 2.29 µs per loop

@mezzarobba mezzarobba removed this from the sage-6.4 milestone Apr 14, 2015
@videlec
Copy link
Contributor

videlec commented Apr 22, 2015

comment:9

Replying to @mezzarobba:

Fixed?

sage: sage: x=random()
sage: sage: y=RealNumber(x)
sage: sage: z=RDF(x)
sage: sage: timeit('exp(x)')
625 loops, best of 3: 17.7 µs per loop
sage: sage: timeit('exp(y)')
625 loops, best of 3: 5.9 µs per loop
sage: sage: timeit('exp(z)')
625 loops, best of 3: 2.29 µs per loop

Half

sage: x = random()
sage: timeit('exp(x)', number=50000)
50000 loops, best of 3: 8.15 µs per loop
sage: from math import exp as math_exp
sage: timeit('math_exp(x)', number=50000)
50000 loops, best of 3: 290 ns per loop

just 30x slower. Better than the 65x that was reported for the difference between float and RR.

@jdemeyer
Copy link

comment:10

92x on my system:

sage: timeit('exp(x)', number=100000, repeat=10)
100000 loops, best of 10: 8.55 µs per loop
sage: timeit('math_exp(x)', number=100000, repeat=10)
100000 loops, best of 10: 92.1 ns per loop

@mezzarobba
Copy link
Member

comment:11

Wait, what exactly are we trying to measure? I thought this ticket was about the overhead of exp() (I mean sage.functions.log.exp) for some argument types. If we allow ourselves to call the “right” function or method for each type, then both RDF(x).exp() and math.exp(x) are fast when applicable.

@videlec
Copy link
Contributor

videlec commented Apr 24, 2015

comment:12

Agreed that it is not exactly the same issue... but still there is a problem for exp being very slow. So we can either open a new ticket for that slightly similar issue or precise the issue here.

@rwst
Copy link

rwst commented Oct 6, 2016

comment:13

I think there was progress from
pynac/pynac#108

I don't think you can get better than a few µs for symbolic exp(), there is too much overhead from symbolic/function.pyx even for GinacFunctions.

@koffie
Copy link

koffie commented Aug 30, 2017

Reviewer: Maarten Derickx

@koffie
Copy link

koffie commented Aug 30, 2017

comment:14

I agree that the original problem is fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants