Faster Code
Note
I won’t claim that my suggestions will make the code perfect, merely that they will make the code better (at least in my biased opinion).
Take another look at the code from the previous section. To keep things simple, let’s just consider the Python version:
# Compute the vector product of the two velocities
i = 10
while j < i+1:
k = i + 3
s[j] = s[j] + k*j
j = j + 1
I’ll start with this line:
while j < i+1:
What is the value of i+1
? It’s 11, since we have i = 10
on the
line above. Is the value of i+1
going to change as we go through the
loop? No, there’s nothing that changes the value of i
in the loop,
so i+1
will be unchanged.
But Python doesn’t “know” that. Python is an interpreted computer language: The Python interpreter looks at each line, one-by-one, converts that line into the native computer machine language, and executes it.1
That means that every time the Python interpreter goes through the
loop, and interprets the statement while j < i+1:
, it’s re-computing
the value of i+1
. Since i
never changes (in the loop), i+1
never
changes. Yet Python must go through the additional step of adding 1 to
i
each time.
Therefore, I claim:
Speed problem 1: The loop performs an unnecessary computation of
i+1
for every iteration of the loop.
Now you’ve probably already guessed:
Speed problem 2: The loop performs an unnecessary computation for
k = i+3
for every iteration of the loop.
Again, since the value of i+3
never changes, the value of k
never
changes. Yet Python must spend time re-calculating k
.2
Note
Why this fuss over a simple addition? Computers are fast, aren’t they? And it’s just an addition, not calculating the space-time tensor in the vicinity of a black-hole merger.
But:
Programs and goals change over time. Right now a loop may be going through 11 entries in a table. Tomorrow it may be going over 10,000 entries.
In my experience, paying attention to what’s actually modified in a loop helps one write code that is easier to read and debug.
Let’s revise the Python version with those two points in mind:
# Compute the vector product of the two velocities
i = 10
k = i + 3
m = i + 1
while j < m:
s[j] = s[j] + k*j
j = j + 1
+=
We can do just a bit better. After you’ve been programming for a while, you’ll notice the following kind of statement is very common:
a = a + b
To make lines of code a bit shorter, and to allow language interpreters or compilers a chance at improving efficiency, both Python and C++ implement a set of operators:
+=, -=, *=, /=, %=
The first one is by far the one I’ve seen most often. The following two statements do the same thing:
a = a + b
a += b
As do these two statements:
value = value + offset
value += offset
C++ goes a step further. Since adding (or subtracting) 1 is very
common, the language has ++
(and --
) operators. The following
statements do the same thing:
a = a + 1;
a += 1;
a++;
++a;
There’s a difference between a++
and ++a
, but I’ll leave that topic
to a more formal C++ course.
Now you know why the language is called C++!
With that in mind, we may get a bit more speed by using +=
in our code:
# Compute the vector product of the two velocities
i = 10
k = i + 3
m = i + 1
while j < m:
s[j] += k*j
j += 1
Well, our code is faster… but there are still problems with it. We’ll look at them in the next section.
- 1
For anyone familiar with compilers and interpreters, I’m skipping over a lot of details here. However, the details (as important as they are to the overall science of computing) still support my point… I think.
- 2
If you’re a C++ programmer, your reaction may be that these two points are meaningless for an optimizing compiler. That’s a legitimate reaction, but I maintain it’s no excuse for sloppy code.