Skip to content

Instantly share code, notes, and snippets.

@Rhomboid
Created November 30, 2013 08:45
Show Gist options
  • Select an option

  • Save Rhomboid/7716724 to your computer and use it in GitHub Desktop.

Select an option

Save Rhomboid/7716724 to your computer and use it in GitHub Desktop.
Python number sieve performance comparison
# http://projecteuler.net/problem=7 (should print 104743)
from operator import itemgetter
from timeit import repeat
def ver1(n):
'''Original, baseline version that uses a dict'''
eratosthenes = dict.fromkeys(range(2, n), True)
for i in range(2, n):
if eratosthenes[i]:
for j in range(i**2, n, i):
eratosthenes[j] = False
prime_list = eratosthenes.items()
filtered_prime_list = []
for tuple in prime_list:
if tuple[1]:
filtered_prime_list.append(tuple[0])
return filtered_prime_list
def ver2(n):
'''Use a list instead of a dict, and build primes list as you go'''
sieve = [True] * n
primes = []
for i in range(2, n):
if sieve[i]:
primes.append(i)
sieve[i * 2::i] = (False,) * ((n - i - 1) // i)
return primes
def ver3(n):
'''Use list.index to find next prime'''
sieve = [True] * n
primes = []
i = 1
while True:
try:
i = sieve.index(True, i + 1)
except ValueError:
return primes
primes.append(i)
sieve[i * 2::i] = (False,) * ((n - i - 1) // i)
def ver4(n):
'''Use bytearray.index to find next prime'''
sieve = bytearray(b'1' * n)
primes = []
i = 1
while True:
try:
i = sieve.index(b'1', i + 1)
except ValueError:
return primes
primes.append(i)
sieve[i * 2::i] = b'0' * ((n - i - 1) // i)
def ver5(n):
'''Use list.index and only store odd numbers'''
n //= 2
sieve = [True] * n
primes = [2]
i = 0
while True:
try:
i = sieve.index(True, i + 1)
except ValueError:
return primes
p = 2 * i + 1
primes.append(p)
sieve[i + p::p] = (False,) * ((n - i - 1) // p)
def ver6(n):
'''Use bytearray.index and only store odd numbers'''
n //= 2
sieve = bytearray(b'1' * n)
primes = [2]
i = 0
while True:
try:
i = sieve.index(b'1', i + 1)
except ValueError:
return primes
p = 2 * i + 1
primes.append(p)
sieve[i + p::p] = b'0' * ((n - i - 1) // p)
repcnt = 25
funcs = [{'name': name, 'func': func} for name, func in globals().items() if name.startswith('ver')]
for f in funcs:
primes = f['func'](105000)
assert primes[10000] == 104743 and len(primes) == 10024
f['elap'] = min(repeat('{}(105000)'.format(f['name']), 'from __main__ import {}'.format(f['name']), repeat=5, number=repcnt)) / repcnt
slowest = max(f['elap'] for f in funcs)
print('{:10} {:65} {:>8} {:>8}'.format('function', 'description', 'elapsed', 'speedup'))
for f in sorted(funcs, key=itemgetter('elap'), reverse=True):
print('{:10} {:65} {:8.6f} {:7.2f}x'.format(f['name'], f['func'].__doc__, f['elap'], slowest / f['elap']))
# python 3.3.3, Windows x86
function description elapsed speedup
ver1 Original, baseline version that uses a dict 0.047903 1.00x
ver6 Use bytearray.index and only store odd numbers 0.017016 2.82x
ver4 Use bytearray.index to find next prime 0.016434 2.91x
ver2 Use a list instead of a dict, and build primes list as you go 0.014152 3.38x
ver3 Use list.index to find next prime 0.012595 3.80x
ver5 Use list.index and only store odd numbers 0.010860 4.41x
# python 2.7.5, Windows x86
function description elapsed speedup
ver1 Original, baseline version that uses a dict 0.056467 1.00x
ver2 Use a list instead of a dict, and build primes list as you go 0.012120 4.66x
ver3 Use list.index to find next prime 0.010797 5.23x
ver6 Use bytearray.index and only store odd numbers 0.010267 5.50x
ver5 Use list.index and only store odd numbers 0.009742 5.80x
ver4 Use bytearray.index to find next prime 0.009481 5.96x
# python 3.3.3, Windows x86_64
function description elapsed speedup
ver1 Original, baseline version that uses a dict 0.048371 1.00x
ver6 Use bytearray.index and only store odd numbers 0.019052 2.54x
ver4 Use bytearray.index to find next prime 0.018135 2.67x
ver2 Use a list instead of a dict, and build primes list as you go 0.012787 3.78x
ver3 Use list.index to find next prime 0.012775 3.79x
ver5 Use list.index and only store odd numbers 0.010947 4.42x
# python 2.7.5, Windows x86_64
function description elapsed speedup
ver1 Original, baseline version that uses a dict 0.061123 1.00x
ver2 Use a list instead of a dict, and build primes list as you go 0.011829 5.17x
ver3 Use list.index to find next prime 0.011191 5.46x
ver5 Use list.index and only store odd numbers 0.008613 7.10x
ver6 Use bytearray.index and only store odd numbers 0.008473 7.21x
ver4 Use bytearray.index to find next prime 0.008438 7.24x
# python 2.7.2, Linux x86_64
function description elapsed speedup
ver1 Original, baseline version that uses a dict 0.048277 1.00x
ver2 Use a list instead of a dict, and build primes list as you go 0.010998 4.39x
ver3 Use list.index to find next prime 0.008768 5.51x
ver6 Use bytearray.index and only store odd numbers 0.008062 5.99x
ver4 Use bytearray.index to find next prime 0.007823 6.17x
ver5 Use list.index and only store odd numbers 0.007440 6.49x
# python 3.2.2, Linux x86_64
function description elapsed speedup
ver1 Original, baseline version that uses a dict 0.033647 1.00x
ver6 Use bytearray.index and only store odd numbers 0.011535 2.92x
ver4 Use bytearray.index to find next prime 0.011267 2.99x
ver2 Use a list instead of a dict, and build primes list as you go 0.008681 3.88x
ver3 Use list.index to find next prime 0.008213 4.10x
ver5 Use list.index and only store odd numbers 0.006904 4.87x
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment