I am trying to optimize further the champion solution in prime number thread by taking out the complex formula for sub-list length. len() of the same subsequence is too slow as len is expensive and generating the subsequence is expensive. This looks to slightly speed up the function but I could not yet take away the division, though I do the division only inside the condition statement. Of course I could try to simplify the length calculation by taking out the optimization of starting marking for n instead of n*n...
I replaced division / by integer division // to be compatible with Python 3 or
from __future__ import division
Also I would be interesting if this recurrence formula could help to speed up the numpy solution, but I have not experience of using numpy much.
If you enable psyco for the code, the story becomes completely different, however and Atkins sieve code becomes faster than this special slicing technique.
import cProfile
def rwh_primes1(n):
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
""" Returns a list of primes < n """
sieve = [True] * (n//2)
for i in xrange(3,int(n**0.5)+1,2):
if sieve[i//2]:
sieve[i*i//2::i] = [False] * ((n-i*i-1)//(2*i)+1)
return [2] + [2*i+1 for i in xrange(1,n/2) if sieve[i]]
def primes(n):
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
# recurrence formula for length by amount1 and amount2 Tony Veijalainen 2010
""" Returns a list of primes < n """
sieve = [True] * (n//2)
amount1 = n-10
amount2 = 6
for i in xrange(3,int(n**0.5)+1,2):
if sieve[i//2]:
## can you make recurrence formula for whole reciprocal?
sieve[i*i//2::i] = [False] * (amount1//amount2+1)
amount1-=4*i+4
amount2+=4
return [2] + [2*i+1 for i in xrange(1,n//2) if sieve[i]]
numprimes=1000000
print('Profiling')
cProfile.Profile.bias = 4e-6
for test in (rwh_primes1, primes):
cProfile.run("test(numprimes)")
Profiling (not so much difference between versions)
3 function calls in 0.191 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.006 0.006 0.191 0.191 <string>:1(<module>)
1 0.185 0.185 0.185 0.185 myprimes.py:3(rwh_primes1)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
3 function calls in 0.192 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.006 0.006 0.192 0.192 <string>:1(<module>)
1 0.186 0.186 0.186 0.186 myprimes.py:12(primes)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
Interestingly by increasing the limit to 10**8 and putting timing decorator to functions removing the profiling:
rwh_primes1 took 23.670 s
primes took 22.792 s
primesieve took 10.850 s
Interestingly if you do not produce list of primes but return the sieve itself the time is around half from number list version.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…