Ho un semplice Sieve of Eratosthanes implementazione come segue:Benchmarking in Python: Perché il mio codice funziona più lentamente con la ripetizione?
# Generate all primes less than k
def sieve(k):
s = [True] * k
s[0] = s[1] = False
for i in range(4, k, 2):
s[i] = False
for i in range(3, int(sqrt(k)) + 2, 2):
if s[i]:
for j in range(i ** 2, k, i * 2):
s[j] = False
return [2] + [ i for i in range(3, k, 2) if s[i] ]
sto benchmarking questo codice generando ripetutamente numeri primi in 10M:
st = time()
for x in range(1000):
rt = time()
sieve(10000000)
print "%3d %.2f %.2f" % (x, time() - rt, (time() - st)/(x + 1))
Sono confuso, come il tempo impiegato per aumenti di funzionamento di prova marcatamente :
run t avg
0 1.49 1.49
1 1.79 1.66
2 2.23 1.85
3 2.72 2.07
4 2.67 2.20
5 2.87 2.31
6 3.05 2.42
7 3.57 2.56
8 3.38 2.65
9 3.48 2.74
10 3.81 2.84
11 3.75 2.92
12 3.85 2.99
13 4.14 3.07
14 4.02 3.14
15 4.05 3.20
16 4.48 3.28
17 4.41 3.34
18 4.19 3.39
19 4.22 3.43
20 4.65 3.49
Tuttavia, cambiando ogni istanza di range
-xrange
elimina il problema:
run t avg
0 1.26 1.26
1 1.23 1.28
2 1.24 1.27
3 1.25 1.26
4 1.23 1.26
5 1.23 1.25
6 1.25 1.25
7 1.25 1.25
8 1.23 1.25
9 1.25 1.25
10 1.24 1.25
Perché è questo il caso? È davvero tutto il sovraccarico di GC? 3x rallenta dopo 20 corse sembra un bel po '...
p.s. ['timeit'] (http://docs.python.org/library/timeit.html) è un modo più semplice per cronometrare il tuo codice. – nneonneo
Non solo la garbage collection, l'allocazione della memoria e tutti questi intervalli. Usare 'range' quando non hai bisogno di una lista è dispendioso. Questo è il motivo per cui il 'range' di Python 3 funziona come' xrange' di Python 2. Quindi, se hai davvero bisogno di una lista, scrivi 'lista (range (n))'. –
Esegue 'gc.collect' dopo ogni aiuto di esecuzione? – nneonneo