Python's fastest way to implement loops (for, while, etc. speed comparison)

post thumb
Python
by Admin/ on 04 Jan 2022

Python's fastest way to implement loops (for, while, etc. speed comparison)


Python is not known to be a very efficient language to execute. In addition, looping is a very time-consuming operation in any language. If any simple single-step operation takes 1 unit of time, repeating the operation tens of thousands of times will eventually increase the time spent tens of thousands of times.

while and for are two keywords commonly used in Python to implement loops, there is a real difference in their efficiency. For example, the following test code.

import timeit

def while_loop(n=100_000_000):
    i = 0
    s = 0
    while i < n:
        s += i
        i += 1
    return s

def for_loop(n=100_000_000):
    s = 0
    for i in range(n):
        s += i
    return s

def main():
    print('while loop\t\t', timeit.timeit(while_loop, number=1))
    print('for loop\t\t', timeit.timeit(for_loop, number=1))

if __name__ == '__main__':
    main()

# => while loop 4.718853999860585
# => for loop 3.211570399813354

This is a simple summation operation that computes the sum of all natural numbers from 1 to n. You can see that the for loop is 1.5 seconds faster than the while loop.

The difference is mainly due to the different mechanics of the two.

In each loop, while actually performs two more steps than for: a bounds check and the self-incrementing of variable i. That is, for each loop, while performs two more steps than for. That is, for each loop, while does a bounds check (while i < n) and a self-increment calculation (i += 1). Both of these operations are explicitly pure Python code.

The for loop does not require a bounds check and self-increment operation, and adds no explicit Python code (pure Python code is less efficient than the underlying C code). When the number of loops is large enough, a significant efficiency gap emerges.

Two more functions can be added to add unnecessary bounds checking and self-incrementing to the for loop.

import timeit

def while_loop(n=100_000_000):
    i = 0
    s = 0
    while i < n:
        s += i
        i += 1
    return s

def for_loop(n=100_000_000):
    s = 0
    for i in range(n):
        s += i
    return s

def for_loop_with_inc(n=100_000_000):
    s = 0
    for i in range(n):
        s += i
        i += 1
    return s

def for_loop_with_test(n=100_000_000):
    s = 0
    for i in range(n):
        if i < n:
            pass
        s += i
    return s

def main():
    print('while loop\t\t', timeit.timeit(while_loop, number=1))
    print('for loop\t\t', timeit.timeit(for_loop, number=1))
    print('for loop with increment\t\t',
          timeit.timeit(for_loop_with_inc, number=1))
    print('for loop with test\t\t', timeit.timeit(for_loop_with_test, number=1))

if __name__ == '__main__':
    main()

# => while loop 4.718853999860585
# => for loop 3.211570399813354
# => for loop with increment 4.602369500091299
# => for loop with test 4.18337869993411

As you can see, the addition of the bounds check and self-increment operations does significantly affect the efficiency of the for loop.

As mentioned earlier, Python’s underlying interpreter and built-in functions are implemented in C. C is much more efficient than Python.

For the above sum of equal variables operation, Python’s built-in sum function can be used to obtain a much more efficient execution than a for or while loop.

import timeit

def while_loop(n=100_000_000):
    i = 0
    s = 0
    while i < n:
        s += i
        i += 1
    return s

def for_loop(n=100_000_000):
    s = 0
    for i in range(n):
        s += i
    return s

def sum_range(n=100_000_000):
    return sum(range(n))

def main():
    print('while loop\t\t', timeit.timeit(while_loop, number=1))
    print('for loop\t\t', timeit.timeit(for_loop, number=1))
    print('sum range\t\t', timeit.timeit(sum_range, number=1))

if __name__ == '__main__':
    main()

# => while loop 4.718853999860585
# => for loop 3.211570399813354
# => sum range 0.8658821999561042

As you can see, using the built-in sum function instead of a loop increases the efficiency of code execution exponentially.

The sum operation of the built-in function is actually a loop, but it is implemented in C, whereas the sum operation in the for loop is implemented in pure Python code s += i. C > Python.

Expand your thinking a bit. As a child, you’ve heard the story of the childhood Gaussian who cleverly calculated the sum of 1 to 100. 1…100 equals (1 + 100) * 50. This same calculation can be applied to the summation operation above.

import timeit

def while_loop(n=100_000_000):
    i = 0
    s = 0
    while i < n:
        s += i
        i += 1
    return s

def for_loop(n=100_000_000):
    s = 0
    for i in range(n):
        s += i
    return s

def sum_range(n=100_000_000):
    return sum(range(n))

def math_sum(n=100_000_000):
    return (n * (n - 1)) // 2

def main():
    print('while loop\t\t', timeit.timeit(while_loop, number=1))
    print('for loop\t\t', timeit.timeit(for_loop, number=1))
    print('sum range\t\t', timeit.timeit(sum_range, number=1))
    print('math sum\t\t', timeit.timeit(math_sum, number=1))

if __name__ == '__main__':
    main()

# => while loop 4.718853999860585
# => for loop 3.211570399813354
# => sum range 0.8658821999561042
# => math sum 2.400018274784088e-06

The final execution time of math sum is about 2.4e-6, which is a million times shorter. The idea here is that since loops are inefficient, a piece of code has to be executed hundreds of millions of times over.

So we just don’t need to loop, and use mathematical formulas to turn hundreds of millions of loops into a single step operation. The efficiency is naturally enhanced to an unprecedented degree.

Final conclusion (a bit riddler).

The fastest way to implement loops – is to not use them

For Python, use built-in functions whenever possible to minimize the pure Python code in the loop.

Of course, built-in functions aren’t the fastest in some cases. When creating lists, for example, it’s the literal writing that’s faster.

Source: https://www.starky.ltd/2021/11/23/the-fastest-way-to-loop-in-python https://mp.weixin.qq.com/s/lJcl-4Xwb9XYEZNG9kuimg


Tags:
comments powered by Disqus