Group Abstract Group Abstract

Message Boards Message Boards

0
|
3.8K Views
|
7 Replies
|
6 Total Likes
View groups...
Share
Share this post:

Same code with involving integer takes longer time

Posted 2 years ago

Hello,

Np = 500;
a = 1;
b = 4.0;
h = (b - a)/Np;
x0 = a;
y[0] = 1;
Y = {{x0, y[0]}};
f[x_, y_] = -y*(x + 1) - Cos[x];
For[m = 0, m <= Np - 1, m++,
  xm = a + m*h;
  y[m + 1] = y[m] + h*f[xm, y[m]];
  AppendTo[Y, {xm + h, y[m + 1]}];
  ];
g2 = ListLinePlot[Y, PlotStyle -> Green, PlotRange -> All]

enter image description here

Np = 500;
a = 1;
b = 4;
h = (b - a)/Np;
x0 = a;
y[0] = 1;
Y = {{x0, y[0]}};
f[x_, y_] = -y*(x + 1) - Cos[x];
For[m = 0, m <= Np - 1, m++,
  xm = a + m*h;
  y[m + 1] = y[m] + h*f[xm, y[m]];
  AppendTo[Y, {xm + h, y[m + 1]}];
  ];
g2 = ListLinePlot[Y, PlotStyle -> Green, PlotRange -> All]

enter image description here

So, the only difference is in b, in that in the first case b=4.0, while in the second case b=4. In the first case the code runs quickly and displays the result, while in the second case, the code runs endlessly and does not display the result.

Can someone explain how exactly that .0 influences the running of the code so much?

Thank you.

POSTED BY: Cornel B.
7 Replies
POSTED BY: Daniel Lichtblau
Posted 2 years ago

Agreed. That’s why I mentioned the looping stuff as a side note.

POSTED BY: Eric Rimbey
Posted 2 years ago

Eric, the Notebook with a value of 4 is not failing in the loop. The loop completes; it's failing inside the ListLinePlot[] function. If you put a Print[] call immediately before the ListLinePlot, you'll see that the loop has completed executing. There's something funky about the way you're creating Y. I don't know how to run the debugger.

POSTED BY: Updating Name
Posted 2 years ago
POSTED BY: Phil Earnhardt
Posted 2 years ago

So, then that it is better to use whenever possible real numbers (with .0) than integer numbers, right?

I wouldn't say "whenever possible". I'd say it's better if you're going to use Plot or other plotting functions or if performance is important.

Well, then what should I use instead of AppendTo and For loop? Which equivalent functions are better to use?

Sometimes (at least for me) it's a matter of experimentation, and sometimes I'm surprised by what ends up being fastest. Maybe someone with deeper knowledge of the implementation details and performance issues could be more definitive, but instead of For, I would generally try

  • Map
  • Nest/NestList
  • NestWhile/NestWhileList
  • Fold/FoldList
  • FoldWhile/FoldWhileList
  • FoldPair/FoldPairList

Instead of AppendTo

  • list = Join[list, {newitem}]
  • list = Flatten[{list, newitem}]
  • list = Append[list, newitem]
  • list[[newindex]] = newitem

For that last one, just allocate the size you need for the list first, and then update by index rather than by appending. Sometimes special data structures (http://reference.wolfram.com/language/guide/DataStructures.html) work best for specific circumstances. I tend to just use the simplest thing (probably Map over a List is the most frequent followed by Nest) until I run into performance issues when scaling, at which point I try whatever seems promising depending on the expressions I'm working with. And sometimes For does actually make things faster. Maybe I should go look for a Wolfram training video on optimization.

POSTED BY: Eric Rimbey
Posted 2 years ago
  1. So, then that it is better to use whenever possible real numbers (with .0) than integer numbers, right?

  2. Well, then what should I use instead of AppendTo and For loop? Which equivalent functions are better to use?

POSTED BY: Cornel B.
Posted 2 years ago

A number expression like 4 is interpreted as an integer. Integers and fractions are not estimated, but are held as exact values, i.e. they have infinite precision. As long as all arithmetic operations being performed use integers or rationals, the arithmetic will be performed exactly, maintaining infinite precision.

Why does that matter? Well, set your Np lower (say 10) to reduce the time spent and then after the computation terminates, inspect Y. You'll see that it is a very complicated expression. This means time must be spent during the plot coming up with estimated values. Now, if you make any of your terms have finite precision, you'll see that Y is much simpler (it'll be all Real values).

If any part of an arithmetic expression has finite precision, then then result will too. How do you force finite precision? You can use N, or you could just change any of your terms to be Real instead of Integer. That's what the decimal point does. 4 is an Integer, but 4. is a Real. You could do this with a or b or pretty much anywhere else.

In general, finite precision calculations will go faster, because the representation is simpler and there are many algorithmic optimizations that are applied.

Side note, AppendTo is relatively inefficient and For loops can be as well, because they don't take advantage of the built-in optimizations for doing computations with lists. It might not matter in this example.

POSTED BY: Eric Rimbey
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard