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

No reevaluation of evaluated values #391

Merged
merged 4 commits into from
Jun 9, 2016
Merged

Conversation

poke1024
Copy link
Contributor

Mathics currently reevaluates variable values (i.e. values of symbols set via Set[]) every time they're accessed.

This can lead to some worrisome performance (and it gets worse for even longer lists):

x=Range[10000]; Timing[First[x]]
{0.2507470000000005,1}

This PR fixes this by not rebuilding expressions if no var is replaced. That way, the original expression's is_evaluated attribute does not get reset, and the expression is thus not reevaluated when Expression.evaluate() gets called for it later on. With change in PR:

x=Range[10000]; Timing[First[x]]
{0.08288399999999996,1}

@bnjones
Copy link
Member

bnjones commented May 23, 2016

Can you run benchmark.py before/after to see if this improves performance across the board?

@@ -1103,6 +1113,9 @@ def replace_vars(self, vars, options=None,
leaves = [Expression('List', *func_params), body] + \
self.leaves[2:]

if len(vars) == 0: # might just be a symbol set via Set[] we looked up here
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why len(vars) == 0 instead of not vars?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I wasn't even aware that not could be used in this way on a dict here. Changed that.

Copy link
Contributor Author

@poke1024 poke1024 May 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

benchmark.py seems to give a very slight across the board improvement of 2-4%, but it could be as well random noise. I think it really only affects the special case of looking up a symbol that's expensive to compute.

EDIT I looked at best, when I should have looked at avg. Now it seems more like 10% to 15% improvement. Here are the values:

EVALUATION BENCHMARKS (WITH PR CHANGE):
Arithmetic
  '1 + 2'
     5000 loops, avg:  227 us per loop, best:  209 us per loop
  '5 * 3'
     5000 loops, avg:  246 us per loop, best:  223 us per loop

DensityPlot
  'DensityPlot[x + y^2, {x, -3, 3}, {y, -2, 2}]'
        5 loops, avg:  489 ms per loop, best:  378 ms per loop

Expand
  'Expand[(a1+a2)^200]'
        5 loops, avg:  424 ms per loop, best:  328 ms per loop
  'Expand[(a1+a2+a3)^25]'
        5 loops, avg:  883 ms per loop, best:  695 ms per loop
  'Expand[(a1+a2+a3+a4+a5+a6+a7)^3]'
       10 loops, avg:  152 ms per loop, best:  125 ms per loop

Matrix
  'RandomInteger[{0,1}, {10,10}] . RandomInteger[{0,1}, {10,10}]'
        5 loops, avg:  403 ms per loop, best:  315 ms per loop
  'RandomInteger[{0,10}, {10,10}] + RandomInteger[{0,10}, {10,10}]'
      100 loops, avg: 38.4 ms per loop, best: 35.8 ms per loop

Plot
  'Plot[0, {x, -3, 3}]'
      100 loops, avg: 92.4 ms per loop, best: 87.7 ms per loop
  'Plot[x^2 + x + 1, {x, -3, 3}]'
        5 loops, avg:  820 ms per loop, best:  664 ms per loop
  'Plot[Sin[Cos[x^2]], {x, -3, 3}]'
        5 loops, avg: 2.46 s  per loop, best: 2.03 s  per loop
  'Plot[Sin[100 x], {x, -3, 3}]'
        5 loops, avg: 1.75 s  per loop, best: 1.43 s  per loop

Plot3D
  'Plot3D[0, {x, -1, 1}, {y, -1, 1}]'
        5 loops, avg:  264 ms per loop, best:  205 ms per loop
  'Plot3D[x + y^2, {x, -3, 3}, {y, -2, 2}]'
        5 loops, avg:  822 ms per loop, best:  639 ms per loop
  'Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -3, 3}]'
        5 loops, avg: 2.55 s  per loop, best: 2.08 s  per loop
  'Plot3D[Sin[100 x + 100 y ^ 2], {x, 0, 1}, {y, 0, 1}]'
        5 loops, avg: 2.83 s  per loop, best: 2.14 s  per loop

Random
  'RandomInteger[{-100, 100}, 100]'
     1000 loops, avg: 5.82 ms per loop, best: 3.94 ms per loop
  'RandomInteger[10, {10, 10}]'
     1000 loops, avg: 5.83 ms per loop, best: 4.59 ms per loop
  'RandomInteger[{0,1}, {5, 5, 5}]'
     1000 loops, avg: 7.77 ms per loop, best: 6.22 ms per loop
  'RandomReal[1, 100]'
     1000 loops, avg: 7.88 ms per loop, best: 6.37 ms per loop
  'RandomReal[{-1, 1}, 100]'
     1000 loops, avg: 7.57 ms per loop, best: 6.21 ms per loop
  'RandomComplex[2 + I, 50]'
      100 loops, avg: 37.1 ms per loop, best: 29.5 ms per loop
  'RandomComplex[{-1 - I, 1 + I}, {10, 10}]'
      100 loops, avg: 65.9 ms per loop, best: 58.6 ms per loop

Trig
  'Sin[RandomReal[]]'
     1000 loops, avg: 1.97 ms per loop, best: 1.67 ms per loop
  'ArcTan[RandomReal[]]'
     1000 loops, avg: 1.79 ms per loop, best: 1.55 ms per loop
    EVALUATION BENCHMARKS (WITHOUT PR CHANGE):
Arithmetic
  '1 + 2'
     5000 loops, avg:  236 us per loop, best:  210 us per loop
  '5 * 3'
     5000 loops, avg:  289 us per loop, best:  226 us per loop

DensityPlot
  'DensityPlot[x + y^2, {x, -3, 3}, {y, -2, 2}]'
        5 loops, avg:  492 ms per loop, best:  370 ms per loop

Expand
  'Expand[(a1+a2)^200]'
        5 loops, avg:  471 ms per loop, best:  373 ms per loop
  'Expand[(a1+a2+a3)^25]'
        5 loops, avg: 1.02 s  per loop, best:  765 ms per loop
  'Expand[(a1+a2+a3+a4+a5+a6+a7)^3]'
       10 loops, avg:  173 ms per loop, best:  132 ms per loop

Matrix
  'RandomInteger[{0,1}, {10,10}] . RandomInteger[{0,1}, {10,10}]'
        5 loops, avg:  447 ms per loop, best:  353 ms per loop
  'RandomInteger[{0,10}, {10,10}] + RandomInteger[{0,10}, {10,10}]'
      100 loops, avg: 42.3 ms per loop, best: 36.1 ms per loop

Plot
  'Plot[0, {x, -3, 3}]'
       10 loops, avg:  118 ms per loop, best: 89.5 ms per loop
  'Plot[x^2 + x + 1, {x, -3, 3}]'
        5 loops, avg:  833 ms per loop, best:  663 ms per loop
  'Plot[Sin[Cos[x^2]], {x, -3, 3}]'
        5 loops, avg: 2.76 s  per loop, best: 2.26 s  per loop
  'Plot[Sin[100 x], {x, -3, 3}]'
        5 loops, avg: 1.86 s  per loop, best: 1.49 s  per loop

Plot3D
  'Plot3D[0, {x, -1, 1}, {y, -1, 1}]'
        5 loops, avg:  287 ms per loop, best:  216 ms per loop
  'Plot3D[x + y^2, {x, -3, 3}, {y, -2, 2}]'
        5 loops, avg:  859 ms per loop, best:  641 ms per loop
  'Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -3, 3}]'
        5 loops, avg: 2.74 s  per loop, best: 2.16 s  per loop
  'Plot3D[Sin[100 x + 100 y ^ 2], {x, 0, 1}, {y, 0, 1}]'
        5 loops, avg: 2.85 s  per loop, best: 2.19 s  per loop

Random
  'RandomInteger[{-100, 100}, 100]'
     1000 loops, avg: 4.73 ms per loop, best: 3.99 ms per loop
  'RandomInteger[10, {10, 10}]'
     1000 loops, avg: 6.18 ms per loop, best: 4.64 ms per loop
  'RandomInteger[{0,1}, {5, 5, 5}]'
     1000 loops, avg: 7.21 ms per loop, best: 6.28 ms per loop
  'RandomReal[1, 100]'
     1000 loops, avg: 7.26 ms per loop, best: 6.39 ms per loop
  'RandomReal[{-1, 1}, 100]'
     1000 loops, avg: 6.87 ms per loop, best: 6.23 ms per loop
  'RandomComplex[2 + I, 50]'
      100 loops, avg: 32.6 ms per loop, best: 29.6 ms per loop
  'RandomComplex[{-1 - I, 1 + I}, {10, 10}]'
      100 loops, avg: 63.6 ms per loop, best: 59.5 ms per loop

Trig
  'Sin[RandomReal[]]'
     1000 loops, avg: 1.78 ms per loop, best:  1.7 ms per loop
  'ArcTan[RandomReal[]]'
     1000 loops, avg: 1.65 ms per loop, best: 1.57 ms per loop

@sn6uv sn6uv assigned sn6uv and unassigned sn6uv May 23, 2016
@sn6uv sn6uv merged commit 7d02a48 into mathics:master Jun 9, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants