Performance testing, how to reduce running time

Asked

Viewed 85 times

2

I want to create a function that returns a list with all the powers of 2 of the numbers from 0 to 99, in the shortest possible time.

So far I have performed 3 tests and my current script is this:

import timeit
import math

lista = [x for x in range(100)]

def powf(x):
    return math.pow(x,2)

def teste1():
    x = list(map(powf, lista))
    return x

def teste2(x):
    x = [powf(x) for x in lista]
    return x    

def teste3(y):
    listareturn = []
    for i in y:
        listareturn.append(powf(i))
    return listareturn

print('teste1')
print(timeit.timeit("teste1()", setup="from __main__ import teste1, lista", number=100000))
print('teste2')
print(timeit.timeit("teste2(lista)", setup="from __main__ import teste2, lista", number=100000))
print('teste3')
print(timeit.timeit("teste3(lista)", setup="from __main__ import teste3, lista", number=100000))

output:

teste1 = 3.0448245999999997
teste2 = 3.2884434
teste3 = 3.5317369999999997

It would be important for me to find more performative ways to write in python.

It is possible to further reduce the execution time of this function ?

  • numpy is very good for calculating in lists

2 answers

3


The fastest way is the one that pushes the complexity of building the list for the compiler or for initialization of the program so that it only needs to be built once.

Look at this:

import timeit
import math

lista = [x for x in range(100)]

def powf(x):
    return math.pow(x,2)

def teste1():
    x = list(map(powf, lista))
    return x

def teste2(x):
    x = [math.pow(x, 2) for x in lista]
    return x    

def teste3(y):
    listareturn = []
    for i in y:
        listareturn.append(powf(i))
    return listareturn

potencias = tuple(2**x for x in range(100))

def teste4():
    return potencias

print('teste1')
print(timeit.timeit("teste1()", setup="from __main__ import teste1, lista", number=100000))
print('teste2')
print(timeit.timeit("teste2(lista)", setup="from __main__ import teste2, lista", number=100000))
print('teste3')
print(timeit.timeit("teste3(lista)", setup="from __main__ import teste3, lista", number=100000))
print('teste4')
print(timeit.timeit("teste4()", setup="from __main__ import teste4, lista", number=100000))
print('indexando')
print(teste4()[50])

The exit on my machine was this:

teste1
12.5717021
teste2
7.806296900000001
teste3
11.117290700000002
teste4
0.019261000000000195
indexando
1125899906842624

Note that the form 4 is much faster than the others, after all, the only thing it does is a return of a fixed tuple.

  • Vitor but how I could visualize and manipulate this object later, since it is being returned a <Generator Object <genexpr> at 0x0000014B02D54E48> ?

  • 1

    @So it depends what you want to do with it later. Any measurement of performance is only valid if the context in which what is measured is taken into account, as certain optimizations may or may not be valid in that context. You have not explained in your question what is the context in which you want to use this list.

  • I cannot refute this, you are right. But there is a way to access the result of Index 50 with this method ?

  • @Filipegonçalves I edited the code and reread the test to be able to index and demonstrate how to do.

  • Victor got much faster and 100% functional for what I needed. Please edit your reply and change the formula of the potentials variable to x**2, and also check the time you put in the last test pq here on my machine I got in 0.00858150000000002 much smaller than the others already in your answer apparently this was the slowest procedure.

  • @Filipegonçalves O 0.019261000000000195 is the time of teste4, very fast than everyone else. Already the 1125899906842624 is just the result of using print(teste4()[50]).

Show 1 more comment

1

Browser other questions tagged

You are not signed in. Login or sign up in order to post.