python loop performance pk

Posted by randydg on Thu, 30 Dec 2021 19:36:39 +0100

python loop performance pk

In any programming language, loops are very time-consuming operations. Assuming that any simple one-step operation takes one unit of time, repeat this operation for tens of thousands of times, and the final time will increase by tens of thousands of times. As we all know, python is not a language with high execution efficiency. Therefore, we pay more attention to the loop performance in python language.

for and while

while and for are two common methods to implement loops in python, but there is a gap in their running efficiency. Use the following test code:

import timeit

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


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


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


if __name__ == '__main__':
    main()

Operation results:

# while loop: 0.11076588099240325
# for loop: 0.03892302500025835

As you can see, a simple summation loop, the for loop is much faster than the while loop.

What causes this gap?

First of all, it is common sense that C code is more efficient than Python code. At the same time, the underlying interpreter and built-in functions of Python are implemented in C language.

In fact, in each loop, while performs two more steps than for: boundary checking and autoincrement of variable i. That is, while i < n and i += 1, and these two steps are pure python scripts displayed. In contrast, the for loop does not need these two steps to rely on the operation of python script, so the efficiency is better than the while loop, and with the increasing number of loops, the gap between the two is becoming larger and larger.

In order to confirm the above explanation, we conducted the following tests:

import timeit


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


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


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


def for_loop_with_test(n=100):
    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=10000))
    print('for loop\t\t', timeit.timeit(for_loop, number=10000))
    print('for loop with increment\t\t',
          timeit.timeit(for_loop_with_inc, number=10000))
    print('for loop with test\t\t', timeit.timeit(for_loop_with_test, number=10000))


if __name__ == '__main__':
    main()

Operation results:

# while loop		 0.08734580200689379
# for loop		 0.039982129994314164
# for loop with increment		 0.04891946600400843
# for loop with test		 0.04814562000683509

It can be seen that the results of the test confirm the above conclusion.

Built in function

Still using the above example, there is a built-in function sum() in python to sum. Let's compare the efficiency of sum() and loop.

import timeit


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


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


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


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


if __name__ == '__main__':
    main()

Operation results:

# while loop		 0.052548438994563185
# for loop		 0.0333536260004621
# sum range		 0.00758898000640329

As you can see, sum() performs summation fastest! This is because the sum() function is a built-in function. It loops in c language, so it is more efficient than the previous while and for functions.

Continue to optimize

In order to solve the problem of summation of equal difference sequence, do we have any good methods except rough circulation? If you master basic mathematical knowledge, you can know: S u m ( A n ) = a 1 + a n 2 ∗ n Sum({A_n})=\frac{a_1 + a_n}{2}*n Sum(An) = 2a1 + an * n. let's test the efficiency of direct calculation.

import timeit


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


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


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


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


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


if __name__ == '__main__':
    main()

Operation results:

# while loop		 0.060537102006492205
# for loop		 0.03300404299807269
# sum range		 0.007836175005650148
# math sum		 0.0013752939994446933

The efficiency has been improved again. The reason is obvious. We only need one step to get the results, avoiding thousands of cycles (whether python or c), and the efficiency of the code has naturally reached an unprecedented improvement.

Final conclusion

After the above tests, we have come to the final conclusion: the fastest way to realize the loop is not to use the loop. If you can't completely avoid loops, try to use python's built-in functions and reduce pure python scripts in loops.

Topics: Python Algorithm Back-end