Pabce
Pabce

Reputation: 1439

Why is a += x slower than a = a+x?

I'm working on optimizing a python program for which I have speed issues. I was playing about on another document with various things that appeared on my program which could influence total speed of execution.

I found that:

a = 0
for x in range(10000000):
    a += x
return a 

is slightly slower than:

a = 0
for x in range(10000000):
    a = a + x
return a 

The first script takes between 1.5 and 1.55 seconds to execute, while the second takes regulary about 1,36-1.37 seconds (using cProfile).

Any idea why this could be? Thank's :)

Upvotes: 1

Views: 532

Answers (2)

kiriloff
kiriloff

Reputation: 26333

a += x is basically not an increment operation. You are assigning the variable a + x to a again. Which is pretty much the same as assigning the the value of the variable with a = a + x.

So as Pieters mentionned, there is no reason to have such gap in timeit.

+++++ EDIT to DSM

integers in Python are immutable: you increment a if you increment b if you defined

a = 5

and

b = 5

so that to 'increment' b, you have to 'reassign' it to b, that is what i meant.

Upvotes: 0

Martijn Pieters
Martijn Pieters

Reputation: 1121834

Use the timeit module to do proper timings. It avoids common pitfalls, uses the most precise timer implementation for your platform and tries to minimise the influence of OS scheduling by repeating the tested code many times.

Using a profiler on the other hand adds a lot of overhead to support instrumenting the full call stack; timeit measures the complete execution time, not individual calls in the stack.

Using timeit shows the two versions are too close to call (default is 1 million iterations):

>>> timeit.timeit('a += x', 'a = x = 1')
0.047940969467163086
>>> timeit.timeit('a = a + x', 'a = x = 1')
0.04770612716674805

Both operations are one bytecode:

>>> def f(): a += x
... 
>>> def g(): a = a + x
... 
>>> import dis
>>> dis.dis(f)
  1           0 LOAD_FAST                0 (a)
              3 LOAD_GLOBAL              0 (x)
              6 INPLACE_ADD         
              7 STORE_FAST               0 (a)
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE        
>>> dis.dis(g)
  1           0 LOAD_FAST                0 (a)
              3 LOAD_GLOBAL              0 (x)
              6 BINARY_ADD          
              7 STORE_FAST               0 (a)
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE        

Upvotes: 11

Related Questions