Opened 12 years ago
Closed 5 years ago
#11332 closed defect (wontfix)
65x penalty in performance for using float instead of RealNumber
Reported by: | Pablo Angulo | Owned by: | Burcin Erocal |
---|---|---|---|
Priority: | major | Milestone: | sage-duplicate/invalid/wontfix |
Component: | symbolics | Keywords: | float, RealNumber |
Cc: | Merged in: | ||
Authors: | Reviewers: | Maarten Derickx | |
Report Upstream: | N/A | Work issues: | |
Branch: | Commit: | ||
Dependencies: | Stopgaps: |
Description
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
Change History (15)
comment:1 Changed 12 years ago by
comment:2 Changed 12 years ago by
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".
comment:3 Changed 9 years ago by
Milestone: | sage-5.11 → sage-5.12 |
---|
comment:4 Changed 9 years ago by
Milestone: | sage-6.1 → sage-6.2 |
---|
comment:5 Changed 9 years ago by
Milestone: | sage-6.2 → sage-6.3 |
---|
comment:6 Changed 8 years ago by
Milestone: | sage-6.3 → sage-6.4 |
---|
comment:7 Changed 8 years ago by
Component: | performance → symbolics |
---|---|
Owner: | changed from tbd to Burcin Erocal |
comment:8 follow-up: 9 Changed 8 years ago by
Milestone: | sage-6.4 → sage-duplicate/invalid/wontfix |
---|---|
Status: | new → needs_review |
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
comment:9 Changed 8 years ago by
Replying to mmezzarobba:
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
.
comment:10 Changed 8 years ago by
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
comment:11 Changed 8 years ago by
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.
comment:12 Changed 8 years ago by
Status: | needs_review → needs_info |
---|
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.
comment:13 Changed 6 years ago by
Status: | needs_info → needs_review |
---|
I think there was progress from https://github.com/pynac/pynac/issues/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 GinacFunction
s.
comment:14 Changed 5 years ago by
Reviewers: | → Maarten Derickx |
---|---|
Status: | needs_review → positive_review |
I agree that the original problem is fixed.
comment:15 Changed 5 years ago by
Resolution: | → wontfix |
---|---|
Status: | positive_review → closed |
It's a bit worse:
125 loops, best of 3: 7.88 ms per loop
while
625 loops, best of 3: 48.3 µs per loop
so the ratio is rather around 150x.